Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions notebooks/deepdive.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
}
},
"source": [
"import pyiron_workflow as pwf"
"import pyiron_workflow as pwf\n",
"import pyiron_workflow.data"
],
"outputs": [],
"execution_count": 81
Expand Down Expand Up @@ -293,7 +294,7 @@
" _output_labels = (\"plus\", \"minus\")\n",
"\n",
" def is_bound(self, n) -> bool:\n",
" if self.outputs.plus.value is not pwf.api.NOT_DATA:\n",
" if self.outputs.plus.value is not pyiron_workflow.data.NOT_DATA:\n",
" return self.outputs.plus.value > n and self.outputs.minus.value < n\n",
" else:\n",
" raise RuntimeError(\"Run the node first\")\n",
Expand Down Expand Up @@ -1178,7 +1179,7 @@
"source": [
"i2d = pwf.api.inputs_to_dict(\n",
" input_specification={\n",
" \"x\": (None, pwf.api.NOT_DATA),\n",
" \"x\": (None, pyiron_workflow.data.NOT_DATA),\n",
" \"y\": (int, 42)\n",
" }\n",
")\n",
Expand Down Expand Up @@ -1628,7 +1629,7 @@
"start_time": "2025-08-13T22:35:56.546690Z"
}
},
"source": "assert(pwf.std.UserInput().inputs.user_input.value is pwf.api.NOT_DATA)",
"source": "assert(pwf.std.UserInput().inputs.user_input.value is pyiron_workflow.data.NOT_DATA)",
"outputs": [],
"execution_count": 120
},
Expand Down
2 changes: 1 addition & 1 deletion pyiron_workflow/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"""

# Node developer entry points
from pyiron_workflow.channels import NOT_DATA
from pyiron_workflow.data import NOT_DATA
from pyiron_workflow.executors import CloudpickleProcessPoolExecutor, NodeSlurmExecutor
from pyiron_workflow.find import (
find_nodes as _find_nodes, # Not formally in API -- don't rely on interface
Expand Down
26 changes: 1 addition & 25 deletions pyiron_workflow/channels.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@
import typing
from abc import ABC, abstractmethod

from pyiron_snippets.singleton import Singleton

from pyiron_workflow.data import NOT_DATA
from pyiron_workflow.mixin.display_state import HasStateDisplay
from pyiron_workflow.mixin.has_interface_mixins import HasChannel, HasLabel
from pyiron_workflow.type_hinting import (
Expand Down Expand Up @@ -304,29 +303,6 @@ class OutputChannel(Channel[InputType], ABC):
"""Mixin for output channels."""


class NotData(metaclass=Singleton):
"""
This class exists purely to initialize data channel values where no default value
is provided; it lets the channel know that it has _no data in it_ and thus should
not identify as ready.
"""

@classmethod
def __repr__(cls):
# We use the class directly (not instances of it) where there is not yet data
# So give it a decent repr, even as just a class
return "NOT_DATA"

def __reduce__(self):
return "NOT_DATA"

def __bool__(self):
return False


NOT_DATA = NotData()


class DataChannel(FlavorChannel["DataChannel"], typing.Generic[ReceiverType], ABC):
"""
Data channels control the flow of data on the graph.
Expand Down
26 changes: 26 additions & 0 deletions pyiron_workflow/data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from __future__ import annotations

from pyiron_snippets.singleton import Singleton


class NotData(metaclass=Singleton):
"""
This class exists purely to initialize data channel values where no default value
is provided; it lets the channel know that it has _no data in it_ and thus should
not identify as ready.
"""

@classmethod
def __repr__(cls):
# We use the class directly (not instances of it) where there is not yet data
# So give it a decent repr, even as just a class
return "NOT_DATA"

def __reduce__(self):
return "NOT_DATA"

def __bool__(self):
return False


NOT_DATA = NotData()
4 changes: 2 additions & 2 deletions pyiron_workflow/draw.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import graphviz
from pyiron_snippets.colors import SeabornColors

