nodebpy 520.3.0__tar.gz → 520.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {nodebpy-520.3.0 → nodebpy-520.4.0}/PKG-INFO +1 -1
- {nodebpy-520.3.0 → nodebpy-520.4.0}/pyproject.toml +2 -2
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/assets/_codegen.py +3 -3
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/builder/asset.py +1 -1
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/builder/mixins.py +12 -2
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/builder/socket.py +0 -1
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/builder/tree.py +1 -1
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/export/codegen.py +1 -1
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/lib/nodearrange/arrange/ordering.py +1 -1
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/_mixins.py +1 -1
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/geometry/converter.py +3 -3
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/geometry/manual.py +3 -3
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/geometry/zone.py +2 -2
- {nodebpy-520.3.0 → nodebpy-520.4.0}/README.md +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/__init__.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/assets/__init__.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/assets/__main__.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/builder/__init__.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/builder/_registry.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/builder/_utils.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/builder/accessor.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/builder/arrange.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/builder/items.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/builder/node.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/export/__init__.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/export/diagram.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/lib/nodearrange/__init__.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/lib/nodearrange/arrange/__init__.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/lib/nodearrange/arrange/graph.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/lib/nodearrange/arrange/ranking.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/lib/nodearrange/arrange/realize.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/lib/nodearrange/arrange/stacking.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/lib/nodearrange/arrange/structs.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/lib/nodearrange/arrange/sugiyama.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/lib/nodearrange/arrange/x_coords.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/lib/nodearrange/arrange/y_coords.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/lib/nodearrange/config.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/lib/nodearrange/utils.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/__init__.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/compositor/__init__.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/compositor/assets.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/compositor/color.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/compositor/converter.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/compositor/distort.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/compositor/filter.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/compositor/group.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/compositor/input.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/compositor/interface.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/compositor/manual.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/compositor/matte.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/compositor/output.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/compositor/vector.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/geometry/__init__.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/geometry/assets.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/geometry/attribute.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/geometry/color.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/geometry/geometry.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/geometry/grid.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/geometry/group.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/geometry/groups.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/geometry/input.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/geometry/interface.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/geometry/output.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/geometry/texture.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/geometry/utilities.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/geometry/vector.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/shader/__init__.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/shader/assets.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/shader/color.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/shader/converter.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/shader/grid.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/shader/group.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/shader/input.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/shader/manual.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/shader/output.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/shader/script.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/shader/shader.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/shader/texture.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/nodes/shader/vector.py +0 -0
- {nodebpy-520.3.0 → nodebpy-520.4.0}/src/nodebpy/types.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "nodebpy"
|
|
3
|
-
version = "520.
|
|
3
|
+
version = "520.4.0"
|
|
4
4
|
description = "Build nodes trees in Blender more elegantly with code"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [
|
|
@@ -42,5 +42,5 @@ dev = [
|
|
|
42
42
|
"syrupy>=5.0.0",
|
|
43
43
|
"pytest-xdist>=3.8.0",
|
|
44
44
|
"griffe<2.0.0",
|
|
45
|
-
"ty
|
|
45
|
+
"ty==0.0.51",
|
|
46
46
|
]
|
|
@@ -144,7 +144,7 @@ def _introspect(library: AssetLibrary, names: set[str] | None) -> list[_AssetCla
|
|
|
144
144
|
path = library.path()
|
|
145
145
|
library_source = _library_source(library)
|
|
146
146
|
|
|
147
|
-
with bpy.data.libraries.load(path, link=False, assets_only=True) as (src, _):
|
|
147
|
+
with bpy.data.libraries.load(path, link=False, assets_only=True) as (src, _): # ty: ignore[invalid-context-manager]
|
|
148
148
|
available = list(src.node_groups)
|
|
149
149
|
wanted = [n for n in available if names is None or n in names]
|
|
150
150
|
|
|
@@ -155,7 +155,7 @@ def _introspect(library: AssetLibrary, names: set[str] | None) -> list[_AssetCla
|
|
|
155
155
|
# compositor "Combine Spherical" both exist) and we'd introspect the
|
|
156
156
|
# wrong one. Blender renames the appended copy on a clash; that's fine,
|
|
157
157
|
# we only read its interface (the emitted _asset_name uses the original).
|
|
158
|
-
with bpy.data.libraries.load(path, link=False, assets_only=True) as (
|
|
158
|
+
with bpy.data.libraries.load(path, link=False, assets_only=True) as ( # ty: ignore[invalid-context-manager]
|
|
159
159
|
src,
|
|
160
160
|
dst,
|
|
161
161
|
):
|
|
@@ -170,7 +170,7 @@ def _introspect(library: AssetLibrary, names: set[str] | None) -> list[_AssetCla
|
|
|
170
170
|
"CompositorNodeTree": "CompositorNodeGroup",
|
|
171
171
|
}[group.bl_idname]
|
|
172
172
|
node = host.nodes.new(node_type)
|
|
173
|
-
node.node_tree = group
|
|
173
|
+
node.node_tree = group # ty: ignore[unresolved-attribute]
|
|
174
174
|
classes.append(
|
|
175
175
|
_AssetClass(
|
|
176
176
|
class_name=_class_name(name),
|
|
@@ -93,7 +93,7 @@ class _AssetGroupMixin:
|
|
|
93
93
|
path = cls._library.path()
|
|
94
94
|
if not os.path.exists(path):
|
|
95
95
|
raise FileNotFoundError(f"Asset library not found: {path}")
|
|
96
|
-
with bpy.data.libraries.load(path, link=False, assets_only=True) as (src, dst):
|
|
96
|
+
with bpy.data.libraries.load(path, link=False, assets_only=True) as (src, dst): # ty: ignore[invalid-context-manager]
|
|
97
97
|
if cls._asset_name not in src.node_groups:
|
|
98
98
|
raise KeyError(f"Node group {cls._asset_name!r} not found in {path}")
|
|
99
99
|
dst.node_groups = [cls._asset_name]
|
|
@@ -367,7 +367,11 @@ class LinkingMixin:
|
|
|
367
367
|
else:
|
|
368
368
|
self._link(source, input)
|
|
369
369
|
|
|
370
|
-
|
|
370
|
+
@overload
|
|
371
|
+
def __rshift__(self, other: None) -> Self: ...
|
|
372
|
+
@overload
|
|
373
|
+
def __rshift__(self, other: _RShiftT) -> _RShiftT: ...
|
|
374
|
+
def __rshift__(self, other: _RShiftT | None) -> _RShiftT | Self:
|
|
371
375
|
"""Chain nodes using >> operator. Links output to input.
|
|
372
376
|
|
|
373
377
|
Usage:
|
|
@@ -377,8 +381,14 @@ class LinkingMixin:
|
|
|
377
381
|
If the target node has an ellipsis placeholder (...), links to that specific input.
|
|
378
382
|
Otherwise, finds the best compatible socket pair based on type compatibility.
|
|
379
383
|
|
|
380
|
-
Returns the right-hand node to enable continued chaining.
|
|
384
|
+
Returns the right-hand node to enable continued chaining. A ``None``
|
|
385
|
+
target is a no-op passthrough — nothing is linked and ``self`` is
|
|
386
|
+
returned so an optional node can be conditionally skipped::
|
|
387
|
+
|
|
388
|
+
src >> SetPosition() >> (Transform() if trans else None) >> out
|
|
381
389
|
"""
|
|
390
|
+
if other is None:
|
|
391
|
+
return self
|
|
382
392
|
if isinstance(other, _SocketLike):
|
|
383
393
|
source = self._default_output_socket
|
|
384
394
|
target = other.socket
|
|
@@ -629,7 +629,7 @@ class TreeBuilder(Generic[_TreeT]):
|
|
|
629
629
|
ignore_visibility: bool = False,
|
|
630
630
|
):
|
|
631
631
|
if isinstance(tree, str):
|
|
632
|
-
self.tree = bpy.data.node_groups.new(tree, tree_type) #
|
|
632
|
+
self.tree = bpy.data.node_groups.new(tree, tree_type) # ty: ignore[invalid-assignment]
|
|
633
633
|
else:
|
|
634
634
|
self.tree = tree # type: ignore
|
|
635
635
|
|
|
@@ -507,7 +507,7 @@ def _with_probe_tree(tree_idname: str, fn: Callable[[Any], _T], default: _T) ->
|
|
|
507
507
|
try:
|
|
508
508
|
import bpy
|
|
509
509
|
|
|
510
|
-
probe_tree = bpy.data.node_groups.new("__nodebpy_codegen_probe__", tree_idname)
|
|
510
|
+
probe_tree = bpy.data.node_groups.new("__nodebpy_codegen_probe__", tree_idname) # ty: ignore[invalid-argument-type]
|
|
511
511
|
try:
|
|
512
512
|
return fn(probe_tree)
|
|
513
513
|
finally:
|
|
@@ -453,7 +453,7 @@ def sort_reduced_free_columns(
|
|
|
453
453
|
|
|
454
454
|
def pos(v: Node | Cluster) -> int:
|
|
455
455
|
w = non_cluster_descendant(H.free_LT, v) if v.type == Kind.CLUSTER else v
|
|
456
|
-
return H.free_col.index(
|
|
456
|
+
return H.free_col.index(w)
|
|
457
457
|
|
|
458
458
|
for H in crossing_reduction_graphs:
|
|
459
459
|
H.reduced_free_col.sort(key=pos)
|
|
@@ -82,7 +82,7 @@ class _FormatStringMixin(ItemsMixin):
|
|
|
82
82
|
):
|
|
83
83
|
super().__init__()
|
|
84
84
|
key_args = {"Format": format}
|
|
85
|
-
key_args.update(self._add_inputs(**(items or {})))
|
|
85
|
+
key_args.update(self._add_inputs(**(items or {})))
|
|
86
86
|
self._establish_links(**key_args)
|
|
87
87
|
|
|
88
88
|
@property
|
|
@@ -1023,7 +1023,7 @@ class CombineBundle(BaseNode):
|
|
|
1023
1023
|
default.
|
|
1024
1024
|
"""
|
|
1025
1025
|
if isinstance(value, str):
|
|
1026
|
-
self.node.bundle_items.new(value, name)
|
|
1026
|
+
self.node.bundle_items.new(value, name) # ty: ignore[invalid-argument-type]
|
|
1027
1027
|
elif isinstance(value, (BaseNode, Socket, bpy.types.NodeSocket)):
|
|
1028
1028
|
extend = self.node.inputs[len(self.node.inputs) - 1]
|
|
1029
1029
|
self.tree.link(self._source_socket(value), extend)
|
|
@@ -1034,7 +1034,7 @@ class CombineBundle(BaseNode):
|
|
|
1034
1034
|
socket_type = _infer_value_type(value)
|
|
1035
1035
|
if socket_type is None:
|
|
1036
1036
|
raise TypeError(f"Unsupported bundle item {name!r}: {value!r}")
|
|
1037
|
-
self.node.bundle_items.new(socket_type, name)
|
|
1037
|
+
self.node.bundle_items.new(socket_type, name) # ty: ignore[invalid-argument-type]
|
|
1038
1038
|
self.node.inputs[name].default_value = value
|
|
1039
1039
|
|
|
1040
1040
|
|
|
@@ -6527,7 +6527,7 @@ class SeparateBundle(BaseNode):
|
|
|
6527
6527
|
# name and socket-type string (the inverse of CombineBundle, where the
|
|
6528
6528
|
# type is inferred from a linked source).
|
|
6529
6529
|
for name, socket_type in (items or {}).items():
|
|
6530
|
-
self.node.bundle_items.new(socket_type, name)
|
|
6530
|
+
self.node.bundle_items.new(socket_type, name) # ty: ignore[invalid-argument-type]
|
|
6531
6531
|
self._establish_links(Bundle=bundle)
|
|
6532
6532
|
|
|
6533
6533
|
|
|
@@ -684,7 +684,7 @@ class EvaluateClosure(BaseNode):
|
|
|
684
684
|
# one unlinked. This mirrors CombineBundle (inputs) / SeparateBundle
|
|
685
685
|
# (outputs).
|
|
686
686
|
for name, socket_type in (output_items or {}).items():
|
|
687
|
-
self.node.output_items.new(socket_type, name)
|
|
687
|
+
self.node.output_items.new(socket_type, name) # ty: ignore[invalid-argument-type]
|
|
688
688
|
for name, value in (input_items or {}).items():
|
|
689
689
|
self._add_input_item(name, value)
|
|
690
690
|
self.active_input_index = active_input_index
|
|
@@ -693,7 +693,7 @@ class EvaluateClosure(BaseNode):
|
|
|
693
693
|
|
|
694
694
|
def _add_input_item(self, name: str, value: "InputLinkable | str") -> None:
|
|
695
695
|
if isinstance(value, str):
|
|
696
|
-
self.node.input_items.new(value, name)
|
|
696
|
+
self.node.input_items.new(value, name) # ty: ignore[invalid-argument-type]
|
|
697
697
|
return
|
|
698
698
|
extend = self.node.inputs[len(self.node.inputs) - 1] # input __extend__
|
|
699
699
|
self.tree.link(self._source_socket(value), extend)
|
|
@@ -1795,7 +1795,7 @@ class FieldToGrid(ItemsMixin, BaseNode, Generic[_T]):
|
|
|
1795
1795
|
linkable = {k: v for k, v in items.items() if not _is_default_value(v)}
|
|
1796
1796
|
defaults = {k: v for k, v in items.items() if _is_default_value(v)}
|
|
1797
1797
|
|
|
1798
|
-
key_args.update(self._add_inputs(**linkable))
|
|
1798
|
+
key_args.update(self._add_inputs(**linkable))
|
|
1799
1799
|
for name, value in defaults.items():
|
|
1800
1800
|
socket = self._add_socket(name=name, type="FLOAT")
|
|
1801
1801
|
if value is not None:
|
|
@@ -599,12 +599,12 @@ class ClosureZone(_ZonePair):
|
|
|
599
599
|
``"VECTOR"``, …); the item collection lives on the output node and
|
|
600
600
|
drives the matching output socket on the input node.
|
|
601
601
|
"""
|
|
602
|
-
self.output.node.input_items.new(type, name)
|
|
602
|
+
self.output.node.input_items.new(type, name) # ty: ignore[invalid-argument-type]
|
|
603
603
|
return _wrap_socket(self.input.node.outputs[-2])
|
|
604
604
|
|
|
605
605
|
def output_item(self, name: str, type: str = "GEOMETRY") -> SocketLinker:
|
|
606
606
|
"""Declare a closure output and return the target to feed with ``>>``."""
|
|
607
|
-
self.output.node.output_items.new(type, name)
|
|
607
|
+
self.output.node.output_items.new(type, name) # ty: ignore[invalid-argument-type]
|
|
608
608
|
return _wrap_socket(self.output.node.inputs[-2])
|
|
609
609
|
|
|
610
610
|
@property
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|