Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions packages/tree_clipper/src/tree_clipper/import_nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,21 @@ def deserializer(
if self.debug_prints:
print(f"{prop_from_root.to_str()}: missing, assume not set")
continue

# https://github.com/Algebraic-UG/tree_clipper/issues/161
if (
prop.type in [PROP_TYPE_POINTER, PROP_TYPE_COLLECTION]
and prop.fixed_type.__module__ != "_bpy_types"
):
self.report.warnings.append(
f"""This property is missing in serialization.
It appears to be from a third-party addon: {prop.fixed_type.__module__}

Tree Clipper is skipping it.
{prop_from_root.to_str()}"""
)
continue

self._error_out(
getter=getter,
reason="missing property in serialization",
Expand Down
132 changes: 132 additions & 0 deletions packages/tree_clipper/tests/test_third_party_attributes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import bpy

from tree_clipper.import_nodes import ImportIntermediate, ImportParameters
from tree_clipper.specific_handlers import BUILT_IN_EXPORTER, BUILT_IN_IMPORTER

from .util import (
make_test_node_tree,
round_trip_without_external,
export_to_string,
diff_exports,
)


# just to pick any node that isn't specifically handled
# that is the "worst case" scenario
def test_third_party_node_type_to_test():
assert bpy.types.NodeGroupInput not in BUILT_IN_EXPORTER
assert bpy.types.NodeGroupInput not in BUILT_IN_IMPORTER


class TreeClipperTest(bpy.types.PropertyGroup):
foo: bpy.props.StringProperty() # ty:ignore


def register_third_party_properties():
# simple properties
bpy.types.NodeGroupInput.tree_clipper_test_bool = bpy.props.BoolProperty()
bpy.types.NodeGroupInput.tree_clipper_test_enum = bpy.props.EnumProperty(
items=[("foo",) * 3]
)
bpy.types.NodeGroupInput.tree_clipper_test_float = bpy.props.FloatProperty()
bpy.types.NodeGroupInput.tree_clipper_test_int = bpy.props.IntProperty()
bpy.types.NodeGroupInput.tree_clipper_test_string = bpy.props.StringProperty()

# pointer property
bpy.utils.register_class(TreeClipperTest)
bpy.types.NodeGroupInput.tree_clipper_test_pointer = bpy.props.PointerProperty(
type=TreeClipperTest
)

# collection property
bpy.types.NodeGroupInput.tree_clipper_test_collection = (
bpy.props.CollectionProperty(type=TreeClipperTest)
)


def unregister_third_party_properties():
del bpy.types.NodeGroupInput.tree_clipper_test_bool
del bpy.types.NodeGroupInput.tree_clipper_test_enum
del bpy.types.NodeGroupInput.tree_clipper_test_float
del bpy.types.NodeGroupInput.tree_clipper_test_int
del bpy.types.NodeGroupInput.tree_clipper_test_string
del bpy.types.NodeGroupInput.tree_clipper_test_pointer
del bpy.types.NodeGroupInput.tree_clipper_test_collection

bpy.utils.unregister_class(TreeClipperTest)


def test_third_party_both_have_it():
try:
register_third_party_properties()

tree = make_test_node_tree()
tree.nodes.new("NodeGroupInput")

round_trip_without_external(tree.name)

finally:
unregister_third_party_properties()


def test_third_party_only_exporter_has_it():
try:
register_third_party_properties()

tree = make_test_node_tree()
tree.nodes.new("NodeGroupInput")
original_name = tree.name

before = export_to_string(original_name)

unregister_third_party_properties()

import_intermediate = ImportIntermediate(string=before)
import_report = import_intermediate.import_all(
parameters=ImportParameters(
specific_handlers=BUILT_IN_IMPORTER,
debug_prints=True,
)
)

after = export_to_string(import_report.renames_node_group[original_name])

try:
diff_exports(before=before, import_report=import_report, after=after)
assert False, "diff should be the properties"
except:

Check failure on line 97 in packages/tree_clipper/tests/test_third_party_attributes.py

View workflow job for this annotation

GitHub Actions / Check code style

ruff (E722)

packages/tree_clipper/tests/test_third_party_attributes.py:97:9: E722 Do not use bare `except`
pass

register_third_party_properties()
finally:
unregister_third_party_properties()


def test_third_party_only_impoter_has_it():
try:
tree = make_test_node_tree()
tree.nodes.new("NodeGroupInput")
original_name = tree.name

before = export_to_string(original_name)

register_third_party_properties()

import_intermediate = ImportIntermediate(string=before)
import_report = import_intermediate.import_all(
parameters=ImportParameters(
specific_handlers=BUILT_IN_IMPORTER,
debug_prints=True,
)
)

after = export_to_string(import_report.renames_node_group[original_name])

try:
diff_exports(before=before, import_report=import_report, after=after)
assert False, "diff should be the properties"
except:

Check failure on line 128 in packages/tree_clipper/tests/test_third_party_attributes.py

View workflow job for this annotation

GitHub Actions / Check code style

ruff (E722)

packages/tree_clipper/tests/test_third_party_attributes.py:128:9: E722 Do not use bare `except`
pass

finally:
unregister_third_party_properties()
33 changes: 17 additions & 16 deletions packages/tree_clipper/tests/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,26 +78,27 @@ def diff_exports(
assert diff == {}


def round_trip_without_external(original_name: str):
def export_to_string(name: str) -> str:
export_intermediate = ExportIntermediate(
parameters=ExportParameters(
is_material=False,
name=name,
specific_handlers=BUILT_IN_EXPORTER,
export_sub_trees=True,
debug_prints=True,
write_from_roots=False,
)
def export_to_string(name: str) -> str:
export_intermediate = ExportIntermediate(
parameters=ExportParameters(
is_material=False,
name=name,
specific_handlers=BUILT_IN_EXPORTER,
export_sub_trees=True,
debug_prints=True,
write_from_roots=False,
)
)

while export_intermediate.step():
pass
while export_intermediate.step():
pass

string = export_intermediate.export_to_str(compress=False, json_indent=4)
print(string)
return string

string = export_intermediate.export_to_str(compress=False, json_indent=4)
print(string)
return string

def round_trip_without_external(original_name: str):
before = export_to_string(original_name)

import_intermediate = ImportIntermediate(string=before)
Expand Down
Loading