mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-28 15:53:00 +00:00
Optimise IfcPatch recipe: make toposort backend configurable
aothms asked for the toposort dependency ordering used by the dedup
walk to try igraph's C-backed topological_sorting() first, since it
should shave off additional time on top of the non-recursive
get_info fix. Falls back to the pure python toposort package with a
warning if igraph is not installed.
Generated with the assistance of an AI coding tool.
(cherry picked from commit 7ebdd046b6)
This commit is contained in:
committed by
Dion Moult
parent
4299968b6e
commit
6dba261e1b
@@ -18,11 +18,18 @@
|
||||
|
||||
# This file was generated with the assistance of an AI coding tool.
|
||||
|
||||
import logging
|
||||
import sys
|
||||
from unittest import mock
|
||||
|
||||
import pytest
|
||||
|
||||
import ifcopenshell
|
||||
import ifcopenshell.guid
|
||||
|
||||
import ifcpatch
|
||||
import test.bootstrap
|
||||
from ifcpatch.recipes.Optimise import _toposort
|
||||
|
||||
|
||||
def add_context(f: ifcopenshell.file) -> ifcopenshell.entity_instance:
|
||||
@@ -71,3 +78,42 @@ class TestOptimise(test.bootstrap.IFC4):
|
||||
assert len(output.by_type("IfcPolyline")) == 2
|
||||
walls_after = output.by_type("IfcWall")
|
||||
assert curve_of(walls_after[0]) != curve_of(walls_after[1])
|
||||
|
||||
def test_folding_still_works_on_the_pure_python_fallback(self):
|
||||
context = add_context(self.file)
|
||||
coords = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 0.0)]
|
||||
add_wall_with_curve(self.file, context, coords)
|
||||
add_wall_with_curve(self.file, context, coords)
|
||||
|
||||
with mock.patch.dict(sys.modules, {"igraph": None}):
|
||||
output = ifcpatch.execute({"file": self.file, "recipe": "Optimise", "arguments": []})
|
||||
|
||||
assert len(output.by_type("IfcPolyline")) == 1
|
||||
|
||||
|
||||
GRAPH = {4: {2, 3}, 2: {1}, 3: {1}, 1: set()}
|
||||
|
||||
|
||||
def assert_dependency_order(order: list[int], graph: dict[int, set[int]]) -> None:
|
||||
position = {id_: i for i, id_ in enumerate(order)}
|
||||
assert sorted(order) == sorted(graph)
|
||||
for id_, references in graph.items():
|
||||
for reference in references:
|
||||
assert position[reference] < position[id_]
|
||||
|
||||
|
||||
class TestToposortBackends:
|
||||
def test_igraph_backend_orders_dependencies_first(self):
|
||||
pytest.importorskip("igraph")
|
||||
assert_dependency_order(_toposort(GRAPH, logging.getLogger(__name__)), GRAPH)
|
||||
|
||||
def test_igraph_backend_includes_references_missing_from_the_keys(self):
|
||||
pytest.importorskip("igraph")
|
||||
assert _toposort({2: {1}}, logging.getLogger(__name__)) == [1, 2]
|
||||
|
||||
def test_pure_python_fallback_warns_when_igraph_is_unavailable(self, caplog):
|
||||
with mock.patch.dict(sys.modules, {"igraph": None}):
|
||||
with caplog.at_level(logging.WARNING):
|
||||
order = _toposort(GRAPH, logging.getLogger(__name__))
|
||||
assert_dependency_order(order, GRAPH)
|
||||
assert "python-igraph" in caplog.text
|
||||
|
||||
Reference in New Issue
Block a user