leon-thomm / ryvencore Goto Github PK
View Code? Open in Web Editor NEWNode editor Python backend
Home Page: https://leon-thomm.github.io/ryvencore/
License: GNU Lesser General Public License v2.1
Node editor Python backend
Home Page: https://leon-thomm.github.io/ryvencore/
License: GNU Lesser General Public License v2.1
main: should generally be working.
dev: is used for development and is expected to have breaking or incomplete changes.
v*: used for commits dedicated to specific legacy versions.
publishing pypi packages
New PyPI releases are published by creating a git tag, e.g.
git tag v0.4.0a9
git push v0.4.0a9
and then see Actions tab on GitHub
Feel free to suggest changes.
Hi @leon-thomm, I've been using ryvencore over on ironflow to build a jupyter-based gui to drive for our project pyiron and I'm absolutely loving it.
I discovered that the default values in the initial input channels were not being used. In addition to the dtypes, where default
is actively solicited in the initializer, I thought it might be nice to allow specifying defaults for non-typed input using add_data['val']
.
A MWE example is below with a little fix to put in NodeInput.__init__
if you'd like. I'd be happy to make a PR, but when I forked the repo I discovered that main here is way out of date compared to the conda-forge installation (v0.3.1.1). NodeInput.__init__
doesn't even take a dtypes: Dtypes = None
kwarg. Where is the more up-to-date code coming from? The only branch ahead of main here doesn't have it, and unfortunately I don't have permissions to dig into the conda feedstock source to look there.
MWE:
import ryvencore as rc
class MyNode(rc.Node):
title = 'mwe'
init_inputs = [
rc.NodeInputBP(type_='data', add_data={'val': 'towel'}), # Without dtype
rc.NodeInputBP(type_='data', dtype=rc.dtypes.Integer(default=42))
]
def place_event(self):
super().place_event()
print(f"{self.__class__.__name__} got placed")
session = rc.Session()
session.register_node(MyNode)
script = session.create_script(title='mwe')
node = script.flow.create_node(MyNode)
print("Initialized?", node.initialized)
print("Values after initialization:", node.input(0), node.input(1))
def set_defaults(node_input):
"""Something like could be added to NodeInput.__init__"""
if node_input.dtype is not None:
node_input.update(node_input.dtype.default)
elif 'val' in node_input.add_data.keys():
node_input.update(node_input.add_data['val'])
set_defaults(node.inputs[0])
set_defaults(node.inputs[1])
print("Values after setting defaults:", node.input(0), node.input(1))
>>> MyNode got placed
>>> Initialized? True
>>> Values after initialization: None None
>>> Values after setting defaults: towel 42
edited for hyperlinks
In the documentation of ryvencore, there is an example of Data flow.
It does not work as is. May I suggest the following code that implements the registration of the node in the session before using them?
import ryvencore as rc
class Producer(rc.Node):
init_outputs = [rc.NodeOutputType()]
def push_data(self, d):
self.d = d
self.update()
def update_event(self, inp=-1):
self.set_output_val(0, self.d)
class Consumer(rc.Node):
init_inputs = [rc.NodeInputType()]
def update_event(self, inp=-1):
p = self.input(0).payload
p.append(4)
print(p)
def build_and_run(D):
s = rc.Session()
s.register_node(Producer)
s.register_node(Consumer)
f = s.create_flow('main')
producer = f.create_node(Producer)
consumer1 = f.create_node(Consumer)
consumer2 = f.create_node(Consumer)
f.connect_nodes(producer.outputs[0], consumer1.inputs[0])
f.connect_nodes(producer.outputs[0], consumer2.inputs[0])
return producer.push_data(D)
build_and_run(rc.Data([1,2,3]))
When trying to create a node but not using a node that what previously register, the program prints a message but does not output an error. Thus the program fails at a later stage making it harder to debug.
In the following example, we want to create a node 'Producer' (string) which fails (we should use the class directly) but only creates an error 3 lines later.
import ryvencore as rc
class Producer(rc.Node):
init_outputs = [rc.NodeOutputType()]
def push_data(self, d):
self.d = d
self.update()
def update_event(self, inp=-1):
self.set_output_val(0, self.d)
class Consumer(rc.Node):
init_inputs = [rc.NodeInputType()]
def update_event(self, inp=-1):
p = self.input(0).payload
p.append(4)
print(p)
def build_and_run(D):
s = rc.Session()
s.register_node(Producer)
s.register_node(Consumer)
f = s.create_flow('main')
producer = f.create_node('Producer')
consumer1 = f.create_node(Consumer)
consumer2 = f.create_node(Consumer)
f.connect_nodes(producer.outputs[0], consumer1.inputs[0])
f.connect_nodes(producer.outputs[0], consumer2.inputs[0])
return producer.push_data(D)
build_and_run(rc.Data([1,2,3]))
Error message
Node class Producer not in session nodes
On ryvencore 0.3.1.1.
By using mutable defaults, multiple input channels can impact each other. MWE:
import ryvencore as rc
l1 = rc.NodeInputBP(type_='data', dtype=rc.dtypes.List())
l2 = rc.NodeInputBP(type_='data', dtype=rc.dtypes.List())
l2.dtype.val.append('bar')
print(l2.dtype.default, l1.dtype.val, l1.dtype.default)
c1 = rc.NodeInputBP(type_='data', dtype=rc.dtypes.Choice())
c2 = rc.NodeInputBP(type_='data', dtype=rc.dtypes.Choice())
c2.dtype.items.append(str)
print(c1.dtype.items)
>>> ['bar'] ['bar'] ['bar']
>>> [<class 'str'>]
If I'm correctly understanding the typical use cases of dtypes, I can't imagine it's very likely someone would come in and mutate things like this, but I guess it's possible someone tries to get clever and update the items available to a choice and winds up updating more choices than they meant to. Adding the pattern self.items = items if items is not None else []
and changing the signature to items = None
should clean it up (and similar for List
and default
), so even if it's unlikely to be problematic the fix is easy.
This is really weird.
When trying to undo a paste command with a DrawingObject
as content, the error from the title appears in the console. In several attempts, I have been able to locate the crash, but not the source for this
def remove_drawing(self, drawing: DrawingObject):
"""Removes a drawing from the scene."""
self.scene().removeItem(drawing)
self.drawings.remove(drawing)
This method of FlowView
does execute completely, however self.scene().removeItem(drawing)
seems to have no effect. The debugger always crashes without error description anywhere in this method when undoing a paste command. I then tried to get more information using simple print statement but even things like this (!!):
def remove_drawing(self, drawing: DrawingObject):
"""Removes a drawing from the scene."""
print(drawing)
# self.scene().removeItem(drawing)
# self.drawings.remove(drawing)
results in a debugger crash when I try to break at the print line. I could not find any redefinitions of the word and methods str
or print
in any files, including the DrawingObject
. I also don't overwrite builtin methods in DrawingObject
.
It completely breaks the undo of the paste command (removing), however it doesn't break the delete command, which doesn't make any sense to me. The error is also printed when moving DrawingObject
s. I've no idea what to do with this...
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.