nodebpy 520.31.0__tar.gz → 520.32.1__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.
Files changed (126) hide show
  1. {nodebpy-520.31.0 → nodebpy-520.32.1}/PKG-INFO +7 -10
  2. {nodebpy-520.31.0 → nodebpy-520.32.1}/README.md +6 -8
  3. {nodebpy-520.31.0 → nodebpy-520.32.1}/pyproject.toml +7 -6
  4. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/__init__.py +2 -2
  5. nodebpy-520.32.1/src/nodebpy/__main__.py +41 -0
  6. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/assets/__init__.py +4 -2
  7. nodebpy-520.32.1/src/nodebpy/assets/__main__.py +76 -0
  8. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/assets/_codegen.py +151 -177
  9. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/assets/_library.py +238 -103
  10. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/assets/_pipeline.py +5 -5
  11. nodebpy-520.32.1/src/nodebpy/assets/_textconv.py +88 -0
  12. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/builder/__init__.py +9 -11
  13. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/builder/_utils.py +12 -0
  14. nodebpy-520.32.1/src/nodebpy/builder/items.py +985 -0
  15. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/builder/mixins.py +15 -2
  16. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/builder/node.py +25 -15
  17. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/builder/socket.py +36 -12
  18. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/builder/tree.py +63 -4
  19. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/export/_floats.py +2 -0
  20. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/export/codegen.py +177 -123
  21. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/export/diagram.py +18 -4
  22. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/export/plot.py +2 -2
  23. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/export/web_render.py +0 -1
  24. nodebpy-520.32.1/src/nodebpy/layout/DESIGN.md +293 -0
  25. nodebpy-520.32.1/src/nodebpy/layout/__init__.py +26 -0
  26. nodebpy-520.32.1/src/nodebpy/layout/api.py +83 -0
  27. nodebpy-520.32.1/src/nodebpy/layout/apply.py +192 -0
  28. nodebpy-520.32.1/src/nodebpy/layout/balancing.py +251 -0
  29. nodebpy-520.32.1/src/nodebpy/layout/build.py +190 -0
  30. nodebpy-520.32.1/src/nodebpy/layout/common.py +131 -0
  31. nodebpy-520.32.1/src/nodebpy/layout/config.py +142 -0
  32. nodebpy-520.32.1/src/nodebpy/layout/digraph.py +694 -0
  33. nodebpy-520.32.1/src/nodebpy/layout/dna.py +186 -0
  34. nodebpy-520.32.1/src/nodebpy/layout/edits.py +172 -0
  35. nodebpy-520.32.1/src/nodebpy/layout/extract.py +174 -0
  36. nodebpy-520.32.1/src/nodebpy/layout/long_links.py +338 -0
  37. nodebpy-520.32.1/src/nodebpy/layout/model.py +449 -0
  38. nodebpy-520.32.1/src/nodebpy/layout/node_size.py +608 -0
  39. nodebpy-520.32.1/src/nodebpy/layout/ordering.py +806 -0
  40. nodebpy-520.32.1/src/nodebpy/layout/packing.py +207 -0
  41. nodebpy-520.32.1/src/nodebpy/layout/pipeline.py +335 -0
  42. nodebpy-520.32.1/src/nodebpy/layout/placement.py +641 -0
  43. nodebpy-520.32.1/src/nodebpy/layout/priority.py +152 -0
  44. nodebpy-520.32.1/src/nodebpy/layout/ranking.py +503 -0
  45. nodebpy-520.32.1/src/nodebpy/layout/realize.py +242 -0
  46. nodebpy-520.32.1/src/nodebpy/layout/reroutes.py +214 -0
  47. nodebpy-520.32.1/src/nodebpy/layout/routing.py +171 -0
  48. nodebpy-520.32.1/src/nodebpy/layout/snapping.py +183 -0
  49. nodebpy-520.32.1/src/nodebpy/layout/spacing.py +75 -0
  50. nodebpy-520.32.1/src/nodebpy/layout/stacking.py +415 -0
  51. nodebpy-520.32.1/src/nodebpy/layout/sugiyama.py +351 -0
  52. nodebpy-520.32.1/src/nodebpy/layout/zones.py +79 -0
  53. nodebpy-520.32.1/src/nodebpy/nodes/_mixins.py +468 -0
  54. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/compositor/assets.py +1 -1
  55. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/geometry/__init__.py +6 -6
  56. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/geometry/assets.py +1 -1
  57. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/geometry/geometry.py +3 -3
  58. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/geometry/groups.py +2 -2
  59. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/geometry/manual.py +162 -221
  60. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/geometry/zone.py +263 -380
  61. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/shader/__init__.py +4 -4
  62. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/shader/assets.py +2 -5
  63. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/shader/output.py +1 -1
  64. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/shader/texture.py +3 -3
  65. nodebpy-520.31.0/src/nodebpy/assets/__main__.py +0 -214
  66. nodebpy-520.31.0/src/nodebpy/builder/items.py +0 -770
  67. nodebpy-520.31.0/src/nodebpy/builder/layout.py +0 -1038
  68. nodebpy-520.31.0/src/nodebpy/lib/__init__.py +0 -0
  69. nodebpy-520.31.0/src/nodebpy/lib/nodearrange/VENDORED.md +0 -104
  70. nodebpy-520.31.0/src/nodebpy/lib/nodearrange/__init__.py +0 -6
  71. nodebpy-520.31.0/src/nodebpy/lib/nodearrange/arrange/__init__.py +0 -1
  72. nodebpy-520.31.0/src/nodebpy/lib/nodearrange/arrange/balancing.py +0 -182
  73. nodebpy-520.31.0/src/nodebpy/lib/nodearrange/arrange/graph.py +0 -622
  74. nodebpy-520.31.0/src/nodebpy/lib/nodearrange/arrange/ordering.py +0 -561
  75. nodebpy-520.31.0/src/nodebpy/lib/nodearrange/arrange/ranking.py +0 -335
  76. nodebpy-520.31.0/src/nodebpy/lib/nodearrange/arrange/realize.py +0 -270
  77. nodebpy-520.31.0/src/nodebpy/lib/nodearrange/arrange/stacking.py +0 -318
  78. nodebpy-520.31.0/src/nodebpy/lib/nodearrange/arrange/structs.py +0 -208
  79. nodebpy-520.31.0/src/nodebpy/lib/nodearrange/arrange/sugiyama.py +0 -347
  80. nodebpy-520.31.0/src/nodebpy/lib/nodearrange/arrange/x_coords.py +0 -229
  81. nodebpy-520.31.0/src/nodebpy/lib/nodearrange/arrange/y_coords.py +0 -376
  82. nodebpy-520.31.0/src/nodebpy/lib/nodearrange/config.py +0 -75
  83. nodebpy-520.31.0/src/nodebpy/lib/nodearrange/utils.py +0 -106
  84. nodebpy-520.31.0/src/nodebpy/nodes/_mixins.py +0 -474
  85. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/builder/_registry.py +0 -0
  86. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/builder/_socket_order.py +0 -0
  87. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/builder/accessor.py +0 -0
  88. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/builder/asset.py +0 -0
  89. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/export/__init__.py +0 -0
  90. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/export/parity.py +0 -0
  91. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/live.py +0 -0
  92. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/__init__.py +0 -0
  93. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/compositor/__init__.py +0 -0
  94. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/compositor/color.py +0 -0
  95. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/compositor/converter.py +0 -0
  96. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/compositor/distort.py +0 -0
  97. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/compositor/filter.py +0 -0
  98. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/compositor/group.py +0 -0
  99. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/compositor/input.py +0 -0
  100. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/compositor/interface.py +0 -0
  101. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/compositor/manual.py +0 -0
  102. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/compositor/matte.py +0 -0
  103. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/compositor/output.py +0 -0
  104. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/compositor/vector.py +0 -0
  105. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/geometry/attribute.py +0 -0
  106. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/geometry/color.py +0 -0
  107. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/geometry/converter.py +0 -0
  108. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/geometry/grid.py +0 -0
  109. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/geometry/group.py +0 -0
  110. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/geometry/input.py +0 -0
  111. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/geometry/interface.py +0 -0
  112. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/geometry/output.py +0 -0
  113. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/geometry/texture.py +0 -0
  114. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/geometry/utilities.py +0 -0
  115. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/geometry/vector.py +0 -0
  116. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/shader/color.py +0 -0
  117. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/shader/converter.py +0 -0
  118. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/shader/grid.py +0 -0
  119. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/shader/group.py +0 -0
  120. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/shader/input.py +0 -0
  121. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/shader/manual.py +0 -0
  122. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/shader/script.py +0 -0
  123. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/shader/shader.py +0 -0
  124. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/nodes/shader/vector.py +0 -0
  125. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/py.typed +0 -0
  126. {nodebpy-520.31.0 → nodebpy-520.32.1}/src/nodebpy/types.py +0 -0