from pyiron_workflow.channels import NotData
from pyiron_workflow.data import NOT_DATA

if TYPE_CHECKING:
from pyiron_workflow.channels import Channel as WorkflowChannel # noqa: F401
Expand Down Expand Up @@ -198,7 +198,7 @@ def shape(self) -> str:

@property
def style(self) -> str:
if len(self.channel.connections) == 0 and self.channel.value is NotData():
if len(self.channel.connections) == 0 and self.channel.value is NOT_DATA:
return "bold"
return "filled"

Expand Down
3 changes: 2 additions & 1 deletion pyiron_workflow/mixin/injection.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
import abc
from typing import TYPE_CHECKING, Any

from pyiron_workflow.channels import NOT_DATA, OutputData
from pyiron_workflow.channels import OutputData
from pyiron_workflow.data import NOT_DATA
from pyiron_workflow.io import GenericOutputs
from pyiron_workflow.mixin.has_interface_mixins import HasChannel

Expand Down
2 changes: 1 addition & 1 deletion pyiron_workflow/mixin/preview.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

from pyiron_snippets.dotdict import DotDict

from pyiron_workflow.channels import NOT_DATA
from pyiron_workflow.data import NOT_DATA
from pyiron_workflow.logging import logger
from pyiron_workflow.output_parser import ParseOutput

Expand Down
2 changes: 1 addition & 1 deletion pyiron_workflow/nodes/for_loop.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from pandas import DataFrame
from pyiron_snippets.factory import classfactory

from pyiron_workflow.channels import NOT_DATA
from pyiron_workflow.data import NOT_DATA
from pyiron_workflow.mixin.run import InterpretableAsExecutor
from pyiron_workflow.nodes.composite import Composite
from pyiron_workflow.nodes.static_io import StaticNode
Expand Down
3 changes: 2 additions & 1 deletion pyiron_workflow/nodes/standard.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
from pathlib import Path
from time import sleep

from pyiron_workflow.channels import NOT_DATA, OutputSignal
from pyiron_workflow.channels import OutputSignal
from pyiron_workflow.data import NOT_DATA
from pyiron_workflow.nodes.function import Function, as_function_node


Expand Down
2 changes: 1 addition & 1 deletion pyiron_workflow/nodes/transform.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from pyiron_snippets.factory import classfactory

from pyiron_workflow import identifier
from pyiron_workflow.channels import NOT_DATA, NotData
from pyiron_workflow.data import NOT_DATA, NotData
from pyiron_workflow.nodes.static_io import StaticNode


Expand Down
5 changes: 4 additions & 1 deletion tests/cluster/slurm_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@
import time

import pyiron_workflow as pwf
import pyiron_workflow.data
from pyiron_workflow.executors.wrapped_executorlib import NodeSlurmExecutor

t_overhead = 2
t_sleep = 10


