nodebpy 520.30.2__tar.gz → 520.32.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.
Files changed (126) hide show
  1. {nodebpy-520.30.2 → nodebpy-520.32.0}/PKG-INFO +7 -10
  2. {nodebpy-520.30.2 → nodebpy-520.32.0}/README.md +6 -8
  3. {nodebpy-520.30.2 → nodebpy-520.32.0}/pyproject.toml +7 -6
  4. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/__init__.py +2 -2
  5. nodebpy-520.32.0/src/nodebpy/__main__.py +41 -0
  6. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/assets/__init__.py +4 -2
  7. nodebpy-520.32.0/src/nodebpy/assets/__main__.py +76 -0
  8. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/assets/_codegen.py +151 -177
  9. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/assets/_library.py +238 -103
  10. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/assets/_pipeline.py +5 -5
  11. nodebpy-520.32.0/src/nodebpy/assets/_textconv.py +88 -0
  12. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/builder/__init__.py +9 -11
  13. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/builder/_utils.py +12 -0
  14. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/builder/accessor.py +15 -0
  15. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/builder/asset.py +4 -4
  16. nodebpy-520.32.0/src/nodebpy/builder/items.py +964 -0
  17. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/builder/mixins.py +56 -40
  18. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/builder/node.py +45 -30
  19. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/builder/socket.py +36 -12
  20. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/builder/tree.py +63 -4
  21. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/export/_floats.py +2 -0
  22. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/export/codegen.py +177 -123
  23. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/export/diagram.py +18 -4
  24. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/export/plot.py +2 -2
  25. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/export/web_render.py +0 -1
  26. nodebpy-520.32.0/src/nodebpy/layout/DESIGN.md +293 -0
  27. nodebpy-520.32.0/src/nodebpy/layout/__init__.py +26 -0
  28. nodebpy-520.32.0/src/nodebpy/layout/api.py +83 -0
  29. nodebpy-520.32.0/src/nodebpy/layout/apply.py +192 -0
  30. nodebpy-520.32.0/src/nodebpy/layout/balancing.py +251 -0
  31. nodebpy-520.32.0/src/nodebpy/layout/build.py +190 -0
  32. nodebpy-520.32.0/src/nodebpy/layout/common.py +131 -0
  33. nodebpy-520.32.0/src/nodebpy/layout/config.py +142 -0
  34. nodebpy-520.32.0/src/nodebpy/layout/digraph.py +694 -0
  35. nodebpy-520.32.0/src/nodebpy/layout/dna.py +186 -0
  36. nodebpy-520.32.0/src/nodebpy/layout/edits.py +172 -0
  37. nodebpy-520.32.0/src/nodebpy/layout/extract.py +174 -0
  38. nodebpy-520.32.0/src/nodebpy/layout/long_links.py +338 -0
  39. nodebpy-520.32.0/src/nodebpy/layout/model.py +449 -0
  40. nodebpy-520.32.0/src/nodebpy/layout/node_size.py +608 -0
  41. nodebpy-520.32.0/src/nodebpy/layout/ordering.py +806 -0
  42. nodebpy-520.32.0/src/nodebpy/layout/packing.py +207 -0
  43. nodebpy-520.32.0/src/nodebpy/layout/pipeline.py +335 -0
  44. nodebpy-520.32.0/src/nodebpy/layout/placement.py +641 -0
  45. nodebpy-520.32.0/src/nodebpy/layout/priority.py +152 -0
  46. nodebpy-520.32.0/src/nodebpy/layout/ranking.py +503 -0
  47. nodebpy-520.32.0/src/nodebpy/layout/realize.py +242 -0
  48. nodebpy-520.32.0/src/nodebpy/layout/reroutes.py +214 -0
  49. nodebpy-520.32.0/src/nodebpy/layout/routing.py +171 -0
  50. nodebpy-520.32.0/src/nodebpy/layout/snapping.py +183 -0
  51. nodebpy-520.32.0/src/nodebpy/layout/spacing.py +75 -0
  52. nodebpy-520.32.0/src/nodebpy/layout/stacking.py +415 -0
  53. nodebpy-520.32.0/src/nodebpy/layout/sugiyama.py +351 -0
  54. nodebpy-520.32.0/src/nodebpy/layout/zones.py +79 -0
  55. nodebpy-520.32.0/src/nodebpy/nodes/_mixins.py +468 -0
  56. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/compositor/assets.py +1 -1
  57. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/geometry/__init__.py +6 -6
  58. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/geometry/assets.py +1 -1
  59. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/geometry/geometry.py +3 -3
  60. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/geometry/groups.py +2 -2
  61. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/geometry/manual.py +162 -221
  62. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/geometry/zone.py +245 -380
  63. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/shader/__init__.py +4 -4
  64. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/shader/assets.py +2 -5
  65. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/shader/output.py +1 -1
  66. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/shader/texture.py +3 -3
  67. nodebpy-520.30.2/src/nodebpy/assets/__main__.py +0 -214
  68. nodebpy-520.30.2/src/nodebpy/builder/items.py +0 -770
  69. nodebpy-520.30.2/src/nodebpy/builder/layout.py +0 -1038
  70. nodebpy-520.30.2/src/nodebpy/lib/__init__.py +0 -0
  71. nodebpy-520.30.2/src/nodebpy/lib/nodearrange/VENDORED.md +0 -104
  72. nodebpy-520.30.2/src/nodebpy/lib/nodearrange/__init__.py +0 -6
  73. nodebpy-520.30.2/src/nodebpy/lib/nodearrange/arrange/__init__.py +0 -1
  74. nodebpy-520.30.2/src/nodebpy/lib/nodearrange/arrange/balancing.py +0 -182
  75. nodebpy-520.30.2/src/nodebpy/lib/nodearrange/arrange/graph.py +0 -622
  76. nodebpy-520.30.2/src/nodebpy/lib/nodearrange/arrange/ordering.py +0 -561
  77. nodebpy-520.30.2/src/nodebpy/lib/nodearrange/arrange/ranking.py +0 -335
  78. nodebpy-520.30.2/src/nodebpy/lib/nodearrange/arrange/realize.py +0 -270
  79. nodebpy-520.30.2/src/nodebpy/lib/nodearrange/arrange/stacking.py +0 -318
  80. nodebpy-520.30.2/src/nodebpy/lib/nodearrange/arrange/structs.py +0 -208
  81. nodebpy-520.30.2/src/nodebpy/lib/nodearrange/arrange/sugiyama.py +0 -347
  82. nodebpy-520.30.2/src/nodebpy/lib/nodearrange/arrange/x_coords.py +0 -229
  83. nodebpy-520.30.2/src/nodebpy/lib/nodearrange/arrange/y_coords.py +0 -376
  84. nodebpy-520.30.2/src/nodebpy/lib/nodearrange/config.py +0 -75
  85. nodebpy-520.30.2/src/nodebpy/lib/nodearrange/utils.py +0 -106
  86. nodebpy-520.30.2/src/nodebpy/nodes/_mixins.py +0 -474
  87. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/builder/_registry.py +0 -0
  88. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/builder/_socket_order.py +0 -0
  89. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/export/__init__.py +0 -0
  90. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/export/parity.py +0 -0
  91. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/live.py +0 -0
  92. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/__init__.py +0 -0
  93. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/compositor/__init__.py +0 -0
  94. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/compositor/color.py +0 -0
  95. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/compositor/converter.py +0 -0
  96. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/compositor/distort.py +0 -0
  97. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/compositor/filter.py +0 -0
  98. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/compositor/group.py +0 -0
  99. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/compositor/input.py +0 -0
  100. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/compositor/interface.py +0 -0
  101. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/compositor/manual.py +0 -0
  102. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/compositor/matte.py +0 -0
  103. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/compositor/output.py +0 -0
  104. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/compositor/vector.py +0 -0
  105. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/geometry/attribute.py +0 -0
  106. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/geometry/color.py +0 -0
  107. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/geometry/converter.py +0 -0
  108. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/geometry/grid.py +0 -0
  109. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/geometry/group.py +0 -0
  110. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/geometry/input.py +0 -0
  111. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/geometry/interface.py +0 -0
  112. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/geometry/output.py +0 -0
  113. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/geometry/texture.py +0 -0
  114. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/geometry/utilities.py +0 -0
  115. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/geometry/vector.py +0 -0
  116. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/shader/color.py +0 -0
  117. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/shader/converter.py +0 -0
  118. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/shader/grid.py +0 -0
  119. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/shader/group.py +0 -0
  120. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/shader/input.py +0 -0
  121. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/shader/manual.py +0 -0
  122. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/shader/script.py +0 -0
  123. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/shader/shader.py +0 -0
  124. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/nodes/shader/vector.py +0 -0
  125. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/py.typed +0 -0
  126. {nodebpy-520.30.2 → nodebpy-520.32.0}/src/nodebpy/types.py +0 -0
@@ -1,13 +1,12 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: nodebpy
3
- Version: 520.30.2
3
+ Version: 520.32.0
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.30.2"
3
+ version = "520.32.0"
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()