While implementing caching for components, I did some cleanup. Despite
the fact that subgraph caching is put on hold for now (in favor of a
larger cache refactor later), these are the changes that I think are
worth keeping anyway.
* Makes subgraph node IDs deterministic
* Allows usage of the topological sort without execution
* Tracks parent nodes (i.e. those that caused a node to be created) and
display nodes (i.e. the one we want to highlight while an ephemeral
node is executing) separately.
Execution blocking can be done by returning an `ExecutionBlocker`
(imported from graph_utils) either in place of results or as a specific
output. Any node that uses an `ExecutionBlocker` as input will be
skipped. This operates on a per-entry basis when inputs are lists.
If the `ExecutionBlocker` is initialized with an error message, that
message will be displayed on the first node it's used on (and further
downstream nodes will be silently skipped).
Honestly, I'm still a little concerned here. There's nothing stopping a
custom node from having a data type of ["str",int]. I've improved
recognition to at least prevent the detection of other types, but we
may still want a more systemic fix (e.g. wrapping literals within a
class when using them as inputs to nodes in subgraphs).
Note that For loops still require WAS-ns. They just expand to using the
integer operation node internally.
Also adds some nodes for accumulation operations.
Previously, nodes that were connected to output nodes only via optional
inputs were never validated, but were still run. This would cause a
Python error and stop execution wherever we happen to be in the
execution list. This bug exists on master, but may be more noticeable in
this branch because execution order is non-deterministic.
Other minor change this commit introduces: `raw_link` can be specified
as an option on an input to receive the raw link (in the standard form
of [node_id, output_index]) rather than a resolved value.