Skip to content

Commit

Permalink
Merge branch 'main' into simple_storage
Browse files Browse the repository at this point in the history
  • Loading branch information
liamhuber committed Jan 18, 2024
2 parents 7777c34 + cc93042 commit c0ae035
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 0 deletions.
31 changes: 31 additions & 0 deletions pyiron_workflow/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,9 @@ class Node(HasToDict, ABC, metaclass=AbstractHasPost):
owning this, if any.
ready (bool): Whether the inputs are all ready and the node is neither
already running nor already failed.
graph_path (str): The file-path-like path of node labels from the parent-most
node down to this node.
graph_root (Node): The parent-most node in this graph.
run_args (dict): **Abstract** the argmuments to use for actually running the
node. Must be specified in child classes.
running (bool): Whether the node has called :meth:`run` and has not yet
Expand Down Expand Up @@ -224,6 +227,7 @@ class Node(HasToDict, ABC, metaclass=AbstractHasPost):
"""

package_identifier = None
_semantic_delimiter = "/"

_STORAGE_FILE_NAME = "project.h5"
# This isn't nice, just a technical necessity in the current implementation
Expand All @@ -250,6 +254,7 @@ def __init__(
**kwargs: Keyword arguments passed on with `super`.
"""
super().__init__(*args, **kwargs)
self._label = None
self.label: str = label
self._parent = None
if parent is not None:
Expand Down Expand Up @@ -303,6 +308,16 @@ def __post__(
except ReadinessError:
pass

@property
def label(self) -> str:
return self._label

@label.setter
def label(self, new_label: str):
if self._semantic_delimiter in new_label:
raise ValueError(f"{self._semantic_delimiter} cannot be in the label")
self._label = new_label

@property
@abstractmethod
def inputs(self) -> Inputs:
Expand Down Expand Up @@ -353,6 +368,22 @@ def parent(self, new_parent: Composite | None) -> None:
"parent"
)

@property
def graph_path(self) -> str:
"""
The path of node labels from the graph root (parent-most node) down to this
node.
"""
path = self.label
if self.parent is not None:
path = self.parent.graph_path + self._semantic_delimiter + path
return path

@property
def graph_root(self) -> Node:
"""The parent-most node in this graph."""
return self if self.parent is None else self.parent.graph_root

@property
def readiness_report(self) -> str:
input_readiness = "\n".join(
Expand Down
62 changes: 62 additions & 0 deletions tests/unit/test_composite.py
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,68 @@ def test_de_activate_strict_connections(self):
msg="Activating should propagate to children"
)

def test_graph_info(self):
top = AComposite("topmost")
top.middle_composite = AComposite("middle_composite")
top.middle_composite.deep_node = Composite.create.SingleValue(plus_one)
top.middle_function = Composite.create.SingleValue(plus_one)

with self.subTest("test_graph_path"):
self.assertEqual(
top.label,
top.graph_path,
msg="The parent-most node should be its own path."
)
self.assertEqual(
Composite._semantic_delimiter.join(
[top.label, top.middle_composite.label]
),
top.middle_composite.graph_path,
msg="The path should go to the parent-most object."
)
self.assertEqual(
Composite._semantic_delimiter.join(
[top.label, top.middle_function.label]
),
top.middle_function.graph_path,
msg="The path should go to the parent-most object."
)
self.assertEqual(
Composite._semantic_delimiter.join(
[
top.label,
top.middle_composite.label,
top.middle_composite.deep_node.label
]
),
top.middle_composite.deep_node.graph_path,
msg="The path should go to the parent-most object, recursively from all "
"depths."
)

with self.subTest("test_graph_root"):
self.assertIs(
top,
top.graph_root,
msg="The parent-most node should be its own graph_root."
)
self.assertIs(
top,
top.middle_composite.graph_root,
msg="The parent-most node should be the graph_root."
)
self.assertIs(
top,
top.middle_function.graph_root,
msg="The parent-most node should be the graph_root."
)
self.assertIs(
top,
top.middle_composite.deep_node.graph_root,
msg="The parent-most node should be the graph_root, recursively accessible "
"from all depths."
)


if __name__ == '__main__':
unittest.main()
17 changes: 17 additions & 0 deletions tests/unit/test_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,23 @@ def test_run_after_init(self):
msg="With run_after_init, the node should run right away"
)

def test_graph_info(self):
n = ANode("n")

self.assertEqual(
n.label,
n.graph_path,
msg="Lone nodes should just have their label as the path, as there is no "
"parent above."
)

self.assertIs(
n,
n.graph_root,
msg="Lone nodes should be their own graph_root, as there is no parent "
"above."
)


if __name__ == '__main__':
unittest.main()

0 comments on commit c0ae035

Please sign in to comment.