Shelves (Node Library Groups)¶
Shelves are the catalog entries that tell FuncNodes which node classes are available and how they are grouped in the UI. A shelf is a small tree that contains node classes (funcnodes_core.node.Node) and optional subshelves.
Structure¶
- Data model:
funcnodes_core.lib.Shelfholdsname,description,nodes(list of node classes), andsubshelves(list of Shelves). Each shelf gets a generatedshelf_idwhen validated. - Serialization: Shelves serialize to JSON via
funcnodes_core.lib.serialize_shelf, emittingname,description,nodes(serialized node classes), and nestedsubshelves. - Storage: The runtime keeps a flat registry (
funcnodes_core.lib.Library) keyed by tuple paths (("Top", "Child", ...)) for GC‑friendly storage. Complete shelf trees are materialized on demand.
How shelves are discovered¶
FuncNodes loads shelves from installed Python packages via the funcnodes.module entry point group:
- If a distribution exposes
shelf = "<pkg>:<object>"underproject.entry-points."funcnodes.module", that object is read and validated withfuncnodes_core.lib.check_shelf. Dictionaries are accepted and converted toShelfinstances. - If no
shelfentry point is present, FuncNodes falls back to introspection: every non‑abstract subclass ofNodedefined in the module is collected into a shelf named after the module (funcnodes_core.lib.libparser.module_to_shelf). - Additional optional entry points (
render_options,external_worker,plugin_setup) may also be exported; they are processed in_setup.pybut do not affect shelf discovery itself.
Example (from modules/funcnodes_files/pyproject.toml):
[project.entry-points."funcnodes.module"]
module = "funcnodes_files"
shelf = "funcnodes_files:NODE_SHELF"
react_plugin = "funcnodes_files:REACT_PLUGIN"
Here NODE_SHELF is the authoritative shelf object; the React plugin entry point is consumed by the UI host but does not change the shelf tree.
How shelves are mounted at runtime¶
- The Workermanager/Worker loads installed modules, parses their entry points, and registers shelves into a
Libraryinstance attached to eachNodeSpace. Library.add_shelfmerges shelves by path, keeping node IDs unique per shelf. External shelves can be mounted via weak references (add_external_shelf,add_subshelf_weak) so they disappear automatically when their owner is GC’d.- Finding nodes is path‑aware:
Library.find_nodeidreturns all shelf paths containing a node ID, andget_node_by_idonly succeeds if the node is both registered and referenced by at least one shelf.
Authoring guidance for module writers¶
- Export a
Shelf(or dict convertible to one) through thefuncnodes.moduleentry point to get precise grouping and descriptions. - Ensure each node class has a globally unique
node_id; shelves store only node IDs, so duplicates are skipped when the Library deduplicates. - Organize subshelves for UI grouping—paths are preserved (
["Vision", "Filters", ...]) and rendered as nested menus in the editor host.