def state_check(wf, expected_wf, expected_n2, expected_result=pwf.api.NOT_DATA):
def state_check(
wf, expected_wf, expected_n2, expected_result=pyiron_workflow.data.NOT_DATA
):
wf_running, n_running, outputs = (
wf.running,
wf.n2.running,
Expand Down
3 changes: 2 additions & 1 deletion tests/integration/test_workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
from static import demo_nodes

from pyiron_workflow._tests import ensure_tests_in_python_path
from pyiron_workflow.channels import NOT_DATA, OutputSignal
from pyiron_workflow.channels import OutputSignal
from pyiron_workflow.data import NOT_DATA
from pyiron_workflow.nodes.composite import FailedChildError
from pyiron_workflow.nodes.function import Function
from pyiron_workflow.workflow import Workflow
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/mixin/test_preview.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from pyiron_snippets.factory import classfactory

from pyiron_workflow.channels import NOT_DATA
from pyiron_workflow.data import NOT_DATA
from pyiron_workflow.logging import logger
from pyiron_workflow.mixin.preview import ScrapesIO, no_output_validation_warning

Expand Down
2 changes: 1 addition & 1 deletion tests/unit/nodes/test_composite.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from static import demo_nodes

from pyiron_workflow._tests import ensure_tests_in_python_path
from pyiron_workflow.channels import NOT_DATA
from pyiron_workflow.data import NOT_DATA
from pyiron_workflow.io import Inputs
from pyiron_workflow.mixin.injection import OutputsWithInjection
from pyiron_workflow.nodes.composite import Composite
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/nodes/test_function.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import numpy as np

from pyiron_workflow.channels import NOT_DATA
from pyiron_workflow.data import NOT_DATA
from pyiron_workflow.node import (
Node as NonBuiltinTypeHint,
)
Expand Down
9 changes: 5 additions & 4 deletions tests/unit/nodes/test_macro.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from static import demo_nodes

import pyiron_workflow.data
from pyiron_workflow import channels
from pyiron_workflow._tests import ensure_tests_in_python_path
from pyiron_workflow.mixin import injection
Expand Down Expand Up @@ -148,7 +149,7 @@ def test_creation_from_decorator(self):

self.assertIs(
m.outputs.three__result.value,
channels.NOT_DATA,
pyiron_workflow.data.NOT_DATA,
msg="Output should be accessible with the usual naming convention, but we "
"have not run yet so there shouldn't be any data",
)
Expand Down Expand Up @@ -221,7 +222,7 @@ def test_with_executor(self):
macro.executor = futures.ProcessPoolExecutor()

self.assertIs(
channels.NOT_DATA,
pyiron_workflow.data.NOT_DATA,
macro.outputs.three__result.value,
msg="Sanity check that test is in right starting condition",
)
Expand All @@ -231,7 +232,7 @@ def test_with_executor(self):
result, futures.Future, msg="Should be running as a parallel process"
)
self.assertIs(
channels.NOT_DATA,
pyiron_workflow.data.NOT_DATA,
downstream.outputs.result.value,
msg="Downstream events should not yet have triggered either, we should wait"
"for the callback when the result is ready",
Expand Down Expand Up @@ -657,7 +658,7 @@ def DoesntAutoloadChildren(self, x):

self.assertIs(
DoesntAutoloadChildren().some_child.outputs.x.value,
channels.NOT_DATA,
pyiron_workflow.data.NOT_DATA,
msg="Despite having the same label as a saved node at instantiation time, "
"without autoloading children, our macro safely gets a fresh instance. "
"Since this is clearly preferable, here we leave autoload to take its "
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/nodes/test_transform.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from pandas import DataFrame

from pyiron_workflow.channels import NOT_DATA
from pyiron_workflow.data import NOT_DATA
from pyiron_workflow.nodes.function import as_function_node
from pyiron_workflow.nodes.transform import (
Transformer,
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/test_channels.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import unittest

from pyiron_workflow.channels import (
NOT_DATA,
AccumulatingInputSignal,
BadCallbackError,
Channel,
Expand All @@ -16,6 +15,7 @@
OutputSignal,
TooManyConnectionsError,
)
from pyiron_workflow.data import NOT_DATA


class DummyParent:
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/test_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
import bagofholding as boh

from pyiron_workflow.channels import (
NOT_DATA,
InputData,
InputLockedError,
)
from pyiron_workflow.data import NOT_DATA
from pyiron_workflow.io import Inputs
from pyiron_workflow.mixin.injection import (
OutputDataWithInjection,
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/test_workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from static import demo_nodes

from pyiron_workflow._tests import ensure_tests_in_python_path
from pyiron_workflow.channels import NOT_DATA
from pyiron_workflow.data import NOT_DATA
from pyiron_workflow.storage import TypeNotFoundError, available_backends
from pyiron_workflow.workflow import NoArgsError, ParentMostError, Workflow

Expand Down
Loading