control.assign_control to support batching

This commit is contained in:
Andrej730
2025-09-09 11:14:57 +05:00
parent fcb263f59a
commit abfb56350d
23 changed files with 104 additions and 50 deletions
+4 -6
View File
@@ -135,10 +135,8 @@ def assign_cost_item_type(
List of found product types. List of found product types.
""" """
product_types = list(spatial.get_selected_product_types()) product_types = list(spatial.get_selected_product_types())
rels = [ ifc.run("control.assign_control", relating_control=cost_item, related_objects=product_types)
ifc.run("control.assign_control", relating_control=cost_item, related_object=product_type)
for product_type in product_types
]
cost.load_cost_item_types(cost_item) cost.load_cost_item_types(cost_item)
return product_types return product_types
@@ -213,10 +211,10 @@ def assign_cost_value(
ifc.run("cost.assign_cost_value", cost_item=cost_item, cost_rate=cost_rate) ifc.run("cost.assign_cost_value", cost_item=cost_item, cost_rate=cost_rate)
existing_cost_rate = cost.get_assigned_rate_cost_item(cost_item) existing_cost_rate = cost.get_assigned_rate_cost_item(cost_item)
if existing_cost_rate is None: if existing_cost_rate is None:
ifc.run("control.assign_control", relating_control=cost_rate, related_object=cost_item) ifc.run("control.assign_control", relating_control=cost_rate, related_objects=[cost_item])
else: else:
ifc.run("control.unassign_control", relating_control=existing_cost_rate, related_object=cost_item) ifc.run("control.unassign_control", relating_control=existing_cost_rate, related_object=cost_item)
ifc.run("control.assign_control", relating_control=cost_rate, related_object=cost_item) ifc.run("control.assign_control", relating_control=cost_rate, related_objects=[cost_item])
def load_schedule_of_rates(cost: type[tool.Cost], schedule_of_rates: ifcopenshell.entity_instance) -> None: def load_schedule_of_rates(cost: type[tool.Cost], schedule_of_rates: ifcopenshell.entity_instance) -> None:
+1 -1
View File
@@ -422,7 +422,7 @@ def edit_task_calendar(
task: ifcopenshell.entity_instance, task: ifcopenshell.entity_instance,
work_calendar: ifcopenshell.entity_instance, work_calendar: ifcopenshell.entity_instance,
) -> None: ) -> None:
ifc.run("control.assign_control", relating_control=work_calendar, related_object=task) ifc.run("control.assign_control", relating_control=work_calendar, related_objects=[task])
ifc.run("sequence.cascade_schedule", task=task) ifc.run("sequence.cascade_schedule", task=task)
sequence.load_task_properties() sequence.load_task_properties()
+2 -1
View File
@@ -261,6 +261,7 @@ class ScheduleIfcGenerator:
wbs: Union[WBSEntry, None], wbs: Union[WBSEntry, None],
work_schedule: Union[ifcopenshell.entity_instance, None], work_schedule: Union[ifcopenshell.entity_instance, None],
) -> None: ) -> None:
assert self.file
activity["ifc"] = ifcopenshell.api.sequence.add_task( activity["ifc"] = ifcopenshell.api.sequence.add_task(
self.file, self.file,
work_schedule=None if wbs else work_schedule, work_schedule=None if wbs else work_schedule,
@@ -283,7 +284,7 @@ class ScheduleIfcGenerator:
ifcopenshell.api.control.assign_control( ifcopenshell.api.control.assign_control(
self.file, self.file,
relating_control=calendar["ifc"], relating_control=calendar["ifc"],
related_object=activity["ifc"], related_objects=[activity["ifc"]],
) )
ifcopenshell.api.sequence.edit_task_time( ifcopenshell.api.sequence.edit_task_time(
self.file, self.file,
+1 -1
View File
@@ -263,7 +263,7 @@ class MSP2Ifc:
ifcopenshell.api.control.assign_control( ifcopenshell.api.control.assign_control(
self.file, self.file,
relating_control=calendar, relating_control=calendar,
related_object=task["ifc"], related_objects=[task["ifc"]],
) )
ifcopenshell.api.sequence.edit_task( ifcopenshell.api.sequence.edit_task(
+3 -2
View File
@@ -20,6 +20,7 @@ from __future__ import annotations
import csv import csv
import ifcopenshell import ifcopenshell
import ifcopenshell.api import ifcopenshell.api
import ifcopenshell.api.control
import ifcopenshell.api.cost import ifcopenshell.api.cost
import ifcopenshell.api.root import ifcopenshell.api.root
import ifcopenshell.util.unit import ifcopenshell.util.unit
@@ -353,14 +354,14 @@ class Csv2Ifc:
existing_cost_rate = assignment.RelatingControl existing_cost_rate = assignment.RelatingControl
if existing_cost_rate is None: if existing_cost_rate is None:
ifcopenshell.api.control.assign_control( ifcopenshell.api.control.assign_control(
self.file, relating_control=rate_cost_item, related_object=cost_item["ifc"] self.file, relating_control=rate_cost_item, related_objects=[cost_item["ifc"]]
) )
else: else:
ifcopenshell.api.control.unassign_control( ifcopenshell.api.control.unassign_control(
self.file, relating_control=existing_cost_rate, related_object=cost_item["ifc"] self.file, relating_control=existing_cost_rate, related_object=cost_item["ifc"]
) )
ifcopenshell.api.control.assign_control( ifcopenshell.api.control.assign_control(
self.file, relating_control=rate_cost_item, related_object=cost_item["ifc"] self.file, relating_control=rate_cost_item, related_objects=[cost_item["ifc"]]
) )
else: else:
print(f"No cost item found with RateID={cost_rate['RateID']}") print(f"No cost item found with RateID={cost_rate['RateID']}")
@@ -53,6 +53,22 @@ pre_listeners: dict[str, dict] = {}
post_listeners: dict[str, dict] = {} post_listeners: dict[str, dict] = {}
def batching_argument_deprecation(
usecase_path: str, settings: dict, prev_argument: str, new_argument: str, replace_usecase: Optional[str] = None
) -> tuple[str, dict]:
if replace_usecase is not None:
print(f"WARNING. `{usecase_path}` api method is deprecated and should be replaced with `{replace_usecase}`.")
if prev_argument in settings:
print(
f"WARNING. `{prev_argument}` argument is deprecated for API method "
f'"{usecase_path}" and should be replaced with `{new_argument}`.'
)
settings = settings | {new_argument: [settings[prev_argument]]}
settings.pop(prev_argument)
return (replace_usecase or usecase_path, settings)
def renamed_arguments_deprecation( def renamed_arguments_deprecation(
usecase_path: str, settings: dict, arguments_remapped: dict[str, str] usecase_path: str, settings: dict, arguments_remapped: dict[str, str]
) -> tuple[str, dict]: ) -> tuple[str, dict]:
@@ -71,7 +87,11 @@ def renamed_arguments_deprecation(
# "group.add_group": partial( # "group.add_group": partial(
# renamed_arguments_deprecation, arguments_remapped={"Name": "name", "Description": "description"} # renamed_arguments_deprecation, arguments_remapped={"Name": "name", "Description": "description"}
# ), # ),
ARGUMENTS_DEPRECATION: dict[str, Callable[[str, dict[str, Any]], tuple[str, dict[str, Any]]]] = {} ARGUMENTS_DEPRECATION: dict[str, Callable[[str, dict[str, Any]], tuple[str, dict[str, Any]]]] = {
"control.assign_control": partial(
batching_argument_deprecation, prev_argument="related_object", new_argument="related_objects"
),
}
CACHED_USECASE_CLASSES: dict[str, Callable] = {} CACHED_USECASE_CLASSES: dict[str, Callable] = {}
@@ -25,9 +25,9 @@ from typing import Union
def assign_control( def assign_control(
file: ifcopenshell.file, file: ifcopenshell.file,
relating_control: ifcopenshell.entity_instance, relating_control: ifcopenshell.entity_instance,
related_object: ifcopenshell.entity_instance, related_objects: list[ifcopenshell.entity_instance],
) -> Union[ifcopenshell.entity_instance, None]: ) -> Union[ifcopenshell.entity_instance, None]:
"""Assigns a planning control or constraint to an object """Assigns a planning control or constraint to a list of objects.
IFC can describe concepts that control other objects. For example, a IFC can describe concepts that control other objects. For example, a
planning calendar controls the availability of working days for planning calendar controls the availability of working days for
@@ -42,7 +42,7 @@ def assign_control(
:param relating_control: The IfcControl entity that is creating the :param relating_control: The IfcControl entity that is creating the
control or constraint control or constraint
:param related_object: The IfcObjectDefinition that is being controlled :param related_objects: The list of IfcObjectDefinition that is being controlled
:return: The newly created IfcRelAssignsToControl. If relationship already :return: The newly created IfcRelAssignsToControl. If relationship already
existed before and wasn't changed then returns None. existed before and wasn't changed then returns None.
@@ -59,7 +59,7 @@ def assign_control(
# All subtasks will inherit this calendar, so assigning a single # All subtasks will inherit this calendar, so assigning a single
# calendar to the root task effectively defines a "default" calendar # calendar to the root task effectively defines a "default" calendar
ifcopenshell.api.control.assign_control(model, ifcopenshell.api.control.assign_control(model,
relating_control=calendar, related_object=task) relating_control=calendar, related_objects=[task])
# Another common example might be relating a cost item and a product # Another common example might be relating a cost item and a product
wall = ifcopenshell.api.root.create_entity(model, ifc_class="IfcWall") wall = ifcopenshell.api.root.create_entity(model, ifc_class="IfcWall")
@@ -67,22 +67,33 @@ def assign_control(
cost_item = ifcopenshell.api.cost.add_cost_item(model, cost_item = ifcopenshell.api.cost.add_cost_item(model,
cost_schedule=schedule) cost_schedule=schedule)
ifcopenshell.api.control.assign_control(model, ifcopenshell.api.control.assign_control(model,
relating_control=cost_item, related_object=wall) relating_control=cost_item, related_objects=[wall])
""" """
if related_object.HasAssignments: # Filter out already assigned objects.
for assignment in related_object.HasAssignments: related_objects_set = set(related_objects)
if assignment.is_a("IfcRelAssignsToControl") and assignment.RelatingControl == relating_control: objects_to_assign: set[ifcopenshell.entity_instance] = set()
return
control_assignments = set(relating_control.Controls)
if control_assignments:
for obj in related_objects_set:
existing_assignment = next((a for a in obj.HasAssignments if a in control_assignments), None)
# Skip objects already assigned to this control.
if existing_assignment:
continue
objects_to_assign.add(obj)
else:
objects_to_assign = related_objects_set
if not objects_to_assign:
return None
controls: Union[ifcopenshell.entity_instance, None] controls: Union[ifcopenshell.entity_instance, None]
controls = next(iter(relating_control.Controls), None) controls = next(iter(relating_control.Controls), None)
if controls: if controls:
if related_object in controls.RelatedObjects: related_objects_new: list[ifcopenshell.entity_instance] = list(controls.RelatedObjects)
return related_objects_new.extend(objects_to_assign)
related_objects = set(controls.RelatedObjects) controls.RelatedObjects = list(related_objects_new)
related_objects.add(related_object)
controls.RelatedObjects = list(related_objects)
ifcopenshell.api.owner.update_owner_history(file, element=controls) ifcopenshell.api.owner.update_owner_history(file, element=controls)
else: else:
controls = file.create_entity( controls = file.create_entity(
@@ -90,7 +101,7 @@ def assign_control(
**{ **{
"GlobalId": ifcopenshell.guid.new(), "GlobalId": ifcopenshell.guid.new(),
"OwnerHistory": ifcopenshell.api.owner.create_owner_history(file), "OwnerHistory": ifcopenshell.api.owner.create_owner_history(file),
"RelatedObjects": [related_object], "RelatedObjects": list(objects_to_assign),
"RelatingControl": relating_control, "RelatingControl": relating_control,
}, },
) )
@@ -45,7 +45,7 @@ def unassign_control(
cost_item = ifcopenshell.api.cost.add_cost_item(model, cost_item = ifcopenshell.api.cost.add_cost_item(model,
cost_schedule=schedule) cost_schedule=schedule)
ifcopenshell.api.control.assign_control(model, ifcopenshell.api.control.assign_control(model,
relating_control=cost_item, related_object=wall) relating_control=cost_item, related_objects=[wall])
# And now let's change our mind # And now let's change our mind
ifcopenshell.api.control.unassign_control(model, ifcopenshell.api.control.unassign_control(model,
@@ -59,7 +59,7 @@ def add_cost_item(
cost_item_ = ifcopenshell.api.root.create_entity(file, ifc_class="IfcCostItem") cost_item_ = ifcopenshell.api.root.create_entity(file, ifc_class="IfcCostItem")
if cost_schedule: if cost_schedule:
ifcopenshell.api.control.assign_control(file, cost_schedule, cost_item_) ifcopenshell.api.control.assign_control(file, cost_schedule, [cost_item_])
elif cost_item: elif cost_item:
ifcopenshell.api.nest.assign_object(file, related_objects=[cost_item_], relating_object=cost_item) ifcopenshell.api.nest.assign_object(file, related_objects=[cost_item_], relating_object=cost_item)
return cost_item_ return cost_item_
@@ -66,7 +66,7 @@ def add_cost_item_quantity(
schedule = ifcopenshell.api.cost.add_cost_schedule(model) schedule = ifcopenshell.api.cost.add_cost_schedule(model)
item = ifcopenshell.api.cost.add_cost_item(model, cost_schedule=schedule) item = ifcopenshell.api.cost.add_cost_item(model, cost_schedule=schedule)
ifcopenshell.api.control.assign_control(model, ifcopenshell.api.control.assign_control(model,
relating_control=item, related_object=chair) relating_control=item, related_objects=[chair])
# Let's assume we want to count the amount of chairs to calculate our cost item # Let's assume we want to count the amount of chairs to calculate our cost item
# Because this is an IfcQuantityCount the count will be automatically set to "1" chair # Because this is an IfcQuantityCount the count will be automatically set to "1" chair
@@ -122,7 +122,7 @@ class Usecase:
) -> ifcopenshell.entity_instance: ) -> ifcopenshell.entity_instance:
return ifcopenshell.api.control.assign_control( return ifcopenshell.api.control.assign_control(
self.file, self.file,
related_object=related_object, related_objects=[related_object],
relating_control=cost_item, relating_control=cost_item,
) )
@@ -57,7 +57,7 @@ def calculate_cost_item_resource_value(file: ifcopenshell.file, cost_item: ifcop
concrete = ifcopenshell.api.resource.add_resource(model, concrete = ifcopenshell.api.resource.add_resource(model,
ifc_class="IfcConstructionMaterialResource", parent_resource=crew) ifc_class="IfcConstructionMaterialResource", parent_resource=crew)
ifcopenshell.api.control.assign_control(model, ifcopenshell.api.control.assign_control(model,
relating_control=item, related_object=concrete) relating_control=item, related_objects=[concrete])
# ... which has a unit price of 42.0 per m3 # ... which has a unit price of 42.0 per m3
value = ifcopenshell.api.cost.add_cost_value(model, parent=concrete) value = ifcopenshell.api.cost.add_cost_value(model, parent=concrete)
ifcopenshell.api.cost.edit_cost_value(model, cost_value=value, ifcopenshell.api.cost.edit_cost_value(model, cost_value=value,
@@ -72,7 +72,7 @@ def calculate_cost_item_resource_value(file: ifcopenshell.file, cost_item: ifcop
equipment = ifcopenshell.api.resource.add_resource(model, equipment = ifcopenshell.api.resource.add_resource(model,
ifc_class="IfcConstructionEquipmentResource", parent_resource=crew) ifc_class="IfcConstructionEquipmentResource", parent_resource=crew)
ifcopenshell.api.control.assign_control(model, ifcopenshell.api.control.assign_control(model,
relating_control=item, related_object=equipment) relating_control=item, related_objects=[equipment])
# ... with a fixed price of 50,000 # ... with a fixed price of 50,000
value = ifcopenshell.api.cost.add_cost_value(model, parent=concrete) value = ifcopenshell.api.cost.add_cost_value(model, parent=concrete)
ifcopenshell.api.cost.edit_cost_value(model, cost_value=value, ifcopenshell.api.cost.edit_cost_value(model, cost_value=value,
@@ -45,5 +45,5 @@ def copy_cost_schedule(
if isinstance(duplicated_cost_item, list): if isinstance(duplicated_cost_item, list):
# All other nested items are not connected to the cost schedule explicitly. # All other nested items are not connected to the cost schedule explicitly.
duplicated_cost_item = duplicated_cost_item[0] duplicated_cost_item = duplicated_cost_item[0]
ifcopenshell.api.control.assign_control(file, new_schedule, duplicated_cost_item) ifcopenshell.api.control.assign_control(file, new_schedule, [duplicated_cost_item])
return new_schedule return new_schedule
@@ -138,7 +138,7 @@ def add_task(
task.Identification = identification task.Identification = identification
task.IsMilestone = False task.IsMilestone = False
if work_schedule: if work_schedule:
ifcopenshell.api.control.assign_control(file, work_schedule, task) ifcopenshell.api.control.assign_control(file, work_schedule, [task])
elif parent_task: elif parent_task:
rel = ifcopenshell.api.nest.assign_object( rel = ifcopenshell.api.nest.assign_object(
file, file,
@@ -75,7 +75,7 @@ def add_work_calendar(
# We associate the calendar with the construction root task. All # We associate the calendar with the construction root task. All
# subtasks underneath the construction work task will also inherit # subtasks underneath the construction work task will also inherit
# this calendar by default (though you can override them). # this calendar by default (though you can override them).
ifcopenshell.api.control.assign_control(model, relating_control=calendar, related_object=task) ifcopenshell.api.control.assign_control(model, relating_control=calendar, related_objects=[task])
""" """
work_calendar = ifcopenshell.api.root.create_entity( work_calendar = ifcopenshell.api.root.create_entity(
file, file,
@@ -47,5 +47,5 @@ def copy_work_schedule(
duplicated_tasks = ifcopenshell.api.sequence.duplicate_task(file, task)[1] duplicated_tasks = ifcopenshell.api.sequence.duplicate_task(file, task)[1]
# All other nested items are not connected to the work schedule explicitly. # All other nested items are not connected to the work schedule explicitly.
duplicated_task = duplicated_tasks[0] duplicated_task = duplicated_tasks[0]
ifcopenshell.api.control.assign_control(file, new_schedule, duplicated_task) ifcopenshell.api.control.assign_control(file, new_schedule, [duplicated_task])
return new_schedule return new_schedule
@@ -79,7 +79,7 @@ class Usecase:
assert isinstance(res, list) assert isinstance(res, list)
current, duplicate = res current, duplicate = res
ifcopenshell.api.control.assign_control( ifcopenshell.api.control.assign_control(
self.file, relating_control=baseline_work_schedule, related_object=duplicate[0] self.file, relating_control=baseline_work_schedule, related_objects=[duplicate[0]]
) )
for i, task in enumerate(current): for i, task in enumerate(current):
self.create_baseline_reference(task, duplicate[i]) self.create_baseline_reference(task, duplicate[i])
@@ -27,23 +27,33 @@ class TestAssignControl(test.bootstrap.IFC4):
control = ifcopenshell.api.cost.add_cost_schedule(self.file) control = ifcopenshell.api.cost.add_cost_schedule(self.file)
# simple assignment # simple assignment
relation = ifcopenshell.api.control.assign_control(self.file, relating_control=control, related_object=wall) relation = ifcopenshell.api.control.assign_control(self.file, relating_control=control, related_objects=[wall])
assert relation
assert len(self.file.by_type("IfcRelAssignsToControl")) == 1 assert len(self.file.by_type("IfcRelAssignsToControl")) == 1
assert relation.RelatingControl == control assert relation.RelatingControl == control
assert relation.RelatedObjects == (wall,) assert relation.RelatedObjects == (wall,)
# trying to establish existing relationship # trying to establish existing relationship
relation = ifcopenshell.api.control.assign_control(self.file, relating_control=control, related_object=wall) relation = ifcopenshell.api.control.assign_control(self.file, relating_control=control, related_objects=[wall])
assert relation is None assert relation is None
# assigning same control to another object # assigning same control to another object
wall1 = self.file.createIfcWall() wall1 = self.file.createIfcWall()
relation = ifcopenshell.api.control.assign_control(self.file, relating_control=control, related_object=wall1) relation = ifcopenshell.api.control.assign_control(self.file, relating_control=control, related_objects=[wall1])
assert relation is not None assert relation is not None
assert len(self.file.by_type("IfcRelAssignsToControl")) == 1 assert len(self.file.by_type("IfcRelAssignsToControl")) == 1
assert relation.RelatingControl == control assert relation.RelatingControl == control
assert set(relation.RelatedObjects) == set((wall, wall1)) assert set(relation.RelatedObjects) == set((wall, wall1))
def test_batch_assignment(self):
walls = [self.file.createIfcWall() for _ in range(5)]
control = ifcopenshell.api.cost.add_cost_schedule(self.file)
relation = ifcopenshell.api.control.assign_control(self.file, relating_control=control, related_objects=walls)
assert relation
assert len(self.file.by_type("IfcRelAssignsToControl")) == 1
assert relation.RelatingControl == control
assert set(relation.RelatedObjects) == set(walls)
class TestAssignControlIFC2X3(test.bootstrap.IFC2X3, TestAssignControl): class TestAssignControlIFC2X3(test.bootstrap.IFC2X3, TestAssignControl):
pass pass
@@ -27,14 +27,16 @@ class TestUnassignControl(test.bootstrap.IFC4):
control = ifcopenshell.api.cost.add_cost_schedule(self.file) control = ifcopenshell.api.cost.add_cost_schedule(self.file)
# assign and unassign # assign and unassign
relation = ifcopenshell.api.control.assign_control(self.file, relating_control=control, related_object=wall) relation = ifcopenshell.api.control.assign_control(self.file, relating_control=control, related_objects=[wall])
assert relation
ifcopenshell.api.control.unassign_control(self.file, relating_control=control, related_object=wall) ifcopenshell.api.control.unassign_control(self.file, relating_control=control, related_object=wall)
assert len(self.file.by_type("IfcRelAssignsToControl")) == 0 assert len(self.file.by_type("IfcRelAssignsToControl")) == 0
# 1 control 2 related objects # 1 control 2 related objects
wall1 = self.file.createIfcWall() wall1 = self.file.createIfcWall()
relation = ifcopenshell.api.control.assign_control(self.file, relating_control=control, related_object=wall) relation = ifcopenshell.api.control.assign_control(self.file, relating_control=control, related_objects=[wall])
ifcopenshell.api.control.assign_control(self.file, relating_control=control, related_object=wall1) assert relation
ifcopenshell.api.control.assign_control(self.file, relating_control=control, related_objects=[wall1])
ifcopenshell.api.control.unassign_control(self.file, relating_control=control, related_object=wall1) ifcopenshell.api.control.unassign_control(self.file, relating_control=control, related_object=wall1)
assert len(self.file.by_type("IfcRelAssignsToControl")) == 1 assert len(self.file.by_type("IfcRelAssignsToControl")) == 1
assert relation.RelatedObjects == (wall,) assert relation.RelatedObjects == (wall,)
@@ -30,7 +30,7 @@ class TestAddCostItemQuantity(test.bootstrap.IFC4):
schedule = ifcopenshell.api.cost.add_cost_schedule(self.file) schedule = ifcopenshell.api.cost.add_cost_schedule(self.file)
item = ifcopenshell.api.cost.add_cost_item(self.file, cost_schedule=schedule) item = ifcopenshell.api.cost.add_cost_item(self.file, cost_schedule=schedule)
wall = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWall") wall = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWall")
ifcopenshell.api.control.assign_control(self.file, relating_control=item, related_object=wall) ifcopenshell.api.control.assign_control(self.file, relating_control=item, related_objects=[wall])
quantities = [] quantities = []
for quantity_type in quantity_types: for quantity_type in quantity_types:
@@ -95,7 +95,7 @@ class TestEditTaskTime(test.bootstrap.IFC4):
ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcProject") ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcProject")
calendar = ifcopenshell.api.sequence.add_work_calendar(self.file) calendar = ifcopenshell.api.sequence.add_work_calendar(self.file)
task = self.file.createIfcTask() task = self.file.createIfcTask()
ifcopenshell.api.control.assign_control(self.file, relating_control=calendar, related_object=task) ifcopenshell.api.control.assign_control(self.file, relating_control=calendar, related_objects=[task])
task_time = ifcopenshell.api.sequence.add_task_time(self.file, task=task) task_time = ifcopenshell.api.sequence.add_task_time(self.file, task=task)
ifcopenshell.api.sequence.edit_task_time( ifcopenshell.api.sequence.edit_task_time(
self.file, self.file,
@@ -195,7 +195,7 @@ class TestEditTaskTime(test.bootstrap.IFC4):
ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcProject") ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcProject")
calendar = ifcopenshell.api.sequence.add_work_calendar(self.file) calendar = ifcopenshell.api.sequence.add_work_calendar(self.file)
task = self.file.createIfcTask() task = self.file.createIfcTask()
ifcopenshell.api.control.assign_control(self.file, relating_control=calendar, related_object=task) ifcopenshell.api.control.assign_control(self.file, relating_control=calendar, related_objects=[task])
task_time = ifcopenshell.api.sequence.add_task_time(self.file, task=task) task_time = ifcopenshell.api.sequence.add_task_time(self.file, task=task)
ifcopenshell.api.sequence.edit_task_time( ifcopenshell.api.sequence.edit_task_time(
self.file, self.file,
@@ -38,7 +38,7 @@ class TestRemoveWorkCalendar(test.bootstrap.IFC4):
# Assign tasks. # Assign tasks.
task = ifcopenshell.api.sequence.add_task(self.file) task = ifcopenshell.api.sequence.add_task(self.file)
ifcopenshell.api.control.assign_control(self.file, work_calendar, task) ifcopenshell.api.control.assign_control(self.file, work_calendar, [task])
ifcopenshell.api.sequence.remove_work_calendar(self.file, work_calendar) ifcopenshell.api.sequence.remove_work_calendar(self.file, work_calendar)
+13 -2
View File
@@ -16,19 +16,30 @@
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>. # along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
import ifcopenshell.api.cost
import ifcopenshell.api.root
import test.bootstrap import test.bootstrap
import ifcopenshell.api import ifcopenshell.api
import ifcopenshell.api.control
import ifcopenshell.api.sequence
import ifcopenshell.util.element
from datetime import datetime from datetime import datetime
from typing import Union from typing import Union
def deprecation_check(test): def deprecation_check(test):
def new_test(self): def new_test(self):
assert datetime.now().date() < datetime(2024, 8, 1).date(), "API arguments are completely deprecated" assert datetime.now().date() < datetime(2026, 1, 9).date(), "API arguments are completely deprecated"
test(self) test(self)
return new_test return new_test
class TestTemporarySupportForDeprecatedAPIArguments(test.bootstrap.IFC4): class TestTemporarySupportForDeprecatedAPIArguments(test.bootstrap.IFC4):
pass @deprecation_check
def test_assigning_control(self):
model = self.file
element = ifcopenshell.api.root.create_entity(model, ifc_class="IfcWall")
control = ifcopenshell.api.cost.add_cost_schedule(model)
ifcopenshell.api.control.assign_control(model, relating_control=control, related_objects=[element])
assert list(ifcopenshell.util.element.get_controls(element)) == [control]