Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Node constructor #497

Open
XzzX opened this issue Nov 20, 2024 · 3 comments
Open

Node constructor #497

XzzX opened this issue Nov 20, 2024 · 3 comments
Labels
question Further information is requested

Comments

@XzzX
Copy link
Contributor

XzzX commented Nov 20, 2024

Regardless of the way I write a node, it always has a __init__ function that takes no required arguments and all optional arguments are used to set default values for inputs?

@XzzX XzzX added enhancement New feature or request question Further information is requested and removed enhancement New feature or request labels Nov 20, 2024
@liamhuber
Copy link
Member

takes no required arguments

Almost always -- the one exception is instantiating a Workflow, which currently overrides Node.__init__ so that the label is required. The reason for this is not technical, but UX. On the technical side we want each node to have a unique label inside its semantic scope (i.e. in the ownership tree, two nodes with the same owner must not have the same label). We take care of this by auto-generating labels based on the node class, and if there's already a node with this name we either adding a suffix index (if we're feeling relaxed (Composite.strict_naming = False)) or raise an exception if we're feeling strict. So, in principle we could just be lazy and do wf = Workflow() such that wf.label is "Workflow". Since this is a super common object for users to save and load (and auto-load on instantiation when a file matching the label is found...), we force the user to think of a name for each new parent-most workflow, while for other nodes we are content to rely on the auto-generated name. This is also familiar as the old from pyiron_base import Project; pr = Project("my_pyiron_project") pattern.

and all optional arguments are used to set default values for inputs

Optional arguments are indeed used to set default values for inputs, but not necessarily all of them -- nodes also come with their own kwargs that can be set at instantiation. When you're making Function (or Macro) nodes, you'll get a nice error if you try to do something where the node input would conflict with an existing keyword:

import pyiron_workflow as pwf

@pwf.as_function_node
def my_bad_io(label):
    return label

>>> ValueError: Trying to build input preview for my_bad_io, encountered an argument name that conflicts with __init__: label. Please choose a name _not_ among ['self', 'args', 'label', 'parent', 'delete_existing_savefiles', 'autoload', 'autorun', 'checkpoint', 'kwargs']

Both Function and Macro nodes work this way, where their IO is defined by inspecting some function. They inherit from a shared mixin ScrapesIO which handles building class-level previews of what the IO will look like based on the function in being inspected, so the list of protected argument names and its comparison to the inspected function signature is all automated here:

def _build_inputs_preview(cls):

@XzzX
Copy link
Contributor Author

XzzX commented Nov 22, 2024

I can use node.semantic_path to uniquely identify a node?

@liamhuber
Copy link
Member

Within the scope of its ownership graph, yes. I could have two node objects in memory in a single python session that have the same semantic_path (this is just a string), but not in the same graph. There is one nasty exception to this where we [don't have guardrails stopping a user from mucking up the labels manually](#431

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants