"""Check the saved library's public inventory and persistence.""" import bpy import pytest from anyimage.common.node import load_node_group, node_asset_path from tools.nodes.check import GEOMETRY_NAMES, SHADER_NAMES def test_saved_asset_inventory(): bpy.ops.wm.read_factory_settings(use_empty=True) with bpy.data.libraries.load(str(node_asset_path())) as (source, _): assert set(source.node_groups) == GEOMETRY_NAMES | SHADER_NAMES for name in sorted(GEOMETRY_NAMES | SHADER_NAMES): bpy.ops.wm.read_factory_settings(use_empty=True) node_group = load_node_group(name) assert node_group.bl_idname == ("GeometryNodeTree" if name in GEOMETRY_NAMES else "ShaderNodeTree") assert node_group.use_fake_user and node_group.users > 0 if name in GEOMETRY_NAMES: assert node_group.is_modifier if bpy.app.version >= (5, 0, 0): assert node_group.library is not None if name in {"O Image Depth Layer", "O Shadeless"}: expected = ["Color", "Alpha", "Depth", "Bump Scale"] if name == "O Image Depth Layer" else ["Color", "Alpha"] assert [item.name for item in node_group.interface.items_tree if item.item_type == "SOCKET" and item.in_out == "INPUT"] == expected @pytest.mark.parametrize("source", ["definition", "asset"]) def test_geometry_attribute_contract_includes_nested_groups(source): from tools.nodes.build import build_node_groups bpy.ops.wm.read_factory_settings(use_empty=True) if source == "definition": pending = build_node_groups() else: with bpy.data.libraries.load(str(node_asset_path())) as (library, target): target.node_groups = list(library.node_groups) pending = list(target.node_groups) seen = set() allowed = { "UVMap": ("FLOAT2", "CORNER"), "o_balloon": ("FLOAT", "POINT"), ".o_anyimage_depth_cut": ("BOOLEAN", "CORNER"), } while pending: group = pending.pop() if group in seen or group.bl_idname != "GeometryNodeTree": continue seen.add(group) for node in group.nodes: assert node.bl_idname != "GeometryNodeCaptureAttribute", group.name if node.bl_idname == "GeometryNodeGroup" and node.node_tree: pending.append(node.node_tree) if node.bl_idname != "GeometryNodeStoreNamedAttribute": continue name = node.inputs["Name"].default_value if name == "o_normal_scale": assert node.data_type == "FLOAT" and node.domain in {"POINT", "FACE"} else: assert name in allowed, (group.name, name) assert (node.data_type, node.domain) == allowed[name] assert {group.name for group in seen} == GEOMETRY_NAMES