diff --git a/src/ifcopenshell-python/ifcopenshell/api/sequence/cascade_schedule.py b/src/ifcopenshell-python/ifcopenshell/api/sequence/cascade_schedule.py
index abb869b452..834a32661d 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/sequence/cascade_schedule.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/sequence/cascade_schedule.py
@@ -44,7 +44,7 @@ class Usecase:
else:
print("... is a predecessor to ...", debug_task)
print("... which is cyclically a predecessor to ...", task)
- raise Exception("Recursive tasks found. Could not cascade schedule.")
+ raise RecursionError("Recursive tasks found. Could not cascade schedule.")
if not task.TaskTime:
return
diff --git a/src/ifcopenshell-python/ifcopenshell/api/sequence/recalculate_schedule.py b/src/ifcopenshell-python/ifcopenshell/api/sequence/recalculate_schedule.py
index db6d26249a..257b94668c 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/sequence/recalculate_schedule.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/sequence/recalculate_schedule.py
@@ -62,7 +62,7 @@ class Usecase:
break # We have an infinite loop due to a cyclic graph
if is_cyclic:
- raise Exception("Task graph is cyclic and so critical path method cannot be performed.")
+ raise RecursionError("Task graph is cyclic and so critical path method cannot be performed.")
return
self.pending_nodes = set(self.g.nodes)
diff --git a/src/ifcopenshell-python/test/api/sequence/test_cascade_schedule.py b/src/ifcopenshell-python/test/api/sequence/test_cascade_schedule.py
index 48e101559b..9e5f8aa308 100644
--- a/src/ifcopenshell-python/test/api/sequence/test_cascade_schedule.py
+++ b/src/ifcopenshell-python/test/api/sequence/test_cascade_schedule.py
@@ -16,6 +16,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with IfcOpenShell. If not, see .
+import pytest
import datetime
import test.bootstrap
import ifcopenshell.api
@@ -53,6 +54,14 @@ class TestCascadeSchedule(test.bootstrap.IFC4):
assert task3.TaskTime.ScheduleStart == "2000-01-02T09:00:00"
assert task3.TaskTime.ScheduleFinish == "2000-01-04T17:00:00"
+ def test_catching_cyclic_relationships(self):
+ task = self._create_task("P1D")
+ task2 = self._create_task("P2D")
+ self._create_sequence(task, task2, "FINISH_START")
+ with pytest.raises(RecursionError):
+ self._create_sequence(task2, task, "FINISH_START")
+ ifcopenshell.api.run("sequence.cascade_schedule", self.file, task=task)
+
def test_cascading_finish_to_start(self):
task = self._create_task("P1D")
task2 = self._create_task("P2D")
diff --git a/src/ifcopenshell-python/test/api/sequence/test_recalculate_schedule.py b/src/ifcopenshell-python/test/api/sequence/test_recalculate_schedule.py
index 399bd132cc..74ef955d66 100644
--- a/src/ifcopenshell-python/test/api/sequence/test_recalculate_schedule.py
+++ b/src/ifcopenshell-python/test/api/sequence/test_recalculate_schedule.py
@@ -16,6 +16,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with IfcOpenShell. If not, see .
+import pytest
import datetime
import test.bootstrap
import ifcopenshell.api
@@ -29,6 +30,20 @@ class TestRecalculateSchedule(test.bootstrap.IFC4):
ifcopenshell.api.run("sequence.recalculate_schedule", self.file, work_schedule=self.work_schedule)
assert task.TaskTime is None
+ def test_catching_cyclic_relationships(self):
+ self._add_work_schedule()
+ task = self._create_task("P1D")
+ task2 = self._create_task("P2D")
+ task3 = self._create_task("P2D")
+ task4 = self._create_task("P2D")
+ self._create_sequence(task, task2, "FINISH_START")
+ self._create_sequence(task, task4, "FINISH_START")
+ self._create_sequence(task2, task3, "FINISH_START")
+ with pytest.raises(RecursionError):
+ self._create_sequence(task3, task2, "FINISH_START")
+ with pytest.raises(RecursionError):
+ ifcopenshell.api.run("sequence.recalculate_schedule", self.file, work_schedule=self.work_schedule)
+
def test_recalculating_for_a_single_task(self):
self._add_work_schedule()
task = self._create_task("P1D")