mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-18 14:31:39 +00:00
ifcquery/ifcedit: enable shell scripting by composing query and edit commands
Add --format ids to ifcquery to output step IDs suitable for piping into ifcedit parameters. Add ifcedit foreach to apply an operation to every element in a query result. Extend clash and relations output so --format ids extracts all involved element IDs, enabling one-liners like clash detection piped directly into render. Generated with the assistance of an AI coding tool.
This commit is contained in:
@@ -82,3 +82,40 @@ class TestCLI:
|
||||
def test_no_command(self, ifc_path):
|
||||
rc, stdout, stderr = run_ifcquery(ifc_path)
|
||||
assert rc != 0
|
||||
|
||||
def test_select_ids_format(self, ifc_path):
|
||||
rc, stdout, stderr = run_ifcquery(ifc_path, "--format", "ids", "select", "IfcWall")
|
||||
assert rc == 0
|
||||
# Should be a comma-separated string of integers with no surrounding whitespace
|
||||
ids = stdout.strip()
|
||||
assert ids != ""
|
||||
for part in ids.split(","):
|
||||
assert part.isdigit()
|
||||
|
||||
def test_select_ids_format_multiple(self, ifc_path, model):
|
||||
rc, stdout, stderr = run_ifcquery(ifc_path, "--format", "ids", "select", "IfcElement")
|
||||
assert rc == 0
|
||||
ids = stdout.strip().split(",")
|
||||
assert len(ids) >= 2
|
||||
|
||||
def test_ids_format_empty_result(self, ifc_path):
|
||||
rc, stdout, stderr = run_ifcquery(ifc_path, "--format", "ids", "select", "IfcDoor")
|
||||
assert rc == 0
|
||||
assert stdout.strip() == ""
|
||||
|
||||
def test_relations_ids_format(self, ifc_path, model):
|
||||
storey = model.by_type("IfcBuildingStorey")[0]
|
||||
rc, stdout, stderr = run_ifcquery(ifc_path, "--format", "ids", "relations", str(storey.id()))
|
||||
assert rc == 0
|
||||
ids = stdout.strip().split(",")
|
||||
assert all(i.isdigit() for i in ids)
|
||||
# should include the storey itself and its contained elements
|
||||
assert str(storey.id()) in ids
|
||||
wall_id = str(model.by_type("IfcWall")[0].id())
|
||||
assert wall_id in ids
|
||||
|
||||
def test_info_ids_format(self, ifc_path, model):
|
||||
wall = model.by_type("IfcWall")[0]
|
||||
rc, stdout, stderr = run_ifcquery(ifc_path, "--format", "ids", "info", str(wall.id()))
|
||||
assert rc == 0
|
||||
assert stdout.strip() == str(wall.id())
|
||||
|
||||
@@ -91,6 +91,47 @@ class TestTraverseUp:
|
||||
assert len(chain) == 4 # storey -> building -> site -> project
|
||||
|
||||
|
||||
class TestElementsSummary:
|
||||
def test_wall_elements_includes_self(self, model):
|
||||
wall = model.by_type("IfcWall")[0]
|
||||
result = relations(model, wall)
|
||||
ids = [e["id"] for e in result["elements"]]
|
||||
assert wall.id() in ids
|
||||
|
||||
def test_wall_elements_includes_container(self, model):
|
||||
wall = model.by_type("IfcWall")[0]
|
||||
result = relations(model, wall)
|
||||
ids = [e["id"] for e in result["elements"]]
|
||||
storey = model.by_type("IfcBuildingStorey")[0]
|
||||
assert storey.id() in ids
|
||||
|
||||
def test_storey_elements_includes_contained(self, model):
|
||||
storey = model.by_type("IfcBuildingStorey")[0]
|
||||
result = relations(model, storey)
|
||||
ids = [e["id"] for e in result["elements"]]
|
||||
wall = model.by_type("IfcWall")[0]
|
||||
assert wall.id() in ids
|
||||
|
||||
def test_elements_no_duplicates(self, model):
|
||||
storey = model.by_type("IfcBuildingStorey")[0]
|
||||
result = relations(model, storey)
|
||||
ids = [e["id"] for e in result["elements"]]
|
||||
assert len(ids) == len(set(ids))
|
||||
|
||||
def test_elements_all_have_id_and_type(self, model):
|
||||
wall = model.by_type("IfcWall")[0]
|
||||
result = relations(model, wall)
|
||||
for e in result["elements"]:
|
||||
assert "id" in e
|
||||
assert "type" in e
|
||||
|
||||
def test_traverse_up_has_no_elements_field(self, model):
|
||||
wall = model.by_type("IfcWall")[0]
|
||||
result = relations(model, wall, traverse="up")
|
||||
assert isinstance(result, list)
|
||||
assert not any("elements" in item for item in result)
|
||||
|
||||
|
||||
class TestJsonSerializable:
|
||||
def test_relations_serializable(self, model):
|
||||
wall = model.by_type("IfcWall")[0]
|
||||
|
||||
Reference in New Issue
Block a user