Reimplement adding multiple references / schedules cf5ffad9af

Previously it was implemented inline. This now implements it as a
tool.Blender function with tests. Also the previous tests didn't
actually run and weren't actually testing any tools despite being in a
tool tests.
This commit is contained in:
Dion Moult
2026-02-17 11:18:24 +11:00
parent e20e286168
commit 37fe0ad993
3 changed files with 56 additions and 4 deletions
@@ -2896,12 +2896,16 @@ class AddSchedule(bpy.types.Operator, tool.Ifc.Operator, ImportHelper):
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
bl_description = "Add an .ods, .xls or .xlsx file as a schedule" bl_description = "Add an .ods, .xls or .xlsx file as a schedule"
files: bpy.props.CollectionProperty(name="Files", type=bpy.types.OperatorFileListElement)
directory: bpy.props.StringProperty(subtype="DIR_PATH")
filter_glob: bpy.props.StringProperty(default="*.ods;*.xls;*.xlsx", options={"HIDDEN"}) filter_glob: bpy.props.StringProperty(default="*.ods;*.xls;*.xlsx", options={"HIDDEN"})
use_relative_path: bpy.props.BoolProperty(name="Use Relative Path", default=True) use_relative_path: bpy.props.BoolProperty(name="Use Relative Path", default=True)
def _execute(self, context): def _execute(self, context):
filepath = tool.Ifc.get_uri(self.filepath, use_relative_path=self.use_relative_path) for filepath in tool.Blender.get_selected_files(
core.add_document(tool.Ifc, tool.Drawing, "SCHEDULE", uri=filepath) self.directory, self.files, use_relative_path=self.use_relative_path
):
core.add_document(tool.Ifc, tool.Drawing, "SCHEDULE", uri=filepath)
class RemoveSchedule(bpy.types.Operator, tool.Ifc.Operator): class RemoveSchedule(bpy.types.Operator, tool.Ifc.Operator):
@@ -3090,13 +3094,17 @@ class AddReference(bpy.types.Operator, tool.Ifc.Operator, ImportHelper):
bl_description = "Import a .svg file to the project as a reference" bl_description = "Import a .svg file to the project as a reference"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
files: bpy.props.CollectionProperty(name="Files", type=bpy.types.OperatorFileListElement)
directory: bpy.props.StringProperty(subtype="DIR_PATH")
filter_glob: bpy.props.StringProperty(default="*.svg", options={"HIDDEN"}) filter_glob: bpy.props.StringProperty(default="*.svg", options={"HIDDEN"})
use_relative_path: bpy.props.BoolProperty(name="Use Relative Path", default=True) use_relative_path: bpy.props.BoolProperty(name="Use Relative Path", default=True)
filename_ext = ".svg" filename_ext = ".svg"
def _execute(self, context): def _execute(self, context):
filepath = tool.Ifc.get_uri(self.filepath, use_relative_path=self.use_relative_path) for filepath in tool.Blender.get_selected_files(
core.add_document(tool.Ifc, tool.Drawing, "REFERENCE", uri=filepath) self.directory, self.files, use_relative_path=self.use_relative_path
):
core.add_document(tool.Ifc, tool.Drawing, "REFERENCE", uri=filepath)
class RemoveReference(bpy.types.Operator, tool.Ifc.Operator): class RemoveReference(bpy.types.Operator, tool.Ifc.Operator):
+10
View File
@@ -2165,3 +2165,13 @@ class Blender(bonsai.core.tool.Blender):
if cls.BLENDER_5: if cls.BLENDER_5:
return np.array(mathutils_type) return np.array(mathutils_type)
return np.array(mathutils_type, dtype=np.float32) return np.array(mathutils_type, dtype=np.float32)
@classmethod
def get_selected_files(
cls, directory: str, files: bpy.types.OperatorFileListElement, use_relative_path=False
) -> list[Path]:
return [
tool.Ifc.get_uri(Path(directory) / f.name, use_relative_path=use_relative_path)
for f in files
if (Path(directory) / f.name).is_file()
]
+34
View File
@@ -24,8 +24,10 @@ import pytest
import bonsai.core.tool import bonsai.core.tool
import bonsai.tool as tool import bonsai.tool as tool
import tempfile
from bonsai.tool.blender import Blender as subject from bonsai.tool.blender import Blender as subject
from test.bim.bootstrap import NewFile from test.bim.bootstrap import NewFile
from pathlib import Path
if TYPE_CHECKING: if TYPE_CHECKING:
import bpy.stub_internal.rna_enums as rna_enums import bpy.stub_internal.rna_enums as rna_enums
@@ -110,3 +112,35 @@ class TestBlenderErrorMessageExtraction(NewFile):
assert error_reports == [] assert error_reports == []
bpy.utils.unregister_class(OBJECT_OT_test_fail_operator) bpy.utils.unregister_class(OBJECT_OT_test_fail_operator)
class TestGetSelectedFiles(NewFile):
def test_get_a_single_file(self) -> None:
with tempfile.NamedTemporaryFile() as f:
file = type("", (object,), {"name": f.name})()
assert subject.get_selected_files(Path(f.name).parent, [file]) == [f.name]
def test_get_multiple_files(self) -> None:
with tempfile.NamedTemporaryFile() as f:
with tempfile.NamedTemporaryFile() as g:
file = type("", (object,), {"name": f.name})()
file2 = type("", (object,), {"name": g.name})()
assert subject.get_selected_files(Path(f.name).parent, [file, file2]) == [f.name, g.name]
def test_exclude_directories(self) -> None:
with tempfile.NamedTemporaryFile() as f:
with tempfile.TemporaryDirectory() as d:
file = type("", (object,), {"name": f.name})()
directory = type("", (object,), {"name": d})()
assert subject.get_selected_files(Path(f.name).parent, [file, directory]) == [f.name]
def test_get_relative_paths(self) -> None:
with tempfile.TemporaryDirectory() as tmp_dir:
base_path = Path(tmp_dir)
with tempfile.NamedTemporaryFile(dir=tmp_dir, suffix=".ifc") as f:
tool.Ifc.set_path(str(f.name))
with tempfile.NamedTemporaryFile(dir=tmp_dir) as g:
file = type("", (object,), {"name": g.name})
assert subject.get_selected_files(Path(g.name).parent, [file], use_relative_path=True) == [
Path(g.name).name
]