session-py 0.167.0__tar.gz → 0.169.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 (134) hide show
  1. session_py-0.169.0/.github/FUNDING.yml +1 -0
  2. {session_py-0.167.0 → session_py-0.169.0}/PKG-INFO +1 -1
  3. {session_py-0.167.0 → session_py-0.169.0}/pyproject.toml +1 -1
  4. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/brep.py +7 -2
  5. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/color.py +7 -2
  6. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/element.py +12 -3
  7. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/element_test.py +4 -2
  8. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/graph.py +13 -2
  9. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/instance_ref.py +7 -2
  10. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/instance_ref_test.py +2 -1
  11. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/line.py +7 -2
  12. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/line_test.py +2 -1
  13. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/matrix.py +7 -2
  14. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/mesh.py +11 -4
  15. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/nurbscurve.py +9 -3
  16. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/nurbssurface.py +9 -3
  17. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/nurbssurface_trimmed.py +7 -2
  18. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/obb.py +7 -2
  19. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/obb_test.py +2 -1
  20. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/objects.py +7 -2
  21. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/plane.py +7 -2
  22. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/point.py +7 -2
  23. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/pointcloud.py +7 -2
  24. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/polyline.py +9 -3
  25. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/quaternion.py +3 -0
  26. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/session.py +7 -25
  27. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/spatial_bvh.py +3 -0
  28. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/tree.py +10 -2
  29. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/vector.py +3 -0
  30. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/xform.py +7 -2
  31. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/xform_test.py +2 -1
  32. {session_py-0.167.0 → session_py-0.169.0}/.github/workflows/publish.yml +0 -0
  33. {session_py-0.167.0 → session_py-0.169.0}/.github/workflows/test.yml +0 -0
  34. {session_py-0.167.0 → session_py-0.169.0}/.gitignore +0 -0
  35. {session_py-0.167.0 → session_py-0.169.0}/.gitmodules +0 -0
  36. {session_py-0.167.0 → session_py-0.169.0}/AGENTS.md +0 -0
  37. {session_py-0.167.0 → session_py-0.169.0}/README.md +0 -0
  38. {session_py-0.167.0 → session_py-0.169.0}/conftest.py +0 -0
  39. {session_py-0.167.0 → session_py-0.169.0}/examples/bvh_demo.py +0 -0
  40. {session_py-0.167.0 → session_py-0.169.0}/examples/loft_holes.py +0 -0
  41. {session_py-0.167.0 → session_py-0.169.0}/examples/nurbsurface.py +0 -0
  42. {session_py-0.167.0 → session_py-0.169.0}/serialization/.gitkeep +0 -0
  43. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/__init__.py +0 -0
  44. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/aabb.py +0 -0
  45. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/aabb_test.py +0 -0
  46. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/boolean_polyline.py +0 -0
  47. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/boolean_polyline_test.py +0 -0
  48. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/brep_test.py +0 -0
  49. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/closest.py +0 -0
  50. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/closest_test.py +0 -0
  51. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/color_test.py +0 -0
  52. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/convex_hull.py +0 -0
  53. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/convex_hull_test.py +0 -0
  54. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/file_encoders.py +0 -0
  55. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/file_encoders_test.py +0 -0
  56. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/file_obj.py +0 -0
  57. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/file_obj_test.py +0 -0
  58. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/graph_test.py +0 -0
  59. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/intersection.py +0 -0
  60. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/intersection_test.py +0 -0
  61. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/io.py +0 -0
  62. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/io_test.py +0 -0
  63. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/matrix_test.py +0 -0
  64. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/mesh_offset.py +0 -0
  65. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/mesh_offset_test.py +0 -0
  66. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/mesh_test.py +0 -0
  67. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/mini_test.py +0 -0
  68. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/nurbscurve_test.py +0 -0
  69. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/nurbsknot.py +0 -0
  70. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/nurbsknot_test.py +0 -0
  71. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/nurbssurface_test.py +0 -0
  72. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/nurbssurface_trimmed_test.py +0 -0
  73. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/objects_test.py +0 -0
  74. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/plane_test.py +0 -0
  75. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/point_test.py +0 -0
  76. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/pointcloud_test.py +0 -0
  77. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/polyline_test.py +0 -0
  78. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/primitives.py +0 -0
  79. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/primitives_test.py +0 -0
  80. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/proto/.gitattributes +0 -0
  81. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/proto/__init__.py +0 -0
  82. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/proto/boundingbox_pb2.py +0 -0
  83. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/proto/brep_pb2.py +0 -0
  84. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/proto/color_pb2.py +0 -0
  85. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/proto/edge_pb2.py +0 -0
  86. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/proto/element_pb2.py +0 -0
  87. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/proto/file_encoders_pb2.py +0 -0
  88. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/proto/graph_pb2.py +0 -0
  89. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/proto/instance_ref_pb2.py +0 -0
  90. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/proto/line_pb2.py +0 -0
  91. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/proto/matrix_pb2.py +0 -0
  92. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/proto/mesh_pb2.py +0 -0
  93. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/proto/nurbscurve_pb2.py +0 -0
  94. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/proto/nurbssurface_pb2.py +0 -0
  95. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/proto/nurbssurface_trimmed_pb2.py +0 -0
  96. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/proto/objects_pb2.py +0 -0
  97. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/proto/plane_pb2.py +0 -0
  98. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/proto/point_pb2.py +0 -0
  99. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/proto/pointcloud_pb2.py +0 -0
  100. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/proto/polyline_pb2.py +0 -0
  101. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/proto/quaternion_pb2.py +0 -0
  102. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/proto/session_pb2.py +0 -0
  103. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/proto/tolerance_pb2.py +0 -0
  104. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/proto/tree_pb2.py +0 -0
  105. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/proto/treenode_pb2.py +0 -0
  106. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/proto/vector_pb2.py +0 -0
  107. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/proto/vertex_pb2.py +0 -0
  108. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/proto/xform_pb2.py +0 -0
  109. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/py.typed +0 -0
  110. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/quaternion_test.py +0 -0
  111. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/reload.py +0 -0
  112. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/remesh_cdt.py +0 -0
  113. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/remesh_cdt_test.py +0 -0
  114. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/remesh_nurbssurface_adaptive.py +0 -0
  115. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/remesh_nurbssurface_adaptive_test.py +0 -0
  116. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/remesh_nurbssurface_grid.py +0 -0
  117. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/remesh_nurbssurface_grid_test.py +0 -0
  118. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/session_config.py +0 -0
  119. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/session_config_test.py +0 -0
  120. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/session_test.py +0 -0
  121. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/spatial_aabbtree.py +0 -0
  122. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/spatial_aabbtree_test.py +0 -0
  123. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/spatial_bvh_test.py +0 -0
  124. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/spatial_kdtree.py +0 -0
  125. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/spatial_kdtree_test.py +0 -0
  126. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/spatial_octree.py +0 -0
  127. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/spatial_octree_test.py +0 -0
  128. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/spatial_rtree.py +0 -0
  129. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/spatial_rtree_test.py +0 -0
  130. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/tolerance.py +0 -0
  131. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/tolerance_test.py +0 -0
  132. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/tree_test.py +0 -0
  133. {session_py-0.167.0 → session_py-0.169.0}/src/session_py/vector_test.py +0 -0
  134. {session_py-0.167.0 → session_py-0.169.0}/uv.lock +0 -0