@@ -1,13 +1,12 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: nodebpy
3
- Version: 520.31.0
3
+ Version: 520.32.1
4
4
  Summary: Build nodes trees in Blender more elegantly with code
5
5
  Author: Brady Johnston
6
6
  Author-email: Brady Johnston <brady.johnston@me.com>
7
7
  License: GPL-3.0-or-later
8
8
  Requires-Dist: bpy==5.2.* ; extra == 'bpy'
9
9
  Requires-Dist: ruff>=0.14.11 ; extra == 'format'
10
- Requires-Dist: networkx>=3.6.1 ; extra == 'networkx'
11
10
  Requires-Dist: matplotlib>=3.8 ; extra == 'plot'
12
11
  Requires-Python: >=3.13
13
12
  Provides-Extra: bpy
@@ -33,21 +32,19 @@ pip install nodebpy
33
32
  ```python
34
33
  from nodebpy import geometry as g
35
34
 
36
- with g.tree("AnotherTree", collapse=True) as tree:
37
- rotation = (
35
+ with g.tree("AnotherTree", collapse=True, is_modifier=True) as tree:
36
+ rot = (
38
37
  g.RandomValue.vector(min=-1, seed=2)
39
38
  >> g.AlignRotationToVector()
40
39
  >> g.RotateRotation(rotate_by=g.AxisAngleToRotation(angle=0.3))
41
40
  )
41
+ pos = g.Position() * 2.0 + (0, 0.2, 0.3)
42
42
 
43
- _ = (
43
+ (
44
44
  tree.inputs.integer("Count", 10)
45
45
  >> g.Points(position=g.RandomValue.vector(min=-1))
46
- >> g.InstanceOnPoints(instance=g.Cube(), rotation=rotation)
47
- >> g.SetPosition(
48
- position=g.Position() * 2.0 + (0, 0.2, 0.3),
49
- offset=(0, 0, 0.1),
50
- )
46
+ >> g.InstanceOnPoints(instance=g.Cube(), rotation=rot)
47
+ >> g.SetPosition(position=pos, offset=(0, 0, 0.1))
51
48
  >> g.RealizeInstances()
52
49
  >> g.InstanceOnPoints(g.Cube(), instance=...)
53
50
  >> tree.outputs.geometry("Instances")
@@ -15,21 +15,19 @@ pip install nodebpy
15
15
  ```python
