mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 17:31:45 +00:00
Merge remote-tracking branch 'origin/v0.8.0' into tfk-rocksdb-storage
This commit is contained in:
@@ -27,23 +27,33 @@ class TestAssignControl(test.bootstrap.IFC4):
|
||||
control = ifcopenshell.api.cost.add_cost_schedule(self.file)
|
||||
|
||||
# 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 relation.RelatingControl == control
|
||||
assert relation.RelatedObjects == (wall,)
|
||||
|
||||
# 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
|
||||
|
||||
# assigning same control to another object
|
||||
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 len(self.file.by_type("IfcRelAssignsToControl")) == 1
|
||||
assert relation.RelatingControl == control
|
||||
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):
|
||||
pass
|
||||
|
||||
@@ -27,15 +27,17 @@ class TestUnassignControl(test.bootstrap.IFC4):
|
||||
control = ifcopenshell.api.cost.add_cost_schedule(self.file)
|
||||
|
||||
# assign and unassign
|
||||
relation = ifcopenshell.api.control.assign_control(self.file, relating_control=control, related_object=wall)
|
||||
ifcopenshell.api.control.unassign_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_objects=[wall])
|
||||
assert len(self.file.by_type("IfcRelAssignsToControl")) == 0
|
||||
|
||||
# 1 control 2 related objects
|
||||
wall1 = self.file.createIfcWall()
|
||||
relation = ifcopenshell.api.control.assign_control(self.file, relating_control=control, related_object=wall)
|
||||
ifcopenshell.api.control.assign_control(self.file, relating_control=control, related_object=wall1)
|
||||
ifcopenshell.api.control.unassign_control(self.file, relating_control=control, related_object=wall1)
|
||||
relation = ifcopenshell.api.control.assign_control(self.file, relating_control=control, related_objects=[wall])
|
||||
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_objects=[wall1])
|
||||
assert len(self.file.by_type("IfcRelAssignsToControl")) == 1
|
||||
assert relation.RelatedObjects == (wall,)
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ class TestAddCostItemQuantity(test.bootstrap.IFC4):
|
||||
schedule = ifcopenshell.api.cost.add_cost_schedule(self.file)
|
||||
item = ifcopenshell.api.cost.add_cost_item(self.file, cost_schedule=schedule)
|
||||
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 = []
|
||||
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")
|
||||
calendar = ifcopenshell.api.sequence.add_work_calendar(self.file)
|
||||
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)
|
||||
ifcopenshell.api.sequence.edit_task_time(
|
||||
self.file,
|
||||
@@ -195,7 +195,7 @@ class TestEditTaskTime(test.bootstrap.IFC4):
|
||||
ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcProject")
|
||||
calendar = ifcopenshell.api.sequence.add_work_calendar(self.file)
|
||||
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)
|
||||
ifcopenshell.api.sequence.edit_task_time(
|
||||
self.file,
|
||||
|
||||
@@ -38,7 +38,7 @@ class TestRemoveWorkCalendar(test.bootstrap.IFC4):
|
||||
|
||||
# Assign tasks.
|
||||
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)
|
||||
|
||||
|
||||
@@ -16,19 +16,39 @@
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import ifcopenshell.api.cost
|
||||
import ifcopenshell.api.root
|
||||
import test.bootstrap
|
||||
import ifcopenshell.api
|
||||
import ifcopenshell.api.control
|
||||
import ifcopenshell.api.sequence
|
||||
import ifcopenshell.util.element
|
||||
from datetime import datetime
|
||||
from typing import Union
|
||||
|
||||
|
||||
def deprecation_check(test):
|
||||
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)
|
||||
|
||||
return new_test
|
||||
|
||||
|
||||
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]
|
||||
|
||||
@deprecation_check
|
||||
def test_unassigning_control(self):
|
||||
TestTemporarySupportForDeprecatedAPIArguments.test_assigning_control(self)
|
||||
model = self.file
|
||||
element = model.by_type("IfcWall")[0]
|
||||
control = model.by_type("IfcCostSchedule")[0]
|
||||
ifcopenshell.api.control.unassign_control(model, relating_control=control, related_objects=[element])
|
||||
assert list(ifcopenshell.util.element.get_controls(element)) == []
|
||||
|
||||
@@ -145,14 +145,20 @@ class TestAssignType(test.bootstrap.IFC4):
|
||||
This is because the type will have its own PredefinedType, and the element's PredefinedType
|
||||
will conflict with it. (See #7006)
|
||||
"""
|
||||
is_ifc2x3 = self.file.schema == "IFC2X3"
|
||||
element_type = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWallType")
|
||||
element_type.PredefinedType = "MOVABLE"
|
||||
element_type.PredefinedType = "POLYGONAL"
|
||||
|
||||
element = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWall")
|
||||
element.PredefinedType = "USERDEFINED"
|
||||
if not is_ifc2x3:
|
||||
# In IFC2X3, there seems to be no example when both type and occurence have PredefinedType.
|
||||
# So we just ignore it.
|
||||
element.PredefinedType = "USERDEFINED"
|
||||
element.ObjectType = "Test"
|
||||
ifcopenshell.api.type.assign_type(self.file, related_objects=[element], relating_type=element_type)
|
||||
assert element.PredefinedType is None
|
||||
|
||||
if not is_ifc2x3:
|
||||
assert element.PredefinedType is None
|
||||
assert element.ObjectType is None
|
||||
|
||||
def test_keep_predefined_type_if_type_assignment_is_notdefined(self):
|
||||
@@ -160,16 +166,26 @@ class TestAssignType(test.bootstrap.IFC4):
|
||||
if an element has a PredefinedType, it will be removed when assigning a type.(See #7006)
|
||||
This behavior needs to be blocked if the PredefinedType of the typing Entity is set to "NOTDEFINED". (See #7011)
|
||||
"""
|
||||
is_ifc2x3 = self.file.schema == "IFC2X3"
|
||||
element_type = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWallType")
|
||||
element_type.PredefinedType = "NOTDEFINED"
|
||||
|
||||
element = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWall")
|
||||
element.PredefinedType = "USERDEFINED"
|
||||
if not is_ifc2x3:
|
||||
# In IFC2X3, there seems to be no example when both type and occurence have PredefinedType.
|
||||
# So we just ignore it.
|
||||
element.PredefinedType = "USERDEFINED"
|
||||
element.ObjectType = "Test"
|
||||
ifcopenshell.api.type.assign_type(self.file, related_objects=[element], relating_type=element_type)
|
||||
assert element.PredefinedType == "USERDEFINED"
|
||||
|
||||
if not is_ifc2x3:
|
||||
assert element.PredefinedType == "USERDEFINED"
|
||||
assert element.ObjectType == "Test"
|
||||
|
||||
|
||||
class TestAssignTypeIFC2X3(test.bootstrap.IFC2X3, TestAssignType):
|
||||
pass
|
||||
|
||||
|
||||
class TestAssignTypeIFC4X3(test.bootstrap.IFC4X3, TestAssignType):
|
||||
pass
|
||||
|
||||
@@ -47,15 +47,20 @@ class TestPackageSupportedPlatforms:
|
||||
response = conn.getresponse()
|
||||
build_html = response.read().decode("utf-8")
|
||||
|
||||
def find_make_var(var_name: str) -> str:
|
||||
line = next(l for l in text.splitlines() if l.startswith(f"{var_name}:="))
|
||||
return line.partition(":=")[2]
|
||||
|
||||
BINARY_VERSION = find_make_var("BINARY_VERSION")
|
||||
URL_TYPES = ("IOS_URL", "IFCCONVERT_URL")
|
||||
|
||||
missing_urls: set[str] = set()
|
||||
for url_type in URL_TYPES:
|
||||
line = next(l for l in text.splitlines() if l.startswith(f"{url_type}:="))
|
||||
_, _, url_template = line.partition(":=")
|
||||
url_template = find_make_var(url_type)
|
||||
url_template = url_template.replace("$(", "{").replace(")", "}")
|
||||
for platform in SUPPORTED_PLATFORMS:
|
||||
for pyver in SUPPORTED_PY_VERSIONS:
|
||||
url = url_template.format(PYNUMBER=pyver, PLATFORM=platform)
|
||||
url = url_template.format(PYNUMBER=pyver, PLATFORM=platform, BINARY_VERSION=BINARY_VERSION)
|
||||
if url not in build_html:
|
||||
missing_urls.add(url)
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import ifcopenshell.api.control
|
||||
import ifcopenshell.api.cost
|
||||
import ifcopenshell.api.profile
|
||||
import pytest
|
||||
import test.bootstrap
|
||||
@@ -926,6 +928,23 @@ class TestGetGroupsIFC2X3(test.bootstrap.IFC2X3, TestGetGroupsIFC4):
|
||||
pass
|
||||
|
||||
|
||||
class TestGetControls(test.bootstrap.IFC2X3):
|
||||
def test_run(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, related_objects=[element], relating_control=control)
|
||||
assert list(subject.get_controls(element)) == [control]
|
||||
|
||||
|
||||
class TestGetControlsIFC4(test.bootstrap.IFC4, TestGetControls):
|
||||
pass
|
||||
|
||||
|
||||
class TestGetControlsIFC4X3(test.bootstrap.IFC4X3, TestGetControls):
|
||||
pass
|
||||
|
||||
|
||||
class TestGetAggregateIFC4(test.bootstrap.IFC4):
|
||||
def test_getting_the_containing_aggregate_of_a_subelement(self):
|
||||
element = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWall")
|
||||
|
||||
@@ -468,3 +468,29 @@ class TestAngle2YAxis(test.bootstrap.IFC4):
|
||||
assert np.allclose(subject.angle2yaxis(45), (-a, a))
|
||||
assert np.allclose(subject.angle2yaxis(-135), (a, -a))
|
||||
assert np.allclose(subject.angle2yaxis(135), (-a, -a))
|
||||
|
||||
|
||||
class TestDMS2DDandDD2DMS(test.bootstrap.IFC4):
|
||||
def test_dms2dd_and_dd2dms(self):
|
||||
test_cases_3tuple = [
|
||||
(35.41, (35, 24, 36.0)),
|
||||
(-116.89, (-116, -53, -24.0)),
|
||||
]
|
||||
test_cases_4tuple = [
|
||||
(40.431389, (40, 25, 53, 400)),
|
||||
(-4.248056, (-4, -14, -53, -1600)),
|
||||
(-35.401389, (-35, -24, -5, -400)),
|
||||
(148.981667, (148, 58, 54, 1200)),
|
||||
]
|
||||
|
||||
for dd, dms in test_cases_3tuple:
|
||||
d, m, s = subject.dd2dms(dd)
|
||||
assert (d, m, s) == dms
|
||||
dd_converted = subject.dms2dd(dms[0], dms[1], dms[2])
|
||||
assert dd_converted == dd
|
||||
|
||||
for dd, dms in test_cases_4tuple:
|
||||
d, m, s, us = subject.dd2dms(dd, use_us=True)
|
||||
assert (d, m, s, us) == dms
|
||||
dd_converted = subject.dms2dd(dms[0], dms[1], dms[2], dms[3])
|
||||
assert dd_converted == dd
|
||||
|
||||
Reference in New Issue
Block a user