@@ -0,0 +1 @@
1
+ github: [petrasvestartas]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: session_py
3
- Version: 0.167.0
3
+ Version: 0.169.0
4
4
  Summary: A minimal Python geometry library
5
5
  Project-URL: Homepage, https://github.com/petrasvestartas/session_py
6
6
  Project-URL: Repository, https://github.com/petrasvestartas/session_py
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "session_py"
7
- version = "0.167.0"
7
+ version = "0.169.0"
8
8
  description = "A minimal Python geometry library"
9
9
  authors = [{name = "Petras Vestartas", email = "petrasvestartas@gmail.com"}]
10
10
  license = {text = "MIT"}
@@ -396,6 +396,9 @@ class BRep:
396
396
  self.m_shells: list[BRepShell] = []
397
397
  self.m_solids: list[BRepSolid] = []
398
398
 
399
+ def has_guid(self) -> bool:
400
+ return getattr(self, '_guid', None) is not None
401
+
399
402
  @property
400
403
  def guid(self) -> str:
401
404
  if getattr(self, '_guid', None) is None:
@@ -1245,7 +1248,8 @@ class BRep:
1245
1248
  def pb_dumps(self) -> bytes:
1246
1249
  from .proto import brep_pb2
1247
1250
  proto = brep_pb2.BRep()
1248
- proto.guid = self.guid
1251
+ if self.has_guid():
1252
+ proto.guid = self._guid
1249
1253
  proto.name = self.name
1250
1254
  proto.width = self.width
1251
1255
  for c in self.m_curves_2d:
@@ -1301,7 +1305,8 @@ class BRep:
1301
1305
  proto = brep_pb2.BRep()