16
16
  from nodebpy import geometry as g
17
17
 
18
- with g.tree("AnotherTree", collapse=True) as tree:
19
- rotation = (
18
+ with g.tree("AnotherTree", collapse=True, is_modifier=True) as tree:
19
+ rot = (
20
20
  g.RandomValue.vector(min=-1, seed=2)
21
21
  >> g.AlignRotationToVector()
22
22
  >> g.RotateRotation(rotate_by=g.AxisAngleToRotation(angle=0.3))
23
23
  )
24
+ pos = g.Position() * 2.0 + (0, 0.2, 0.3)
24
25
 
25
- _ = (
26
+ (
26
27
  tree.inputs.integer("Count", 10)
27
28
  >> g.Points(position=g.RandomValue.vector(min=-1))
28
- >> g.InstanceOnPoints(instance=g.Cube(), rotation=rotation)
29
- >> g.SetPosition(
30
- position=g.Position() * 2.0 + (0, 0.2, 0.3),
31
- offset=(0, 0, 0.1),
32
- )
29
+ >> g.InstanceOnPoints(instance=g.Cube(), rotation=rot)
30
+ >> g.SetPosition(position=pos, offset=(0, 0, 0.1))
33
31
  >> g.RealizeInstances()
34
32
  >> g.InstanceOnPoints(g.Cube(), instance=...)
35
33
  >> tree.outputs.geometry("Instances")
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "nodebpy"
3
- version = "520.31.0"
3
+ version = "520.32.1"
4
4
  description = "Build nodes trees in Blender more elegantly with code"
5
5
  readme = "README.md"
6
6
  authors = [
@@ -9,10 +9,13 @@ authors = [
9
9
  requires-python = ">=3.13"
10
10
  license = { text = "GPL-3.0-or-later" }
11
11
 
12
+ [project.scripts]
13
+ nodebpy = "nodebpy.__main__:main"
14
+
12
15
  [project.optional-dependencies]
13
- networkx = [
14
- "networkx>=3.6.1",
15
- ]
16
+ # Deprecated: the Sugiyama layout no longer needs networkx. Kept (empty) so
17
+ # existing `nodebpy[networkx]` installs keep resolving.
18
+ networkx = []
16
19
  plot = [
17
20
  "matplotlib>=3.8",
18
21
  ]
@@ -32,7 +35,6 @@ build-backend = "uv_build"
32
35
  dev = [
33
36
  "ipython>=8.0.0",
34
37
  "ipykernel>=6.0.0",
35
- "networkx>=3.6.1",
36
38
  "fake-bpy-module>=20260501",
37
39
  "jsondiff>=2.2.1",
38
40
  "pytest>=9.0.2",
@@ -45,7 +47,6 @@ dev = [
45
47
  "pytest-xdist>=3.8.0",
46
48
  "griffe<2.0.0",
47
49
  "ty==0.0.74",
48
- "types-networkx>=3.6.1.20260728",
49
50
  "matplotlib>=3.11.2",
50
51
  ]
51
52
 
@@ -1,7 +1,7 @@
1
1
  from . import builder, export, live, nodes, types
2
2
  from .builder import (
3
+ SIMPLE_OPTIONS,
3
4
  ArrangeMethod,
4
- SimpleOptions,
5
5
  SugiyamaOptions,
6
6
  TreeBuilder,
7
7
  arrange,
@@ -12,9 +12,9 @@ from .nodes import compositor, geometry, shader
12
12
  from .types import Default
13
13
 
14
14
  __all__ = [
15
+ "SIMPLE_OPTIONS",
15
16
  "ArrangeMethod",
16
17
  "Default",
17
- "SimpleOptions",
18
18
  "SugiyamaOptions",
19
19
  "TreeBuilder",
20
20
  "arrange",
@@ -0,0 +1,41 @@
1
+ """The ``nodebpy`` command line.
2
+
3
+ ``nodebpy <subcommand>`` (or ``python -m nodebpy <subcommand>``) round-trips
4
+ ``.blend`` asset libraries through Python source — ``dump``, ``build``,
5
+ ``ensure``, ``check``, ``plot`` — and renders them as text for ``git diff``
6
+ with ``textconv``; see :mod:`nodebpy.assets._library` and
7
+ :mod:`nodebpy.assets._textconv`.
8
+
9
+ Under a full Blender (no ``bpy`` module) run this file as a script, with the
10
+ arguments after Blender's ``--`` separator::
11
+
12
+ blender -b --factory-startup -P <.../nodebpy/__main__.py> -- textconv <blend>
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import sys
18
+ from pathlib import Path
19
+
20
+ # ``blender ... -P .../nodebpy/__main__.py`` runs this file as a plain script
21
+ # (no package context): put the package root on sys.path so the absolute
22
+ # imports resolve — a no-op under ``python -m nodebpy``.
23
+ if not __package__: # pragma: no cover - only under blender -P
24
+ sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
25
+
26
+
27
+ def main(argv: list[str] | None = None) -> None: # pragma: no cover - CLI wrapper
28
+ if argv is None:
29
+ # Blender passes script arguments after a ``--`` separator: strip
30
+ # everything up to and including it, so the subcommands work there.
31
+ argv = sys.argv[1:]
32
+ if "--" in sys.argv:
33
+ argv = sys.argv[sys.argv.index("--") + 1 :]
34
+
35
+ from nodebpy.assets._library import main as library_main
36
+
37
+ library_main(argv)
38
+
39
+
40
+ if __name__ == "__main__": # pragma: no cover
41
+ main()
@@ -10,13 +10,15 @@ compositor}.assets`` and are re-exported alongside the built-in nodes.
10
10
  ``dump_library`` and ``build_library`` round-trip a ``.blend`` asset library
11
11
  through Python source: every asset is dumped to its own ``.py`` file (the
12
12
  version-controlled source of truth) and the ``.blend`` is rebuilt from them
13
- (``python -m nodebpy.assets dump/build``). The CLI adds ``ensure`` (rebuild
13
+ (``nodebpy dump/build``). The CLI adds ``ensure`` (rebuild
14
14
  only when the ``.blend`` or its fingerprint stamp is stale) and ``check``
15
15
  (verify that build → dump reproduces the sources byte-for-byte), and reads
16
16
  its arguments from a ``[tool.nodebpy.assets]`` pyproject table — see
17
17
  :mod:`nodebpy.assets._pipeline`. ``plot_library`` renders node groups from a
18
18
  ``.blend`` to PNG images by name or wildcard
19
- (``python -m nodebpy.assets plot``), for review outside Blender.
19
+ (``nodebpy plot``), for review outside Blender, and ``nodebpy textconv``
20
+ prints a library's dumped source for ``git diff`` — see
21
+ :mod:`nodebpy.assets._textconv`.
20
22
  """
21
23
 
22
24
  from ..builder import AssetLibrary, BundledLibrary, PackageLibrary
@@ -0,0 +1,76 @@
1
+ """Deprecated ``python -m nodebpy.assets`` entry point; use ``nodebpy``.
2
+
3
+ Forwards to the ``nodebpy`` command (:mod:`nodebpy.__main__`) with a
4
+ ``FutureWarning``, and will be removed in nodebpy 530. Subcommands pass
5
+ through unchanged (``python -m nodebpy.assets dump …`` runs ``nodebpy dump
6
+ …``), and the old flag-based codegen interface (``-b lib.blend -o DIR``)
7
+ runs ``nodebpy dump --api-only lib.blend DIR``. The :mod:`nodebpy.assets`
8
+ module itself stays.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import argparse
14
+ import sys
15
+ import warnings
16
+ from pathlib import Path
17
+
18
+ # ``blender ... -P .../nodebpy/assets/__main__.py`` runs this file as a plain
19
+ # script (no package context): put the package root on sys.path so the
20
+ # absolute imports resolve, a no-op under ``python -m nodebpy.assets``.
21
+ if not __package__: # pragma: no cover - only under blender -P
22
+ sys.path.insert(0, str(Path(__file__).resolve().parents[2]))
23
+
24
+
25
+ def _api_dump_argv(argv: list[str]) -> list[str]:
26
+ """The flag-based codegen command line as a ``dump --api-only`` one."""
27
+ parser = argparse.ArgumentParser(prog="python -m nodebpy.assets")
28
+ parser.add_argument("--blend-file", "-b", type=Path)
29
+ parser.add_argument("--output", "--output-dir", "-o", dest="output", type=Path)
30
+ parser.add_argument("--nodebpy-pkg")
31
+ parser.add_argument("--no-docstrings", dest="docstrings", action="store_false")
32
+ args = parser.parse_args(argv)
33
+ if args.blend_file is None:
34
+ raise SystemExit(
35
+ "python -m nodebpy.assets: nodebpy's own bundled-essentials classes "
36
+ "are regenerated by 'python -m gen' (make generate)."
37
+ )
38
+ if args.output is None or args.output.suffix == ".py":
39
+ raise SystemExit(
40
+ "python -m nodebpy.assets: 'nodebpy dump --api-only' writes one "
41
+ "module per asset, so -o must be a directory; for a single module "
42
+ "call nodebpy.assets.generate_asset_api."
43
+ )
44
+ forwarded = ["dump", "--api-only", str(args.blend_file), str(args.output)]
45
+ if args.nodebpy_pkg:
46
+ forwarded += ["--nodebpy-pkg", args.nodebpy_pkg]
47
+ if not args.docstrings:
48
+ forwarded.append("--no-docstrings")
49
+ return forwarded
50
+
51
+
52
+ def main() -> None:
53
+ # Blender passes script arguments after a ``--`` separator: strip
54
+ # everything up to and including it.
55
+ argv = sys.argv[1:]
56
+ if "--" in sys.argv:
57
+ argv = sys.argv[sys.argv.index("--") + 1 :]
58
+
59
+ # The flag-based codegen interface took no positionals, so a leading
60
+ # positional is always a subcommand.
61
+ if not argv or argv[0].startswith("-"):
62
+ argv = _api_dump_argv(argv)
63
+ warnings.warn(
64
+ "'python -m nodebpy.assets' is deprecated and will be removed in "
65
+ f"nodebpy 530; use 'nodebpy {' '.join(argv[:2])}' instead.",
66
+ FutureWarning,
67
+ stacklevel=2,
68
+ )
69
+
70
+ from nodebpy.__main__ import main as nodebpy_main
71
+
72
+ nodebpy_main(argv)
73
+
74
+
75
+ if __name__ == "__main__": # pragma: no cover
76
+ main()