- Introduced color_image.py for preparing standalone color images for tests. - Added hdr_image.py to create HDR textures for testing. - Implemented test_image_depth_panorama.py to evaluate panorama topology, UVs, and depth discontinuities. - Created test_shadeless.py to validate the opacity and HDR color endpoints of the Shadeless group. - Developed moge3_export.py for exporting dynamic MoGe-3 backbone and ONNX graphs. - Added material.py to inherit material slots onto generated geometry. - Built image_depth_panorama.py to construct a quad panorama with depth separation and sampling.
78 lines
3.3 KiB
Python
78 lines
3.3 KiB
Python
from unittest.mock import patch
|
|
|
|
import bpy
|
|
import pytest
|
|
|
|
from anyimage.operators import ai_setup, remove_background
|
|
from anyimage.operators.convert_to_plane import operators as plane
|
|
|
|
|
|
@pytest.mark.parametrize("kind", ["background", "depth", "relief"])
|
|
def test_nested_native_operator_preserves_plain_error(kind, tmp_path, capfd):
|
|
reason = "Unsupported input format: .tiff"
|
|
if kind == "background":
|
|
inner, outer = remove_background.RunBackgroundRemoval, remove_background.RemoveImageBackground
|
|
else:
|
|
inner = plane.GenerateDepthPlane
|
|
outer = plane.ConvertToDepthPlane if kind == "depth" else plane.ConvertToReliefPlane
|
|
|
|
def reject(operator, context):
|
|
operator.report({"ERROR"}, reason)
|
|
return {"CANCELLED"}
|
|
|
|
prepared = tmp_path / "prepared"
|
|
prepared.mkdir()
|
|
path = prepared / "input.png"
|
|
path.touch()
|
|
with (
|
|
patch.object(inner, "execute", reject),
|
|
patch.object(outer, "poll", classmethod(lambda cls, context: True)),
|
|
patch.object(plane, "invoke_ai_setup_if_needed", return_value=None),
|
|
patch.object(plane, "prepare_material_color_input", return_value=path),
|
|
patch.object(plane, "material_analysis_input", return_value=path),
|
|
patch.object(plane, "depth_plane_settings", return_value=("model", 5)),
|
|
patch.object(plane, "configured_max_ai_input_size", return_value=2048),
|
|
):
|
|
owner = bpy.data.objects.new("Native validation source", None)
|
|
image = bpy.data.images.new("Native validation image", width=1, height=1)
|
|
owner.empty_display_type = "IMAGE"
|
|
owner.data = image
|
|
bpy.context.scene.collection.objects.link(owner)
|
|
bpy.context.view_layer.objects.active = owner
|
|
bpy.utils.register_class(inner)
|
|
bpy.utils.register_class(outer)
|
|
try:
|
|
with pytest.raises(RuntimeError) as error:
|
|
getattr(bpy.ops.anyimage, outer.bl_idname.split(".")[1])()
|
|
assert str(error.value).strip() == f"Error: {reason}"
|
|
assert "Traceback" not in capfd.readouterr().err
|
|
if kind != "background":
|
|
assert not prepared.exists()
|
|
finally:
|
|
bpy.utils.unregister_class(outer)
|
|
bpy.utils.unregister_class(inner)
|
|
bpy.data.objects.remove(owner, do_unlink=True)
|
|
bpy.data.images.remove(image)
|
|
|
|
|
|
def test_native_setup_operator_preserves_plain_error(capfd):
|
|
class RejectInstall(bpy.types.Operator):
|
|
bl_idname = "anyimage.install_environment"
|
|
bl_label = "Reject Install"
|
|
|
|
def execute(self, context):
|
|
self.report({"ERROR"}, "Setup unavailable")
|
|
return {"CANCELLED"}
|
|
|
|
with patch.object(ai_setup, "ai_status", return_value={"ready": False, "environment_ready": False}):
|
|
bpy.utils.register_class(RejectInstall)
|
|
bpy.utils.register_class(ai_setup.SetupAIEnvironment)
|
|
try:
|
|
with pytest.raises(RuntimeError) as error:
|
|
bpy.ops.anyimage.setup_ai_environment(use_mirror=False)
|
|
assert str(error.value).strip() == "Error: Setup unavailable"
|
|
assert "Traceback" not in capfd.readouterr().err
|
|
finally:
|
|
bpy.utils.unregister_class(ai_setup.SetupAIEnvironment)
|
|
bpy.utils.unregister_class(RejectInstall)
|