1302
1306
  proto.ParseFromString(data)
1303
1307
  b = cls()
1304
- b.guid = proto.guid
1308
+ if proto.guid:
1309
+ b.guid = proto.guid
1305
1310
  b.name = proto.name
1306
1311
  b.width = proto.width
1307
1312
  b.m_curves_2d = [NurbsCurve.pb_loads(c.SerializeToString()) for c in proto.curves_2d]
@@ -49,6 +49,9 @@ class Color:
49
49
  self._b = max(0.0, min(1.0, float(b)))
50
50
  self._a = max(0.0, min(1.0, float(a)))
51
51
 
52
+ def has_guid(self) -> bool:
53
+ return getattr(self, '_guid', None) is not None
54
+
52
55
  @property
53
56
  def guid(self) -> str:
54
57
  if getattr(self, '_guid', None) is None:
@@ -438,7 +441,8 @@ class Color:
438
441
  if not _HAS_PROTOBUF:
439
442
  raise ImportError("protobuf not available")
440
443
  proto = color_pb2.Color()
441
- proto.guid = self.guid
444
+ if self.has_guid():
445
+ proto.guid = self._guid
442
446
  proto.name = self.name
443
447
  proto.r = self[0]
444
448
  proto.g = self[1]
@@ -472,7 +476,8 @@ class Color:
472
476
  proto.ParseFromString(data)
473
477
 
474
478
  color = cls(proto.r, proto.g, proto.b, proto.a)
475
- color.guid = proto.guid
479
+ if proto.guid:
480
+ color.guid = proto.guid
476
481
  color.name = proto.name
477
482
  return color
478
483
 
@@ -54,6 +54,9 @@ class ElementFeature:
54
54
  self.face_index = face_index
55
55
  self.outlines = list(outlines or [])
56
56
 
57
+ def has_guid(self) -> bool:
58
+ return getattr(self, '_guid', None) is not None
59
+
57
60
  @property
58
61
  def guid(self) -> str:
59
62
  """Lazily minted, like every other identity in the kernel - a feature nobody names never
@@ -154,7 +157,8 @@ class ElementFeature:
154
157
  def pb_dumps(self) -> bytes:
155
158
  from .proto import element_pb2
156
159
  proto = element_pb2.ElementFeature()
157
- proto.guid = self.guid
160
+ if self.has_guid():
161
+ proto.guid = self._guid
158
162
  proto.name = self.name
159
163
  proto.feature_type = self.feature_type
160
164
  proto.face_index = self.face_index
@@ -215,6 +219,9 @@ class Element:
215
219
  self._edge_vectors = None
216
220
  self._axis = None
217
221
 
222
+ def has_guid(self) -> bool:
223
+ return getattr(self, '_guid', None) is not None
224
+
218
225
  @property
219
226
  def guid(self) -> str:
220
227
  if getattr(self, '_guid', None) is None:
@@ -633,7 +640,8 @@ class Element:
633
640
  def pb_dumps(self) -> bytes:
634
641
  from .proto import element_pb2
635
642
  proto = element_pb2.Element()
636
- proto.guid = self.guid
643
+ if self.has_guid():
644
+ proto.guid = self._guid
637
645
  proto.name = self.name
638
646
  if self._geometry is not None:
639
647
  proto.geometry_type = type(self._geometry).__name__
@@ -671,7 +679,8 @@ class Element:
671
679
  if proto.geometry_type and proto.geometry_type != "None" and proto.geometry_data:
672
680
  geometry = cls._pb_load_geometry(proto.geometry_type, proto.geometry_data)
673
681
  elem = cls(geometry=geometry)
674
- elem.guid = proto.guid
682
+ if proto.guid:
683
+ elem.guid = proto.guid
675
684
  elem.name = proto.name
676
685
  # Carried, not interpreted. A viewer with no wood package registered loads a wood element
677
686
  # as a base Element; if these two were dropped here, saving it again wrote empty values
@@ -325,6 +325,7 @@ def test_registry_round_trip():
325
325
 
326
326
  plate = TestPlate(geometry=_unit_quad(), thickness=12.5, codes=[30, 11, 20])
327
327
  plate.name = "plate_0"
328
+ guid = plate.guid
328
329
  loaded = Element.pb_loads_polymorphic(plate.pb_dumps())
329
330
 
330
331
  # The derived type came back, not a sliced base.
@@ -332,7 +333,7 @@ def test_registry_round_trip():
332
333
  MINI_CHECK(loaded.element_type_name() == "TestPlate")
333
334
 
334
335
  # Identity, base state and domain state all survived.
335
- MINI_CHECK(loaded.guid == plate.guid)
336
+ MINI_CHECK(loaded.guid == guid)
336
337
  MINI_CHECK(loaded.name == "plate_0")
337
338
  MINI_CHECK(isinstance(loaded.geometry, Mesh))
338
339
  MINI_CHECK(TOLERANCE.is_close(loaded.thickness, 12.5))
@@ -445,11 +446,12 @@ def test_registry_json_round_trip():
445
446
 
446
447
  plate = TestPlate(geometry=_unit_quad(), thickness=9.5, codes=[7, 8])
447
448
  plate.name = "plate_json"
449
+ guid = plate.guid
448
450
  loaded = Element.file_json_loads_polymorphic(plate.file_json_dumps())
449
451
 
450
452
  MINI_CHECK(isinstance(loaded, TestPlate))
451
453
  MINI_CHECK(loaded.name == "plate_json")
452
- MINI_CHECK(loaded.guid == plate.guid)
454
+ MINI_CHECK(loaded.guid == guid)
453
455
  MINI_CHECK(TOLERANCE.is_close(loaded.thickness, 9.5))
454
456
  MINI_CHECK(loaded.codes == [7, 8])
455
457
 
@@ -18,6 +18,9 @@ class Vertex:
18
18
  self.attribute = str(attribute)
19
19
  self.index = None
20
20
 
21
+ def has_guid(self) -> bool:
22
+ return getattr(self, '_guid', None) is not None
23
+
21
24
  @property
22
25
  def guid(self) -> str:
23
26
  if getattr(self, '_guid', None) is None:
@@ -67,6 +70,9 @@ class Edge:
67
70
  self.attribute = str(attribute)
68
71
  self.index = None
69
72
 
73
+ def has_guid(self) -> bool:
74
+ return getattr(self, '_guid', None) is not None
75
+
70
76
  @property
71
77
  def guid(self) -> str:
72
78
  if getattr(self, '_guid', None) is None:
@@ -147,6 +153,9 @@ class Graph:
147
153
  self.vertex_count = 0 # Track next available vertex index
148
154
  self.edge_count = 0 # Track next available edge index
149
155
 
156
+ def has_guid(self) -> bool:
157
+ return getattr(self, '_guid', None) is not None
158
+
150
159
  @property
151
160
  def guid(self) -> str:
152
161
  if getattr(self, '_guid', None) is None:
@@ -280,7 +289,8 @@ class Graph:
280
289
 
281
290
  proto = graph_pb2.Graph()
282
291
  proto.name = self.name
283
- proto.guid = self.guid
292
+ if self.has_guid():
293
+ proto.guid = self._guid
284
294
  proto.vertex_count = self.vertex_count
285
295
  proto.edge_count = self.edge_count
286
296
 
@@ -318,7 +328,8 @@ class Graph:
318
328
  proto.ParseFromString(data)
319
329
 
320
330
  graph = cls(name=proto.name)
321
- graph.guid = proto.guid
331
+ if proto.guid:
332
+ graph.guid = proto.guid
322
333
  graph.vertex_count = proto.vertex_count
323
334
  graph.edge_count = proto.edge_count
324
335
 
@@ -48,6 +48,9 @@ class InstanceRef:
48
48
  self._color = None
49
49
  self.flags = 0
50
50
 
51
+ def has_guid(self) -> bool:
52
+ return getattr(self, '_guid', None) is not None
53
+
51
54
  @property
52
55
  def guid(self) -> str:
53
56
  if getattr(self, '_guid', None) is None:
@@ -214,7 +217,8 @@ class InstanceRef:
214
217
  from .proto import instance_ref_pb2
215
218
 
216
219
  proto = instance_ref_pb2.InstanceRef()
217
- proto.guid = self.guid
220
+ if self.has_guid():
221
+ proto.guid = self._guid
218
222
  proto.name = self.name
219
223
  proto.definition_guid = self.definition_guid
220
224
  proto.xform.name = self.xform.name
@@ -235,7 +239,8 @@ class InstanceRef:
235
239
  proto.ParseFromString(data)
236
240
 
237
241
  ref = cls(proto.definition_guid)
238
- ref.guid = proto.guid
242
+ if proto.guid:
243
+ ref.guid = proto.guid
239
244
  ref.name = proto.name
240
245
  if proto.HasField('xform'):
241
246
  ref.xform = Xform()
@@ -102,13 +102,14 @@ def test_instance_ref_protobuf_roundtrip():
102
102
  r.flags = 5
103
103
 
104
104
  # Bytes
105
+ guid = r.guid
105
106
  b = r.pb_dumps()
106
107
  loaded_s = InstanceRef.pb_loads(b)
107
108
 
108
109
  MINI_CHECK(loaded_s.name == "test_ref")
109
110
  MINI_CHECK(loaded_s.definition_guid == "def-xyz")
110
111
  MINI_CHECK(loaded_s.flags == 5)
111
- MINI_CHECK(loaded_s.guid == r.guid)
112
+ MINI_CHECK(loaded_s.guid == guid)
112
113
  MINI_CHECK(TOLERANCE.is_close(loaded_s[14], 3.0))
113
114
 
114
115
  # File
@@ -57,6 +57,9 @@ class Line:
57
57
  self.dash = []
58
58
  self._linecolor = None
59
59
 
60
+ def has_guid(self) -> bool:
61
+ return getattr(self, '_guid', None) is not None
62
+
60
63
  @property
61
64
  def guid(self) -> str:
62
65
  if getattr(self, '_guid', None) is None:
@@ -778,7 +781,8 @@ class Line:
778
781
  from .proto import point_pb2
779
782
 
780
783
  proto = line_pb2.Line()
781
- proto.guid = self.guid
784
+ if self.has_guid():
785
+ proto.guid = self._guid
782
786
  proto.name = self.name
783
787
 
784
788
  # P6: coords packed, colour packed; the name rides a zero-cost string
@@ -813,7 +817,8 @@ class Line:
813
817
 
814
818
  c = proto.coords
815
819
  line = cls(c[0], c[1], c[2], c[3], c[4], c[5]) if len(c) == 6 else cls()
816
- line.guid = proto.guid
820
+ if proto.guid:
821
+ line.guid = proto.guid
817
822
  line.name = proto.name
818
823
 
819
824
  # Load width and linecolor
@@ -183,12 +183,13 @@ def test_line_protobuf_roundtrip():
183
183
  # pb_load(path) │ file │ read from file
184
184
 
185
185
  # Bytes
186
+ guid = l.guid
186
187
  b = l.pb_dumps()
187
188
  loaded_s = Line.pb_loads(b)
188
189
 
189
190
  MINI_CHECK(loaded_s.name == "test_line")
190
191
  MINI_CHECK(TOLERANCE.is_close(loaded_s[0], 42.1))
191
- MINI_CHECK(loaded_s.guid == l.guid)
192
+ MINI_CHECK(loaded_s.guid == guid)
192
193
 
193
194
  # File
194
195
  fname = Path(__file__).resolve().parents[2] / "serialization" / "test_line.bin"
@@ -19,6 +19,9 @@ class Matrix:
19
19
  self._cols = cols
20
20
  self.data = [0.0] * (rows * cols)
21
21
 
22
+ def has_guid(self) -> bool:
23
+ return getattr(self, '_guid', None) is not None
24
+
22
25
  @property
23
26
  def guid(self) -> str:
24
27
  if getattr(self, '_guid', None) is None:
@@ -465,7 +468,8 @@ class Matrix:
465
468
  def pb_dumps(self) -> bytes:
466
469
  from .proto import matrix_pb2
467
470
  proto = matrix_pb2.Matrix()
468
- proto.guid = self.guid
471
+ if self.has_guid():
472
+ proto.guid = self._guid
469
473
  proto.name = self.name
470
474
  proto.rows = self._rows
471
475
  proto.cols = self._cols
@@ -478,7 +482,8 @@ class Matrix:
478
482
  proto = matrix_pb2.Matrix()
479
483
  proto.ParseFromString(data)
480
484
  m = cls.from_list(proto.rows, proto.cols, list(proto.data))
481
- m.guid = proto.guid
485
+ if proto.guid:
486
+ m.guid = proto.guid
482
487
  m.name = proto.name
483
488
  return m
484
489
 
@@ -381,6 +381,9 @@ class Mesh:
381
381
  self._triangle_face_subidx_cache = []
382
382
  self._vertices_cache = []
383
383
 
384
+ def has_guid(self) -> bool:
385
+ return getattr(self, '_guid', None) is not None
386
+
384
387
  @property
385
388
  def guid(self) -> str:
386
389
  if getattr(self, '_guid', None) is None:
@@ -2985,7 +2988,8 @@ class Mesh:
2985
2988
  from .proto import mesh_pb2
2986
2989
 
2987
2990
  proto = mesh_pb2.Mesh()
2988
- proto.guid = self.guid
2991
+ if self.has_guid():
2992
+ proto.guid = self._guid
2989
2993
  proto.name = self.name
2990
2994
 
2991
2995
  # Vertices
@@ -3067,7 +3071,8 @@ class Mesh:
3067
3071
  """Fill an existing Mesh proto message directly (avoids serialize/deserialize cycle)."""
3068
3072
  from .proto import mesh_pb2
3069
3073
  from .proto import color_pb2
3070
- proto.guid = self.guid
3074
+ if self.has_guid():
3075
+ proto.guid = self._guid
3071
3076
  proto.name = self.name
3072
3077
  for vkey, vdata in self.vertex.items():
3073
3078
  vp = proto.vertices[vkey]
@@ -3127,7 +3132,8 @@ class Mesh:
3127
3132
  proto.ParseFromString(data)
3128
3133
 
3129
3134
  mesh = cls()
3130
- mesh.guid = proto.guid
3135
+ if proto.guid:
3136
+ mesh.guid = proto.guid
3131
3137
  mesh.name = proto.name
3132
3138
 
3133
3139
  # Vertices
@@ -3201,7 +3207,8 @@ class Mesh:
3201
3207
  from .color import Color
3202
3208
 
3203
3209
  mesh = cls()
3204
- mesh.guid = proto.guid
3210
+ if proto.guid:
3211
+ mesh.guid = proto.guid
3205
3212
  mesh.name = proto.name
3206
3213
 
3207
3214
  for vkey, vdata in proto.vertices.items():
@@ -744,6 +744,9 @@ class NurbsCurve:
744
744
 
745
745
  self._rmf_cache = None
746
746
 
747
+ def has_guid(self) -> bool:
748
+ return getattr(self, '_guid', None) is not None
749
+
747
750
  @property
748
751
  def guid(self) -> str:
749
752
  if getattr(self, '_guid', None) is None:
@@ -3854,7 +3857,8 @@ class NurbsCurve:
3854
3857
  """Convert to protobuf binary bytes."""
3855
3858
  from .proto import nurbscurve_pb2
3856
3859
  proto = nurbscurve_pb2.NurbsCurve()
3857
- proto.guid = self.guid
3860
+ if self.has_guid():
3861
+ proto.guid = self._guid
3858
3862
  proto.name = self.name
3859
3863
  proto.dimension = int(self.m_dim)
3860
3864
  proto.is_rational = bool(self.m_is_rat)
@@ -3875,7 +3879,8 @@ class NurbsCurve:
3875
3879
 
3876
3880
  def pb_fill(self, proto: "nurbscurve_pb2.NurbsCurve") -> None:
3877
3881
  """Fill an existing NurbsCurve proto message directly (avoids serialize/deserialize cycle)."""
3878
- proto.guid = self.guid
3882
+ if self.has_guid():
3883
+ proto.guid = self._guid
3879
3884
  proto.name = self.name
3880
3885
  proto.dimension = int(self.m_dim)
3881
3886
  proto.is_rational = bool(self.m_is_rat)
@@ -3899,7 +3904,8 @@ class NurbsCurve:
3899
3904
  proto = nurbscurve_pb2.NurbsCurve()
3900
3905
  proto.ParseFromString(data)
3901
3906
  curve = cls()
3902
- curve.guid = proto.guid
3907
+ if proto.guid:
3908
+ curve.guid = proto.guid
3903
3909
  curve.name = proto.name
3904
3910
  curve.m_dim = proto.dimension
3905
3911
  curve.m_is_rat = 1 if proto.is_rational else 0
@@ -117,6 +117,9 @@ class NurbsSurface:
117
117
  else:
118
118
  self.make_clamped_uniform_nurbsknot_vector(1, nurbsknot_delta_v)
119
119
 
120
+ def has_guid(self) -> bool:
121
+ return getattr(self, '_guid', None) is not None
122
+
120
123
  @property
121
124
  def guid(self) -> str:
122
125
  if getattr(self, '_guid', None) is None:
@@ -2975,7 +2978,8 @@ class NurbsSurface:
2975
2978
  from .proto import nurbssurface_pb2
2976
2979
 
2977
2980
  proto = nurbssurface_pb2.NurbsSurface()
2978
- proto.guid = self.guid
2981
+ if self.has_guid():
2982
+ proto.guid = self._guid
2979
2983
  proto.name = self.name
2980
2984
  proto.dimension = self.m_dim
2981
2985
  proto.is_rational = bool(self.m_is_rat)
@@ -3015,7 +3019,8 @@ class NurbsSurface:
3015
3019
 
3016
3020
  def pb_fill(self, proto: "nurbssurface_pb2.NurbsSurface") -> None:
3017
3021
  """Fill an existing NurbsSurface proto message directly (avoids serialize/deserialize cycle)."""
3018
- proto.guid = self.guid
3022
+ if self.has_guid():
3023
+ proto.guid = self._guid
3019
3024
  proto.name = self.name
3020
3025
  proto.dimension = self.m_dim
3021
3026
  proto.is_rational = bool(self.m_is_rat)
@@ -3074,7 +3079,8 @@ class NurbsSurface:
3074
3079
  )
3075
3080
 
3076
3081
  # Load metadata
3077
- surface.guid = proto.guid
3082
+ if proto.guid:
3083
+ surface.guid = proto.guid
3078
3084
  surface.name = proto.name
3079
3085
  surface.width = proto.width
3080
3086
 
@@ -414,6 +414,9 @@ class NurbsSurfaceTrimmed:
414
414
  self.m_outer_loop = NurbsCurve()
415
415
  self.m_inner_loops = []
416
416
 
417
+ def has_guid(self) -> bool:
418
+ return getattr(self, '_guid', None) is not None
419
+
417
420
  @property
418
421
  def guid(self) -> str:
419
422
  if getattr(self, '_guid', None) is None:
@@ -1657,7 +1660,8 @@ class NurbsSurfaceTrimmed:
1657
1660
  def pb_dumps(self) -> bytes:
1658
1661
  from .proto import nurbssurface_trimmed_pb2
1659
1662
  proto = nurbssurface_trimmed_pb2.NurbsSurfaceTrimmed()
1660
- proto.guid = self.guid
1663
+ if self.has_guid():
1664
+ proto.guid = self._guid
1661
1665
  proto.name = self.name
1662
1666
  proto.width = self.width
1663
1667
 
@@ -1692,7 +1696,8 @@ class NurbsSurfaceTrimmed:
1692
1696
  proto.ParseFromString(data)
1693
1697
 
1694
1698
  ts = cls()
1695
- ts.guid = proto.guid
1699
+ if proto.guid:
1700
+ ts.guid = proto.guid
1696
1701
  ts.name = proto.name
1697
1702
  ts.width = proto.width
1698
1703
 
@@ -36,6 +36,9 @@ class OBB:
36
36
  self._guid = None
37
37
  self.name = "my_obb"
38
38
 
39
+ def has_guid(self) -> bool:
40
+ return getattr(self, '_guid', None) is not None
41
+
39
42
  @property
40
43
  def guid(self) -> str:
41
44
  if getattr(self, '_guid', None) is None:
@@ -695,7 +698,8 @@ class OBB:
695
698
  proto.y_axis.ParseFromString(self.y_axis.pb_dumps())
696
699
  proto.z_axis.ParseFromString(self.z_axis.pb_dumps())
697
700
  proto.half_size.ParseFromString(self.half_size.pb_dumps())
698
- proto.guid = self.guid
701
+ if self.has_guid():
702
+ proto.guid = self._guid
699
703
  proto.name = self.name
700
704
  return proto.SerializeToString()
701
705
 
@@ -710,7 +714,8 @@ class OBB:
710
714
  z_axis = Vector.pb_loads(proto.z_axis.SerializeToString())
711
715
  half_size = Vector.pb_loads(proto.half_size.SerializeToString())
712
716
  bbox = cls(center, x_axis, y_axis, z_axis, half_size)
713
- bbox.guid = proto.guid
717
+ if proto.guid:
718
+ bbox.guid = proto.guid
714
719
  bbox.name = proto.name
715
720
  return bbox
716
721
 
@@ -161,11 +161,12 @@ def test_obb_protobuf_roundtrip():
161
161
  bb.name = "test_bbox_proto"
162
162
 
163
163
  # Bytes
164
+ guid = bb.guid
164
165
  b = bb.pb_dumps()
165
166
  loaded_s = OBB.pb_loads(b)
166
167
 
167
168
  MINI_CHECK(loaded_s.name == "test_bbox_proto")
168
- MINI_CHECK(loaded_s.guid == bb.guid)
169
+ MINI_CHECK(loaded_s.guid == guid)
169
170
  MINI_CHECK(TOLERANCE.is_close(loaded_s.center[0], 1.0))
170
171
 
171
172
  # File
@@ -61,6 +61,9 @@ class Objects:
61
61
  self.elements: list[Element] = []
62
62
  self.components: list = []
63
63
 
64
+ def has_guid(self) -> bool:
65
+ return getattr(self, '_guid', None) is not None
66
+
64
67
  @property
65
68
  def guid(self) -> str:
66
69
  if getattr(self, '_guid', None) is None:
@@ -172,7 +175,8 @@ class Objects:
172
175
  from .proto import objects_pb2
173
176
  proto = objects_pb2.Objects()
174
177
  proto.name = self.name
175
- proto.guid = self.guid
178
+ if self.has_guid():
179
+ proto.guid = self._guid
176
180
  for p in self.points:
177
181
  proto.points.add().ParseFromString(p.pb_dumps())
178
182
  for l in self.lines:
@@ -201,7 +205,8 @@ class Objects:
201
205
  def from_proto(cls, proto: "objects_pb2.Objects") -> "Objects":
202
206
  """Create Objects from proto message directly (no SerializeToString)."""
203
207
  objects = cls()
204
- objects.guid = proto.guid
208
+ if proto.guid:
209
+ objects.guid = proto.guid
205
210
  objects.name = proto.name
206
211
  for p in proto.points:
207
212
  objects.points.append(Point.pb_loads(p.SerializeToString()))
@@ -81,6 +81,9 @@ class Plane:
81
81
 
82
82
  self._update_equation()
83
83
 
84
+ def has_guid(self) -> bool:
85
+ return getattr(self, '_guid', None) is not None
86
+
84
87
  @property
85
88
  def guid(self) -> str:
86
89
  if getattr(self, '_guid', None) is None:
@@ -931,7 +934,8 @@ class Plane:
931
934
  from .proto import plane_pb2
932
935
 
933
936
  proto = plane_pb2.Plane()
934
- proto.guid = self.guid
937
+ if self.has_guid():
938
+ proto.guid = self._guid
935
939
  proto.name = self.name
936
940
  proto.width = self.width
937
941
 
@@ -980,7 +984,8 @@ class Plane:
980
984
  y_axis = Vector(frame[6], frame[7], frame[8])
981
985
 
982
986
  plane = cls(origin, x_axis, y_axis, width=proto.width if proto.width > 0 else 1.0)
983
- plane.guid = proto.guid
987
+ if proto.guid:
988
+ plane.guid = proto.guid
984
989
  plane.name = proto.name
985
990
 
986
991
  # Load linecolor
@@ -49,6 +49,9 @@ class Point:
49
49
  self.width = 1.0
50
50
  self._pointcolor = None
51
51
 
52
+ def has_guid(self) -> bool:
53
+ return getattr(self, '_guid', None) is not None
54
+
52
55
  @property
53
56
  def guid(self) -> str:
54
57
  if getattr(self, '_guid', None) is None:
@@ -622,7 +625,8 @@ class Point:
622
625
  from .proto import point_pb2
623
626
 
624
627
  proto = point_pb2.Point()
625
- proto.guid = self.guid
628
+ if self.has_guid():
629
+ proto.guid = self._guid
626
630
  proto.name = self.name
627
631
  proto.x = self[0]
628
632
  proto.y = self[1]
@@ -660,7 +664,8 @@ class Point:
660
664
  proto.ParseFromString(data)
661
665
 
662
666
  pt = cls(proto.x, proto.y, proto.z)
663
- pt.guid = proto.guid
667
+ if proto.guid:
668
+ pt.guid = proto.guid
664
669
  pt.name = proto.name
665
670
  pt.width = proto.width
666
671
 
@@ -59,6 +59,9 @@ class PointCloud:
59
59
  for n in normals:
60
60
  self._normals.extend([n[0], n[1], n[2]])
61
61
 
62
+ def has_guid(self) -> bool:
63
+ return getattr(self, '_guid', None) is not None
64
+
62
65
  @property
63
66
  def guid(self) -> str:
64
67
  """Lazy GUID accessor."""
@@ -545,7 +548,8 @@ class PointCloud:
545
548
  from .proto import pointcloud_pb2
546
549
 
547
550
  proto = pointcloud_pb2.PointCloud()
548
- proto.guid = self.guid
551
+ if self.has_guid():
552
+ proto.guid = self._guid
549
553
  proto.name = self.name
550
554
  proto.coords.extend(self.coords)
551
555
  proto.colors.extend(self._colors)
@@ -575,7 +579,8 @@ class PointCloud:
575
579
  list(proto.colors),
576
580
  list(proto.normals)
577
581
  )
578
- pc.guid = proto.guid
582
+ if proto.guid:
583
+ pc.guid = proto.guid
579
584
  pc.name = proto.name
580
585
  pc.point_size = proto.point_size if proto.point_size > 0 else 1.0
581
586
  pc._lod_min = list(proto.lod_min)