diff --git a/src/bonsai/bonsai/bim/module/boundary/operator.py b/src/bonsai/bonsai/bim/module/boundary/operator.py
index e3bc51683c..5d83a88597 100644
--- a/src/bonsai/bonsai/bim/module/boundary/operator.py
+++ b/src/bonsai/bonsai/bim/module/boundary/operator.py
@@ -25,6 +25,7 @@ import mathutils
import numpy as np
import multiprocessing
import ifcopenshell.api
+import ifcopenshell.api.boundary
import ifcopenshell.geom
import ifcopenshell.util.unit
import ifcopenshell.util.shape
@@ -416,7 +417,7 @@ class UpdateBoundaryGeometry(bpy.types.Operator, tool.Ifc.Operator):
def _execute(self, context):
tool.Boundary.move_origin_to_space_origin(context.active_object)
settings = tool.Boundary.get_assign_connection_geometry_settings(context.active_object)
- ifcopenshell.api.run("boundary.assign_connection_geometry", tool.Ifc.get(), **settings)
+ ifcopenshell.api.boundary.assign_connection_geometry(tool.Ifc.get(), **settings)
return {"FINISHED"}
diff --git a/src/bonsai/bonsai/bim/module/geometry/operator.py b/src/bonsai/bonsai/bim/module/geometry/operator.py
index de59b7a61c..6a234800bf 100644
--- a/src/bonsai/bonsai/bim/module/geometry/operator.py
+++ b/src/bonsai/bonsai/bim/module/geometry/operator.py
@@ -29,6 +29,7 @@ import ifcopenshell.util.representation
import ifcopenshell.util.shape_builder
import ifcopenshell.util.unit
import ifcopenshell.api
+import ifcopenshell.api.boundary
import ifcopenshell.api.grid
import bonsai.core.geometry
import bonsai.core.geometry as core
@@ -479,7 +480,7 @@ class UpdateRepresentation(bpy.types.Operator, tool.Ifc.Operator):
elif product.is_a("IfcRelSpaceBoundary"):
# TODO refactor
settings = tool.Boundary.get_assign_connection_geometry_settings(obj)
- ifcopenshell.api.run("boundary.assign_connection_geometry", tool.Ifc.get(), **settings)
+ ifcopenshell.api.boundary.assign_connection_geometry(tool.Ifc.get(), **settings)
return
if tool.Ifc.is_moved(obj) or tool.Geometry.is_scaled(obj):
diff --git a/src/bonsai/bonsai/bim/module/profile/operator.py b/src/bonsai/bonsai/bim/module/profile/operator.py
index b0d5073429..1a330917db 100644
--- a/src/bonsai/bonsai/bim/module/profile/operator.py
+++ b/src/bonsai/bonsai/bim/module/profile/operator.py
@@ -18,6 +18,7 @@
import bpy
import ifcopenshell.api
+import ifcopenshell.api.profile
import ifcopenshell.util.element
import bonsai.bim.helper
import bonsai.tool as tool
@@ -174,12 +175,12 @@ class AddProfileDef(bpy.types.Operator, tool.Ifc.Operator):
props.object_to_profile = None
if not indices:
points = [(0, 0), (0.1, 0), (0.1, 0.1), (0, 0.1), (0, 0)]
- profile = ifcopenshell.api.run("profile.add_arbitrary_profile", tool.Ifc.get(), profile=points)
+ profile = ifcopenshell.api.profile.add_arbitrary_profile(tool.Ifc.get(), profile=points)
else:
if "inner_curves" not in indices:
points = [(obj.data.vertices[i].co.x, obj.data.vertices[i].co.y) for i in indices["profile"]]
points.append(points[0])
- profile = ifcopenshell.api.run("profile.add_arbitrary_profile", tool.Ifc.get(), profile=points)
+ profile = ifcopenshell.api.profile.add_arbitrary_profile(tool.Ifc.get(), profile=points)
else:
outer_points = [(obj.data.vertices[i].co.x, obj.data.vertices[i].co.y) for i in indices["profile"]]
outer_points.append(outer_points[0])
@@ -189,8 +190,7 @@ class AddProfileDef(bpy.types.Operator, tool.Ifc.Operator):
]
for curve in inner_points:
curve.append(curve[0])
- profile = ifcopenshell.api.run(
- "profile.add_arbitrary_profile_with_voids",
+ profile = ifcopenshell.api.profile.add_arbitrary_profile_with_voids(
tool.Ifc.get(),
outer_profile=outer_points,
inner_profiles=inner_points,
diff --git a/src/ifcopenshell-python/ifcopenshell/api/attribute/edit_attributes.py b/src/ifcopenshell-python/ifcopenshell/api/attribute/edit_attributes.py
index 3cbab7f38d..ff0e2b11b7 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/attribute/edit_attributes.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/attribute/edit_attributes.py
@@ -39,11 +39,8 @@ def edit_attributes(file: ifcopenshell.file, product: ifcopenshell.entity_instan
:param product: The product you want to edit. This may be any rooted IFC
entity.
- :type product: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
diff --git a/src/ifcopenshell-python/ifcopenshell/api/boundary/assign_connection_geometry.py b/src/ifcopenshell-python/ifcopenshell/api/boundary/assign_connection_geometry.py
index d77776f04a..b9a2630442 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/boundary/assign_connection_geometry.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/boundary/assign_connection_geometry.py
@@ -17,17 +17,20 @@
# along with IfcOpenShell. If not, see .
import ifcopenshell.util.unit
+import numpy as np
+import numpy.typing as npt
from typing import Optional
+from ifcopenshell.util.shape_builder import SequenceOfVectors, V, ifc_safe_vector_type
def assign_connection_geometry(
file: ifcopenshell.file,
rel_space_boundary: ifcopenshell.entity_instance,
- outer_boundary: list[tuple[float, float]],
+ outer_boundary: SequenceOfVectors,
location: tuple[float, float, float],
axis: tuple[float, float, float],
ref_direction: tuple[float, float, float],
- inner_boundaries: Optional[list[list[tuple[float, float]]]] = None,
+ inner_boundaries: Optional[SequenceOfVectors] = None,
unit_scale: Optional[float] = None,
) -> None:
"""Create and assign a connection geometry to a space boundary relationship
@@ -40,35 +43,28 @@ def assign_connection_geometry(
:param rel_space_boundary: The space boundary relationship to assign the
connection geometry to.
- :type rel_space_boundary: ifcopenshell.entity_instance
:param outer_boundary: A list of 2D points representing an open
polyline. The last point will connect to the first point. Each
point is represented by an interable of 2 floats. The coordinates of
the points are relative to the positional matrix arguments.
- :type outer_boundary: list[tuple[float, float]]
:param inner_boundaries: A list of zero or more inner boundaries to use
for the plane. Each boundary is represented by an open polyline, as
defined by the outer_boundary argument.
- :type inner_boundaries: list[list[tuple[float, float]]], optional
:param location: The local origin of the connection geometry, defined as
an XYZ coordinate relative to the placement of the space that is
being bounded.
- :type location: tuple[float, float, float]
:param axis: The local X axis of the connection geometry, defined as an
XYZ vector relative to the placement of the space that is being
bounded.
- :type axis: tuple[float, float, float]
:param ref_direction: The local Z axis of the connection geometry,
defined as an XYZ vector relative to the placement of the space that
is being bounded. The Y vector is automatically derived using the
right hand rule.
- :type ref_direction: tuple[float, float, float]
:param unit_scale: The unit scale as calculated by
ifcopenshell.util.unit.calculate_unit_scale. If not provided, it
will be automatically calculated for you.
:type unit_scale: float, optional
:return: None
- :rtype: None
Example:
@@ -83,19 +79,26 @@ def assign_connection_geometry(
usecase = Usecase()
usecase.file = file
usecase.rel_space_boundary = rel_space_boundary
- usecase.outer_boundary = outer_boundary
- usecase.inner_boundaries = inner_boundaries or ()
- usecase.location = location
- usecase.axis = axis
- usecase.ref_direction = ref_direction
- usecase.unit_scale = unit_scale
+ usecase.outer_boundary = V(outer_boundary)
+ usecase.inner_boundaries = V(inner_boundaries or [])
+ usecase.location = V(location)
+ usecase.axis = V(axis)
+ usecase.ref_direction = V(ref_direction)
+ usecase.unit_scale = unit_scale if unit_scale is not None else ifcopenshell.util.unit.calculate_unit_scale(file)
return usecase.execute()
class Usecase:
+ file: ifcopenshell.file
+ rel_space_boundary: ifcopenshell.entity_instance
+ outer_boundary: npt.NDArray
+ inner_boundaries: npt.NDArray
+ location: npt.NDArray
+ axis: npt.NDArray
+ ref_direction: npt.NDArray
+ unit_scale: float
+
def execute(self):
- if self.unit_scale is None:
- self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(self.file)
outer_boundary = self.create_polyline(self.outer_boundary)
inner_boundaries = tuple(self.create_polyline(boundary) for boundary in self.inner_boundaries)
plane = self.create_plane(self.location, self.axis, self.ref_direction)
@@ -103,18 +106,23 @@ class Usecase:
connection_geometry = self.file.createIfcConnectionSurfaceGeometry(curve_bounded_plane)
self.rel_space_boundary.ConnectionGeometry = connection_geometry
- def create_point(self, point):
- return self.file.createIfcCartesianPoint(point / self.unit_scale)
+ def create_point(self, point: npt.NDArray) -> ifcopenshell.entity_instance:
+ return self.file.create_enitty("IfcCartesianPoint", ifc_safe_vector_type(point / self.unit_scale))
- def close_polyline(self, points):
+ def close_polyline(
+ self, points: tuple[ifcopenshell.entity_instance, ...]
+ ) -> tuple[ifcopenshell.entity_instance, ...]:
return points + (points[0],)
- def create_polyline(self, points):
- if points[0] == points[-1]:
+ def create_polyline(self, points: npt.NDArray) -> ifcopenshell.entity_instance:
+ if np.allclose(points[0], points[-1]):
points = points[0 : len(points) - 1]
- return self.file.createIfcPolyline(self.close_polyline(tuple(self.create_point(point) for point in points)))
+ ifc_points = tuple(self.create_point(point) for point in points)
+ return self.file.createIfcPolyline(self.close_polyline(ifc_points))
- def create_plane(self, location, axis, ref_direction):
+ def create_plane(
+ self, location: npt.NDArray, axis: npt.NDArray, ref_direction: npt.NDArray
+ ) -> ifcopenshell.entity_instance:
return self.file.createIfcPlane(
self.file.createIfcAxis2Placement3D(
self.create_point(location),
diff --git a/src/ifcopenshell-python/ifcopenshell/api/classification/add_classification.py b/src/ifcopenshell-python/ifcopenshell/api/classification/add_classification.py
index af886a0014..2932a5bb93 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/classification/add_classification.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/classification/add_classification.py
@@ -20,7 +20,7 @@ import ifcopenshell
import ifcopenshell.guid
import ifcopenshell.util.schema
import ifcopenshell.util.date
-from typing import Union
+from typing import Union, Any
def add_classification(
@@ -61,9 +61,7 @@ def add_classification(
classification library. The latter approach is preferred if you are
using a commonly known system such as Uniclass, as this will ensure
all metadata is added correctly.
- :type classification: str,ifcopenshell.entity_instance
:return: The added IfcClassification element
- :rtype: ifcopenshell.entity_instance
Example:
@@ -81,28 +79,28 @@ def add_classification(
"""
usecase = Usecase()
usecase.file = file
- usecase.settings = {
- "classification": classification,
- }
- return usecase.execute()
+ return usecase.execute(classification)
class Usecase:
- def execute(self):
- if isinstance(self.settings["classification"], str):
- classification = self.file.createIfcClassification(Name=self.settings["classification"])
+ file: ifcopenshell.file
+
+ def execute(self, classification: Union[str, ifcopenshell.entity_instance]) -> ifcopenshell.entity_instance:
+ self.classification = classification
+ if isinstance(self.classification, str):
+ classification = self.file.create_entity("IfcClassification", Name=self.classification)
self.relate_to_project(classification)
return classification
return self.add_from_library()
- def add_from_library(self):
+ def add_from_library(self) -> ifcopenshell.entity_instance:
edition_date = None
- if self.settings["classification"].EditionDate:
- edition_date = ifcopenshell.util.date.ifc2datetime(self.settings["classification"].EditionDate)
- self.settings["classification"].EditionDate = None
+ if self.classification.EditionDate:
+ edition_date = ifcopenshell.util.date.ifc2datetime(self.classification.EditionDate)
+ self.classification.EditionDate = None
migrator = ifcopenshell.util.schema.Migrator()
- result = migrator.migrate(self.settings["classification"], self.file)
+ result = migrator.migrate(self.classification, self.file)
# TODO: should auto date migration be part of the migrator?
if self.file.schema == "IFC2X3" and edition_date:
@@ -118,7 +116,7 @@ class Usecase:
return result
- def relate_to_project(self, classification):
+ def relate_to_project(self, classification: ifcopenshell.entity_instance) -> None:
self.file.create_entity(
"IfcRelAssociatesClassification",
GlobalId=ifcopenshell.guid.new(),
diff --git a/src/ifcopenshell-python/ifcopenshell/api/classification/add_reference.py b/src/ifcopenshell-python/ifcopenshell/api/classification/add_reference.py
index 1e0ae329bf..817d15b5cf 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/classification/add_reference.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/classification/add_reference.py
@@ -21,7 +21,7 @@ import ifcopenshell.api.owner
import ifcopenshell.guid
import ifcopenshell.util.element
import ifcopenshell.util.schema
-from typing import Optional, Union
+from typing import Optional, Union, Any
def add_reference(
@@ -65,23 +65,18 @@ def add_reference(
:param product: The list of IFC objects, properties, or resources you want to
associate the classification reference to.
- :type product: list[ifcopenshell.entity_instance]
:param reference: The classification reference entity taken from an
IFC classification library. If you supply this parameter, you will
use option 2.
- :type reference: ifcopenshell.entity_instance, optional
:param identification: If you choose option 1 and do not specify a
reference, you may manually specify an identification code. The code
is typically a short identifier and may have punctuation to separate
the levels of hierarchy in the classificaion (e.g. Pr_12_23_34).
- :type identification: str, optional
:param name: If you choose option 1 and do not specify a reference, you
may manually specify a name. The name is typically human readable.
- :type name: str, optional
:param classification: The IfcClassification entity in your IFC model
(not the library, if you are doing option 2) that the reference is
part of.
- :type classification: ifcopenshell.entity_instance
:param is_lightweight: If you are doing option 2, choose whether or not
to only add that particular reference (lighweight) or also add all
of its parent references in the classification hierarchy (not
@@ -91,13 +86,11 @@ def add_reference(
references merely help describe the "tree" of classifications, but
is generally unnecessary. Using lightweight classifications are
recommended and is the default.
- :type is_lightweight: bool, optional
:raises TypeError: If file is IFC2X3 and `products` has non-IfcRoot elements.
:return: The newly added IfcClassificationReference
or `None` if `products` was empty list.
- :rtype: Union[ifcopenshell.entity_instance, None]
Example:
@@ -136,6 +129,9 @@ def add_reference(
class Usecase:
+ file: ifcopenshell.file
+ settings: dict[str, Any]
+
def execute(self):
if not self.settings["products"]:
return
diff --git a/src/ifcopenshell-python/ifcopenshell/api/classification/edit_classification.py b/src/ifcopenshell-python/ifcopenshell/api/classification/edit_classification.py
index d6c8ef8bc4..b2091c0eca 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/classification/edit_classification.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/classification/edit_classification.py
@@ -28,11 +28,8 @@ def edit_classification(
IfcClassification, consult the IFC documentation.
:param classification: The IfcClassification entity you want to edit
- :type classification: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -43,7 +40,5 @@ def edit_classification(
ifcopenshell.api.classification.edit_classification(model,
classification=classification, attributes={"Name": "Foo"})
"""
- settings = {"classification": classification, "attributes": attributes or {}}
-
- for name, value in settings["attributes"].items():
- setattr(settings["classification"], name, value)
+ for name, value in attributes.items():
+ setattr(classification, name, value)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/classification/edit_reference.py b/src/ifcopenshell-python/ifcopenshell/api/classification/edit_reference.py
index 80d978e7d3..f5a85d40f9 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/classification/edit_reference.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/classification/edit_reference.py
@@ -28,11 +28,8 @@ def edit_reference(
IfcClassificationReference, consult the IFC documentation.
:param reference: The IfcClassificationReference entity you want to edit
- :type reference: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -43,7 +40,5 @@ def edit_reference(
ifcopenshell.api.classification.edit_reference(model,
reference=reference, attributes={"Name": "Foo"})
"""
- settings = {"reference": reference, "attributes": attributes or {}}
-
- for name, value in settings["attributes"].items():
- setattr(settings["reference"], name, value)
+ for name, value in attributes.items():
+ setattr(reference, name, value)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/classification/remove_classification.py b/src/ifcopenshell-python/ifcopenshell/api/classification/remove_classification.py
index 90e6abbbe7..38382eda91 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/classification/remove_classification.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/classification/remove_classification.py
@@ -28,9 +28,7 @@ def remove_classification(file: ifcopenshell.file, classification: ifcopenshell.
removed from a project.
:param classification: The IfcClassification entity you want to remove
- :type classification: ifcopenshell.entity_instance
:return: None
- :rtype: None
Example:
@@ -42,16 +40,17 @@ def remove_classification(file: ifcopenshell.file, classification: ifcopenshell.
"""
usecase = Usecase()
usecase.file = file
- usecase.settings = {"classification": classification}
- return usecase.execute()
+ return usecase.execute(classification)
class Usecase:
- def execute(self):
- references = self.get_references(self.settings["classification"])
+ file: ifcopenshell.file
+
+ def execute(self, classification: ifcopenshell.entity_instance) -> None:
+ references = self.get_references(classification)
for reference in references:
self.file.remove(reference)
- self.file.remove(self.settings["classification"])
+ self.file.remove(classification)
for rel in self.file.by_type("IfcRelAssociatesClassification"):
if not rel.RelatingClassification:
history = rel.OwnerHistory
diff --git a/src/ifcopenshell-python/ifcopenshell/api/classification/remove_reference.py b/src/ifcopenshell-python/ifcopenshell/api/classification/remove_reference.py
index 0bdd347bfa..55dfd11b08 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/classification/remove_reference.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/classification/remove_reference.py
@@ -33,15 +33,12 @@ def remove_reference(
:param reference: The IfcClassificationReference entity of the
relationship you want to remove.
- :type reference: ifcopenshell.entity_instance
:param product: The list fo object entities of the relationship you want to
remove.
- :type product: list[ifcopenshell.entity_instance]
:raises TypeError: If file is IFC2X3 and `products` has non-IfcRoot elements.
:return: None
- :rtype: None
Example:
@@ -56,20 +53,18 @@ def remove_reference(
ifcopenshell.api.classification.remove_reference(model,
reference=reference, products=[wall_type])
"""
- settings = {"reference": reference, "products": products}
-
is_ifc2x3 = file.schema == "IFC2X3"
- products = set(settings["products"])
- referenced = ifcopenshell.util.element.get_referenced_elements(settings["reference"])
- products -= products.difference(referenced)
+ products_set = set(products)
+ referenced = ifcopenshell.util.element.get_referenced_elements(reference)
+ products_set -= products_set.difference(referenced)
# all products are already unassigned from a reference
- if not products:
+ if not products_set:
return
rooted_products: set[ifcopenshell.entity_instance] = set()
non_rooted_products: set[ifcopenshell.entity_instance] = set()
- for product in settings["products"]:
+ for product in products:
if product.is_a("IfcRoot"):
rooted_products.add(product)
else:
@@ -86,7 +81,7 @@ def remove_reference(
reference_rels = {
rel
for rel in reference_rels
- if rel.is_a("IfcRelAssociatesClassification") and rel.RelatingClassification == settings["reference"]
+ if rel.is_a("IfcRelAssociatesClassification") and rel.RelatingClassification == reference
}
for rel in reference_rels:
@@ -108,7 +103,7 @@ def remove_reference(
rels = getattr(product, "HasExternalReference", [])
reference_rels.update(rels)
- reference_rels = {rel for rel in reference_rels if rel.RelatingReference == settings["reference"]}
+ reference_rels = {rel for rel in reference_rels if rel.RelatingReference == reference}
for rel in reference_rels:
related_objects = set(rel.RelatedResourceObjects) - non_rooted_products
if related_objects:
@@ -117,6 +112,6 @@ def remove_reference(
file.remove(rel)
# TODO: we only handle lightweight classifications here
- referenced_elements = ifcopenshell.util.element.get_referenced_elements(settings["reference"])
+ referenced_elements = ifcopenshell.util.element.get_referenced_elements(reference)
if not referenced_elements:
- file.remove(settings["reference"])
+ file.remove(reference)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/constraint/add_metric_reference.py b/src/ifcopenshell-python/ifcopenshell/api/constraint/add_metric_reference.py
index fdcdf50f6f..63ecfeb3c0 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/constraint/add_metric_reference.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/constraint/add_metric_reference.py
@@ -26,16 +26,14 @@ def add_metric_reference(
Adds a chain of references to a metric. The reference path is a string of the form "attribute.attribute.attribute"
Used to reference a value of an attribute of an instance through a metric objective entity.
"""
- settings = {"metric": metric, "reference_path": reference_path}
-
references_created = []
- if settings["reference_path"]:
- attributes = settings["reference_path"].split(".")
+ if reference_path:
+ attributes = reference_path.split(".")
for i in range(len(attributes)):
if i == 0:
reference = file.create_entity("IfcReference")
reference.AttributeIdentifier = attributes[i]
- settings["metric"].ReferencePath = reference
+ metric.ReferencePath = reference
references_created.append(reference)
else:
reference = file.create_entity("IfcReference")
diff --git a/src/ifcopenshell-python/ifcopenshell/api/constraint/assign_constraint.py b/src/ifcopenshell-python/ifcopenshell/api/constraint/assign_constraint.py
index 74bf3d9a04..f4daad0abb 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/constraint/assign_constraint.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/constraint/assign_constraint.py
@@ -39,36 +39,29 @@ def assign_constraint(
:param products: The list of products the constraint applies to. This is anything
which can have properties or quantities.
- :type products: list[ifcopenshell.entity_instance]
:param constraint: The IfcObjective constraint
- :type constraint: ifcopenshell.entity_instance
:return: The new or updated IfcRelAssociatesConstraint relationship
or `None` if `products` was an empty list.
- :rtype: ifcopenshell.entity_instance
"""
usecase = Usecase()
usecase.file = file
- usecase.settings = {
- "products": products,
- "constraint": constraint,
- }
- return usecase.execute()
+ return usecase.execute(products, constraint)
class Usecase:
- def execute(self):
- products = set(self.settings["products"])
+ file: ifcopenshell.file
+
+ def execute(self, products: list[ifcopenshell.entity_instance], constraint: ifcopenshell.entity_instance):
if not products:
return
+ products_set = set(products)
- self.constraint = self.settings["constraint"]
-
- rels = self.get_constraint_rels()
+ rels = self.get_constraint_rels(constraint)
related_objects = set()
for rel in rels:
related_objects.update(rel.RelatedObjects)
- products_to_assign = products - related_objects
+ products_to_assign = products_set - related_objects
if not products_to_assign:
return rels[0]
@@ -85,14 +78,14 @@ class Usecase:
**{
"GlobalId": ifcopenshell.guid.new(),
"OwnerHistory": ifcopenshell.api.owner.create_owner_history(self.file),
- "RelatingConstraint": self.constraint,
+ "RelatingConstraint": constraint,
"RelatedObjects": list(products_to_assign),
}
)
- def get_constraint_rels(self) -> list[ifcopenshell.entity_instance]:
+ def get_constraint_rels(self, constraint: ifcopenshell.entity_instance) -> list[ifcopenshell.entity_instance]:
rels = []
- for rel in self.file.get_inverse(self.constraint):
+ for rel in self.file.get_inverse(constraint):
if rel.is_a("IfcRelAssociatesConstraint"):
rels.append(rel)
return rels
diff --git a/src/ifcopenshell-python/ifcopenshell/api/constraint/edit_metric.py b/src/ifcopenshell-python/ifcopenshell/api/constraint/edit_metric.py
index 89a0cbef7d..3967846759 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/constraint/edit_metric.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/constraint/edit_metric.py
@@ -26,11 +26,8 @@ def edit_metric(file: ifcopenshell.file, metric: ifcopenshell.entity_instance, a
IfcMetric, consult the IFC documentation.
:param metric: The IfcMetric you want to edit.
- :type metric: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -42,7 +39,5 @@ def edit_metric(file: ifcopenshell.file, metric: ifcopenshell.entity_instance, a
ifcopenshell.api.constraint.edit_metric(model,
metric=metric, attributes={"ConstraintGrade": "HARD"})
"""
- settings = {"metric": metric, "attributes": attributes or {}}
-
- for name, value in settings["attributes"].items():
- setattr(settings["metric"], name, value)
+ for name, value in attributes.items():
+ setattr(metric, name, value)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/constraint/edit_objective.py b/src/ifcopenshell-python/ifcopenshell/api/constraint/edit_objective.py
index ce4e76ba9e..3cd75356a7 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/constraint/edit_objective.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/constraint/edit_objective.py
@@ -28,11 +28,8 @@ def edit_objective(
IfcObjective, consult the IFC documentation.
:param objective: The IfcObjective you want to edit.
- :type objective: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -42,7 +39,5 @@ def edit_objective(
ifcopenshell.api.constraint.edit_objective(model,
objective=objective, attributes={"ConstraintGrade": "HARD"})
"""
- settings = {"objective": objective, "attributes": attributes or {}}
-
- for name, value in settings["attributes"].items():
- setattr(settings["objective"], name, value)
+ for name, value in attributes.items():
+ setattr(objective, name, value)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/constraint/remove_metric.py b/src/ifcopenshell-python/ifcopenshell/api/constraint/remove_metric.py
index f700a2c150..76668f714d 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/constraint/remove_metric.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/constraint/remove_metric.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 ifcopenshell
+import ifcopenshell.util.element
def remove_metric(file: ifcopenshell.file, metric: ifcopenshell.entity_instance) -> None:
@@ -41,17 +42,18 @@ def remove_metric(file: ifcopenshell.file, metric: ifcopenshell.entity_instance)
"""
usecase = Usecase()
usecase.file = file
- usecase.settings = {"metric": metric}
- return usecase.execute()
+ return usecase.execute(metric)
class Usecase:
- def execute(self):
- if self.settings["metric"].ReferencePath:
- reference = self.settings["metric"].ReferencePath
+ file: ifcopenshell.file
+
+ def execute(self, metric: ifcopenshell.entity_instance) -> None:
+ if metric.ReferencePath:
+ reference = metric.ReferencePath
self.delete_reference(reference)
- self.file.remove(self.settings["metric"])
+ self.file.remove(metric)
for rel in self.file.by_type("IfcRelAssociatesConstraint"):
if not rel.RelatingConstraint:
history = rel.OwnerHistory
@@ -62,7 +64,7 @@ class Usecase:
if not resource_rel.RelatingConstraint:
self.file.remove(resource_rel)
- def delete_reference(self, reference):
+ def delete_reference(self, reference: ifcopenshell.entity_instance) -> None:
if reference.InnerReference:
self.delete_reference(reference.InnerReference)
self.file.remove(reference)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/constraint/unassign_constraint.py b/src/ifcopenshell-python/ifcopenshell/api/constraint/unassign_constraint.py
index cff9716809..d9e84cc826 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/constraint/unassign_constraint.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/constraint/unassign_constraint.py
@@ -32,41 +32,35 @@ def unassign_constraint(
other products.
:param products: The list of products the constraint applies to.
- :type products: list[ifcopenshell.entity_instance]
:param constraint: The IfcObjective constraint
- :type constraint: ifcopenshell.entity_instance
:return: None
- :rtype: None
"""
usecase = Usecase()
usecase.file = file
- usecase.settings = {
- "products": products,
- "constraint": constraint,
- }
- return usecase.execute()
+ return usecase.execute(products, constraint)
class Usecase:
- def execute(self):
- products = set(self.settings["products"])
- if not products:
- return
+ file: ifcopenshell.file
- self.constraint = self.settings["constraint"]
- rels = self.get_constraint_rels()
+ def execute(self, products_: list[ifcopenshell.entity_instance], constraint: ifcopenshell.entity_instance):
+ if not products_:
+ return
+ products_set = set(products_)
+
+ rels = self.get_constraint_rels(constraint)
related_objects = set()
for rel in rels:
related_objects.update(rel.RelatedObjects)
- if not related_objects.intersection(products):
+ if not related_objects.intersection(products_set):
return
for rel in rels:
related_objects = set(rel.RelatedObjects)
- if not related_objects.intersection(products):
+ if not related_objects.intersection(products_set):
continue
- related_objects -= products
+ related_objects -= products_set
if related_objects:
rel.RelatedObjects = list(related_objects)
ifcopenshell.api.owner.update_owner_history(self.file, **{"element": rel})
@@ -77,9 +71,9 @@ class Usecase:
if history:
ifcopenshell.util.element.remove_deep2(self.file, history)
- def get_constraint_rels(self) -> list[ifcopenshell.entity_instance]:
+ def get_constraint_rels(self, cosntraint: ifcopenshell.entity_instance) -> list[ifcopenshell.entity_instance]:
rels = []
- for rel in self.file.get_inverse(self.constraint):
+ for rel in self.file.get_inverse(cosntraint):
if rel.is_a("IfcRelAssociatesConstraint"):
rels.append(rel)
return rels
diff --git a/src/ifcopenshell-python/ifcopenshell/api/context/edit_context.py b/src/ifcopenshell-python/ifcopenshell/api/context/edit_context.py
index ba52e83a9e..1a7d567c58 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/context/edit_context.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/context/edit_context.py
@@ -27,11 +27,8 @@ def edit_context(file: ifcopenshell.file, context: ifcopenshell.entity_instance,
IfcGeometricRepresentationContext, consult the IFC documentation.
:param context: The IfcGeometricRepresentationContext entity you want to edit
- :type context: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -47,7 +44,5 @@ def edit_context(file: ifcopenshell.file, context: ifcopenshell.entity_instance,
ifcopenshell.api.context.edit_context(model,
context=body, attributes={"ContextIdentifier": "Body"})
"""
- settings = {"context": context, "attributes": attributes}
-
- for name, value in settings["attributes"].items():
- setattr(settings["context"], name, value)
+ for name, value in attributes.items():
+ setattr(context, name, value)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/cost/copy_cost_item.py b/src/ifcopenshell-python/ifcopenshell/api/cost/copy_cost_item.py
index ac6b563960..fcf298ff7c 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/cost/copy_cost_item.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/cost/copy_cost_item.py
@@ -25,8 +25,6 @@ from typing import Union
def copy_cost_item(
file: ifcopenshell.file, cost_item: ifcopenshell.entity_instance
) -> Union[ifcopenshell.entity_instance, list[ifcopenshell.entity_instance]]:
- # TODO: currently it never returns list of duplicated cost items
- # though it is stated in the docs
"""Copies all cost items and related relationships
The following relationships are also duplicated:
@@ -36,9 +34,7 @@ def copy_cost_item(
* The copy will have duplicated nested cost items
:param cost_item: The cost item to be duplicated
- :type cost_item: ifcopenshell.entity_instance
:return: The duplicated cost item or the list of duplicated cost items if the latter has children
- :rtype: ifcopenshell.entity_instance or list[ifcopenshell.entity_instance]
Example:
.. code:: python
@@ -53,22 +49,29 @@ def copy_cost_item(
"""
usecase = Usecase()
usecase.file = file
- usecase.settings = {"cost_item": cost_item}
- return usecase.execute()
+ return usecase.execute(cost_item)
class Usecase:
- def execute(self):
- self.new_cost_items = []
- return self.duplicate_cost_item(self.settings["cost_item"])
+ file: ifcopenshell.file
+ new_cost_items: list[ifcopenshell.entity_instance]
- def duplicate_cost_item(self, cost_item):
+ def execute(
+ self, cost_item: ifcopenshell.entity_instance
+ ) -> Union[ifcopenshell.entity_instance, list[ifcopenshell.entity_instance]]:
+ self.new_cost_items = []
+ self.duplicate_cost_item(cost_item)
+ return self.new_cost_items[0] if len(self.new_cost_items) == 1 else self.new_cost_items
+
+ def duplicate_cost_item(self, cost_item: ifcopenshell.entity_instance) -> ifcopenshell.entity_instance:
new_cost_item = ifcopenshell.util.element.copy_deep(self.file, cost_item)
self.new_cost_items.append(new_cost_item)
self.copy_indirect_attributes(cost_item, new_cost_item)
return new_cost_item
- def copy_indirect_attributes(self, from_element, to_element):
+ def copy_indirect_attributes(
+ self, from_element: ifcopenshell.entity_instance, to_element: ifcopenshell.entity_instance
+ ) -> None:
for inverse in self.file.get_inverse(from_element):
if inverse.is_a("IfcRelDefinesByProperties"):
inverse = ifcopenshell.util.element.copy(self.file, inverse)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/cost/edit_cost_item.py b/src/ifcopenshell-python/ifcopenshell/api/cost/edit_cost_item.py
index 2417c9ac65..813e306bc8 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/cost/edit_cost_item.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/cost/edit_cost_item.py
@@ -28,11 +28,8 @@ def edit_cost_item(
IfcCostItem, consult the IFC documentation.
:param cost_item: The IfcCostItem entity you want to edit
- :type cost_item: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -42,7 +39,5 @@ def edit_cost_item(
item = ifcopenshell.api.cost.add_cost_item(model, cost_schedule=schedule)
ifcopenshell.api.cost.edit_cost_item(model, cost_item=item, attributes={"Name": "Foo"})
"""
- settings = {"cost_item": cost_item, "attributes": attributes or {}}
-
- for name, value in settings["attributes"].items():
- setattr(settings["cost_item"], name, value)
+ for name, value in attributes.items():
+ setattr(cost_item, name, value)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/cost/edit_cost_item_quantity.py b/src/ifcopenshell-python/ifcopenshell/api/cost/edit_cost_item_quantity.py
index cb265318ac..697d028a37 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/cost/edit_cost_item_quantity.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/cost/edit_cost_item_quantity.py
@@ -28,11 +28,8 @@ def edit_cost_item_quantity(
IfcPhysicalQuantity, consult the IFC documentation.
:param physical_quantity: The IfcPhysicalQuantity entity you want to edit
- :type physical_quantity: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -50,7 +47,5 @@ def edit_cost_item_quantity(
ifcopenshell.api.cost.edit_cost_item_quantity(model,
physical_quantity=quantity, "attributes": {"VolumeValue": 3.0})
"""
- settings = {"physical_quantity": physical_quantity, "attributes": attributes or {}}
-
- for name, value in settings["attributes"].items():
- setattr(settings["physical_quantity"], name, value)
+ for name, value in attributes.items():
+ setattr(physical_quantity, name, value)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/cost/edit_cost_schedule.py b/src/ifcopenshell-python/ifcopenshell/api/cost/edit_cost_schedule.py
index 1c6f42b123..d55e93330e 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/cost/edit_cost_schedule.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/cost/edit_cost_schedule.py
@@ -28,11 +28,8 @@ def edit_cost_schedule(
IfcCostSchedule, consult the IFC documentation.
:param cost_schedule: The IfcCostSchedule entity you want to edit
- :type cost_schedule: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -42,8 +39,5 @@ def edit_cost_schedule(
ifcopenshell.api.cost.edit_cost_schedule(model,
cost_schedule=schedule, attributes={"Name": "Foo"})
"""
-
- settings = {"cost_schedule": cost_schedule, "attributes": attributes or {}}
-
- for name, value in settings["attributes"].items():
- setattr(settings["cost_schedule"], name, value)
+ for name, value in attributes.items():
+ setattr(cost_schedule, name, value)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/cost/edit_cost_value.py b/src/ifcopenshell-python/ifcopenshell/api/cost/edit_cost_value.py
index f3e4e01acd..5812cbcf75 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/cost/edit_cost_value.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/cost/edit_cost_value.py
@@ -31,11 +31,8 @@ def edit_cost_value(
IfcCostValue, consult the IFC documentation.
:param cost_value: The IfcCostValue entity you want to edit
- :type cost_value: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -49,14 +46,12 @@ def edit_cost_value(
ifcopenshell.api.cost.edit_cost_value(model, cost_value=value,
attributes={"AppliedValue": 42.0})
"""
- settings = {"cost_value": cost_value, "attributes": attributes or {}}
-
- for name, value in settings["attributes"].items():
+ for name, value in attributes.items():
if name == "AppliedValue" and value is not None:
# TODO: support all applied value select types
value = file.createIfcMonetaryMeasure(value)
elif name == "UnitBasis":
- old_unit_basis = settings["cost_value"].UnitBasis
+ old_unit_basis = cost_value.UnitBasis
if value:
value_component = file.create_entity(
ifcopenshell.util.unit.get_unit_measure_class(value["UnitComponent"].UnitType),
@@ -65,4 +60,4 @@ def edit_cost_value(
value = file.create_entity("IfcMeasureWithUnit", value_component, value["UnitComponent"])
if old_unit_basis and len(file.get_inverse(old_unit_basis)) == 0:
ifcopenshell.util.element.remove_deep(file, old_unit_basis)
- setattr(settings["cost_value"], name, value)
+ setattr(cost_value, name, value)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/cost/unassign_cost_item_quantity.py b/src/ifcopenshell-python/ifcopenshell/api/cost/unassign_cost_item_quantity.py
index bb815647fd..de180d65ef 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/cost/unassign_cost_item_quantity.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/cost/unassign_cost_item_quantity.py
@@ -30,12 +30,9 @@ def unassign_cost_item_quantity(
have any impact on the cost item.
:param cost_item: The IfcCostItem to remove quantities from
- :type cost_item: ifcopenshell.entity_instance
:param products: A list of IfcProducts that may have parametrically
connected quantities to the cost item
- :type products: list[ifcopenshell.entity_instance]
:return: None
- :rtype: None
Example:
@@ -69,38 +66,39 @@ def unassign_cost_item_quantity(
"""
usecase = Usecase()
usecase.file = file
- usecase.settings = {"cost_item": cost_item, "products": products or []}
- return usecase.execute()
+ return usecase.execute(cost_item, products or [])
class Usecase:
- def execute(self):
- self.quantities = set(self.settings["cost_item"].CostQuantities or [])
- for quantity in self.settings["cost_item"].CostQuantities or []:
+ file: ifcopenshell.file
+
+ def execute(self, cost_item: ifcopenshell.entity_instance, products: list[ifcopenshell.entity_instance]) -> None:
+ quantities = set(cost_item.CostQuantities or [])
+ for quantity in cost_item.CostQuantities or []:
for inverse in self.file.get_inverse(quantity):
if not inverse.is_a("IfcElementQuantity"):
continue
for rel in inverse.DefinesOccurrence or []:
for related_object in rel.RelatedObjects:
- if related_object in self.settings["products"]:
- self.quantities.remove(quantity)
- self.settings["cost_item"].CostQuantities = list(self.quantities)
- for product in self.settings["products"]:
+ if related_object in products:
+ quantities.remove(quantity)
+ cost_item.CostQuantities = list(quantities)
+ for product in products:
ifcopenshell.api.control.unassign_control(
self.file,
related_object=product,
- relating_control=self.settings["cost_item"],
+ relating_control=cost_item,
)
- self.update_cost_item_count()
+ self.update_cost_item_count(cost_item)
- def update_cost_item_count(self):
+ def update_cost_item_count(self, cost_item: ifcopenshell.entity_instance) -> None:
# This is a bold assumption
# https://forums.buildingsmart.org/t/how-does-a-cost-item-know-that-it-is-counting-a-controlled-product/3564
- if len(self.settings["cost_item"].CostQuantities) == 1:
- quantity = self.settings["cost_item"].CostQuantities[0]
+ if len(cost_item.CostQuantities) == 1:
+ quantity = cost_item.CostQuantities[0]
if quantity.is_a("IfcQuantityCount"):
count = 0
- for rel in self.settings["cost_item"].Controls:
+ for rel in cost_item.Controls:
count += len(rel.RelatedObjects)
if count:
quantity[3] = count
diff --git a/src/ifcopenshell-python/ifcopenshell/api/document/assign_document.py b/src/ifcopenshell-python/ifcopenshell/api/document/assign_document.py
index 5627cc1c84..a86a178e86 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/document/assign_document.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/document/assign_document.py
@@ -41,15 +41,12 @@ def assign_document(
:param product: The list of objects to associate the document to. This could be
almost any sensible object in IFC.
- :type product: list[ifcopenshell.entity_instance]
:param document: The IfcDocumentReference to associate to, or
alternatively an IfcDocumentInformation, though this is not
recommended.
- :type document: ifcopenshell.entity_instance
:return: The IfcRelAssociatesDocument relationship
or `None` if `products` was an empty list or all products were
already assigned to the `document`.
- :rtype: ifcopenshell.entity_instance
Example:
@@ -65,43 +62,41 @@ def assign_document(
# Let's imagine storey represents an IfcBuildingStorey for the ground floor
ifcopenshell.api.document.assign_document(model, products=[storey], document=reference)
"""
- settings = {
- "products": products,
- "document": document,
- }
# TODO: do we need to support non-ifcroot elements like we do in classification.add_reference?
# NOTE: reuses code from `library.assign_reference`
- referenced_elements = ifcopenshell.util.element.get_referenced_elements(settings["document"])
- products: set[ifcopenshell.entity_instance] = set(settings["products"])
- products = products - referenced_elements
+ referenced_elements = ifcopenshell.util.element.get_referenced_elements(document)
+ products_set: set[ifcopenshell.entity_instance] = set(products)
+ products_set = products_set - referenced_elements
- if not products:
+ if not products_set:
return
if file.schema == "IFC2X3":
rel = next(
- (r for r in file.by_type("IfcRelAssociatesDocument") if r.RelatingDocument == settings["document"]),
+ (r for r in file.by_type("IfcRelAssociatesDocument") if r.RelatingDocument == document),
None,
)
else:
- ifc_class = settings["document"].is_a()
+ ifc_class = document.is_a()
if ifc_class == "IfcDocumentReference":
- rel = next(iter(settings["document"].DocumentRefForObjects), None)
+ rel = next(iter(document.DocumentRefForObjects), None)
elif ifc_class == "IfcDocumentInformation":
- rel = next(iter(settings["document"].DocumentInfoForObjects), None)
+ rel = next(iter(document.DocumentInfoForObjects), None)
+ else:
+ assert False, f"Unexpected document type: {ifc_class}"
if not rel:
return file.create_entity(
"IfcRelAssociatesDocument",
GlobalId=ifcopenshell.guid.new(),
OwnerHistory=ifcopenshell.api.owner.create_owner_history(file),
- RelatedObjects=list(products),
- RelatingDocument=settings["document"],
+ RelatedObjects=list(products_set),
+ RelatingDocument=document,
)
- related_objects = set(rel.RelatedObjects) | products
+ related_objects = set(rel.RelatedObjects) | products_set
rel.RelatedObjects = list(related_objects)
ifcopenshell.api.owner.update_owner_history(file, element=rel)
return rel
diff --git a/src/ifcopenshell-python/ifcopenshell/api/document/edit_information.py b/src/ifcopenshell-python/ifcopenshell/api/document/edit_information.py
index 09d697f7db..56c1d40df4 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/document/edit_information.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/document/edit_information.py
@@ -30,11 +30,8 @@ def edit_information(
IfcDocumentInformation, consult the IFC documentation.
:param reference: The IfcDocumentInformation entity you want to edit
- :type reference: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -46,7 +43,5 @@ def edit_information(
attributes={"Identification": "A-GA-6100", "Name": "Overall Plan",
"Location": "A-GA-6100 - Overall Plan.pdf"})
"""
- settings = {"information": information, "attributes": attributes}
-
- for name, value in settings["attributes"].items():
- setattr(settings["information"], name, value)
+ for name, value in attributes.items():
+ setattr(information, name, value)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/document/edit_reference.py b/src/ifcopenshell-python/ifcopenshell/api/document/edit_reference.py
index 5a00827305..51ad195bf3 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/document/edit_reference.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/document/edit_reference.py
@@ -30,11 +30,8 @@ def edit_reference(
IfcDocumentReference, consult the IFC documentation.
:param reference: The IfcDocumentReference entity you want to edit
- :type reference: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -49,7 +46,5 @@ def edit_reference(
ifcopenshell.api.document.edit_reference(model,
reference=reference, attributes={"Identification": "2.1.15"})
"""
- settings = {"reference": reference, "attributes": attributes}
-
- for name, value in settings["attributes"].items():
- setattr(settings["reference"], name, value)
+ for name, value in attributes.items():
+ setattr(reference, name, value)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/drawing/edit_text_literal.py b/src/ifcopenshell-python/ifcopenshell/api/drawing/edit_text_literal.py
index 1f7356e989..c083960e59 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/drawing/edit_text_literal.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/drawing/edit_text_literal.py
@@ -28,11 +28,8 @@ def edit_text_literal(
IfcTextLiteral, consult the IFC documentation.
:param reference: The IfcTextLiteral entity you want to edit
- :type reference: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -42,7 +39,5 @@ def edit_text_literal(
ifcopenshell.api.drawing.edit_text_literal(model,
text_literal=text, attributes={"Literal": "MY ANNOTATION"})
"""
- settings = {"text_literal": text_literal, "attributes": attributes or {}}
-
- for name, value in settings["attributes"].items():
- setattr(settings["text_literal"], name, value)
+ for name, value in attributes.items():
+ setattr(text_literal, name, value)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/geometry/add_axis_representation.py b/src/ifcopenshell-python/ifcopenshell/api/geometry/add_axis_representation.py
index 1883374b97..174c475f92 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/geometry/add_axis_representation.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/geometry/add_axis_representation.py
@@ -17,7 +17,7 @@
# along with IfcOpenShell. If not, see .
import ifcopenshell.util.unit
-from typing import Union
+from typing import Union, Any
COORD = Union[tuple[float, float], tuple[float, float, float]]
@@ -82,6 +82,9 @@ def add_axis_representation(
class Usecase:
+ file: ifcopenshell.file
+ settings: dict[str, Any]
+
def execute(self):
self.settings["unit_scale"] = ifcopenshell.util.unit.calculate_unit_scale(self.file)
is_2d = len(self.settings["axis"][0]) == 2
diff --git a/src/ifcopenshell-python/ifcopenshell/api/geometry/add_footprint_representation.py b/src/ifcopenshell-python/ifcopenshell/api/geometry/add_footprint_representation.py
index 6b48845e4e..9d5fe9f20b 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/geometry/add_footprint_representation.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/geometry/add_footprint_representation.py
@@ -26,14 +26,9 @@ def add_footprint_representation(
# A list of IFC curves to include in the curve set
curves: list[ifcopenshell.entity_instance],
) -> ifcopenshell.entity_instance:
- settings = {
- "context": context,
- "curves": curves,
- }
-
return file.createIfcShapeRepresentation(
- settings["context"],
- settings["context"].ContextIdentifier,
+ context,
+ context.ContextIdentifier,
"GeometricCurveSet",
- [file.createIfcGeometricCurveSet(settings["curves"])],
+ [file.createIfcGeometricCurveSet(curves)],
)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/geometry/add_mesh_representation.py b/src/ifcopenshell-python/ifcopenshell/api/geometry/add_mesh_representation.py
index efe6aa5c89..940315621a 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/geometry/add_mesh_representation.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/geometry/add_mesh_representation.py
@@ -17,7 +17,7 @@
# along with IfcOpenShell. If not, see .
import ifcopenshell.util.unit
-from typing import Optional
+from typing import Optional, Any
COORD_3D = tuple[float, float, float]
@@ -60,6 +60,9 @@ def add_mesh_representation(
class Usecase:
+ file: ifcopenshell.file
+ settings: dict[str, Any]
+
def execute(self):
if self.settings["unit_scale"] is None:
self.settings["unit_scale"] = ifcopenshell.util.unit.calculate_unit_scale(self.file)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/geometry/add_profile_representation.py b/src/ifcopenshell-python/ifcopenshell/api/geometry/add_profile_representation.py
index 17cdec58c8..77bb515996 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/geometry/add_profile_representation.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/geometry/add_profile_representation.py
@@ -52,6 +52,9 @@ def add_profile_representation(
class Usecase:
+ file: ifcopenshell.file
+ settings: dict[str, Any]
+
def execute(self):
self.settings["unit_scale"] = ifcopenshell.util.unit.calculate_unit_scale(self.file)
self.settings["clippings"] = [Clipping.parse(c) for c in self.settings["clippings"]]
diff --git a/src/ifcopenshell-python/ifcopenshell/api/geometry/add_window_representation.py b/src/ifcopenshell-python/ifcopenshell/api/geometry/add_window_representation.py
index 22fb99d583..fdc457367b 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/geometry/add_window_representation.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/geometry/add_window_representation.py
@@ -426,6 +426,9 @@ def add_window_representation(
class Usecase:
+ file: ifcopenshell.file
+ settings: dict[str, Any]
+
def execute(self):
builder = ShapeBuilder(self.file)
np_X, np_Y, np_Z = 0, 1, 2
diff --git a/src/ifcopenshell-python/ifcopenshell/api/geometry/connect_path.py b/src/ifcopenshell-python/ifcopenshell/api/geometry/connect_path.py
index 571c5212ba..81fa276a2c 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/geometry/connect_path.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/geometry/connect_path.py
@@ -31,53 +31,33 @@ def connect_path(
related_connection: str = "NOTDEFINED",
description: Optional[str] = None,
) -> ifcopenshell.entity_instance:
- settings = {
- "relating_element": relating_element,
- "related_element": related_element,
- "relating_connection": relating_connection,
- "related_connection": related_connection,
- "description": description,
- }
-
- incompatible_connections = []
- for rel in settings["relating_element"].ConnectedTo:
+ incompatible_connections: list[ifcopenshell.entity_instance] = []
+ for rel in relating_element.ConnectedTo:
if not rel.is_a("IfcRelConnectsPathElements"):
continue
- if rel.RelatedElement == settings["related_element"]:
+ if rel.RelatedElement == related_element:
incompatible_connections.append(rel)
- elif (
- rel.RelatingConnectionType in ["ATSTART", "ATEND"]
- and rel.RelatingConnectionType == settings["relating_connection"]
- ):
+ elif rel.RelatingConnectionType in ["ATSTART", "ATEND"] and rel.RelatingConnectionType == relating_connection:
incompatible_connections.append(rel)
- for rel in settings["relating_element"].ConnectedFrom:
+ for rel in relating_element.ConnectedFrom:
if not rel.is_a("IfcRelConnectsPathElements"):
continue
- if (
- rel.RelatedConnectionType in ["ATSTART", "ATEND"]
- and rel.RelatedConnectionType == settings["relating_connection"]
- ):
+ if rel.RelatedConnectionType in ["ATSTART", "ATEND"] and rel.RelatedConnectionType == relating_connection:
incompatible_connections.append(rel)
- for rel in settings["related_element"].ConnectedFrom:
+ for rel in related_element.ConnectedFrom:
if not rel.is_a("IfcRelConnectsPathElements"):
continue
- if (
- rel.RelatedConnectionType in ["ATSTART", "ATEND"]
- and rel.RelatedConnectionType == settings["related_connection"]
- ):
+ if rel.RelatedConnectionType in ["ATSTART", "ATEND"] and rel.RelatedConnectionType == related_connection:
incompatible_connections.append(rel)
- for rel in settings["related_element"].ConnectedTo:
+ for rel in related_element.ConnectedTo:
if not rel.is_a("IfcRelConnectsPathElements"):
continue
- if rel.RelatedElement == settings["relating_element"]:
+ if rel.RelatedElement == relating_element:
incompatible_connections.append(rel)
- elif (
- rel.RelatingConnectionType in ["ATSTART", "ATEND"]
- and rel.RelatingConnectionType == settings["related_connection"]
- ):
+ elif rel.RelatingConnectionType in ["ATSTART", "ATEND"] and rel.RelatingConnectionType == related_connection:
incompatible_connections.append(rel)
if incompatible_connections:
@@ -87,14 +67,15 @@ def connect_path(
if history:
ifcopenshell.util.element.remove_deep2(file, history)
- return file.createIfcRelConnectsPathElements(
+ return file.create_entity(
+ "IfcRelConnectsPathElements",
ifcopenshell.guid.new(),
OwnerHistory=ifcopenshell.api.owner.create_owner_history(file),
- Description=settings["description"],
- RelatingElement=settings["relating_element"],
- RelatedElement=settings["related_element"],
- RelatingConnectionType=settings["relating_connection"],
- RelatedConnectionType=settings["related_connection"],
+ Description=description,
+ RelatingElement=relating_element,
+ RelatedElement=related_element,
+ RelatingConnectionType=relating_connection,
+ RelatedConnectionType=related_connection,
RelatingPriorities=[],
RelatedPriorities=[],
)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/group/assign_group.py b/src/ifcopenshell-python/ifcopenshell/api/group/assign_group.py
index 64a4f571dc..4972058fb4 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/group/assign_group.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/group/assign_group.py
@@ -46,29 +46,25 @@ def assign_group(
ifcopenshell.api.group.assign_group(model,
products=model.by_type("IfcFurniture"), group=group)
"""
- settings = {
- "products": products,
- "group": group,
- }
-
- if not settings["products"]:
+ if not products:
return
- if not settings["group"].IsGroupedBy:
+ is_grouped_by: tuple[ifcopenshell.entity_instance, ...]
+ if not (is_grouped_by := group.IsGroupedBy):
return file.create_entity(
"IfcRelAssignsToGroup",
**{
"GlobalId": ifcopenshell.guid.new(),
"OwnerHistory": ifcopenshell.api.owner.create_owner_history(file),
- "RelatedObjects": settings["products"],
- "RelatingGroup": settings["group"],
- }
+ "RelatedObjects": products,
+ "RelatingGroup": group,
+ },
)
- rel = settings["group"].IsGroupedBy[0]
+ rel = is_grouped_by[0]
related_objects = set(rel.RelatedObjects) or set()
- products = set(settings["products"])
- if products.issubset(related_objects):
+ products_set = set(products)
+ if products_set.issubset(related_objects):
return rel
- rel.RelatedObjects = list(related_objects | products)
+ rel.RelatedObjects = list(related_objects | products_set)
ifcopenshell.api.owner.update_owner_history(file, **{"element": rel})
return rel
diff --git a/src/ifcopenshell-python/ifcopenshell/api/group/edit_group.py b/src/ifcopenshell-python/ifcopenshell/api/group/edit_group.py
index a404ef0f88..5a7a2b2018 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/group/edit_group.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/group/edit_group.py
@@ -26,11 +26,8 @@ def edit_group(file: ifcopenshell.file, group: ifcopenshell.entity_instance, att
IfcGroup, consult the IFC documentation.
:param group: The IfcGroup entity you want to edit
- :type group: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -40,7 +37,5 @@ def edit_group(file: ifcopenshell.file, group: ifcopenshell.entity_instance, att
ifcopenshell.api.group.edit_group(model,
group=group, attributes={"Description": "All furniture and joinery included in the unit"})
"""
- settings = {"group": group, "attributes": attributes}
-
- for name, value in settings["attributes"].items():
- setattr(settings["group"], name, value)
+ for name, value in attributes.items():
+ setattr(group, name, value)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/group/unassign_group.py b/src/ifcopenshell-python/ifcopenshell/api/group/unassign_group.py
index ee31336eec..cac87106aa 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/group/unassign_group.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/group/unassign_group.py
@@ -46,17 +46,12 @@ def unassign_group(
bad_furniture = furniture[0]
ifcopenshell.api.group.unassign_group(model, products=[bad_furniture], group=group)
"""
- settings = {
- "products": products,
- "group": group,
- }
-
- if not settings["group"].IsGroupedBy:
+ if not group.IsGroupedBy:
return
- rel = settings["group"].IsGroupedBy[0]
+ rel = group.IsGroupedBy[0]
related_objects = set(rel.RelatedObjects) or set()
- products = set(settings["products"])
- related_objects -= products
+ products_set = set(products)
+ related_objects -= products_set
if related_objects:
rel.RelatedObjects = list(related_objects)
ifcopenshell.api.owner.update_owner_history(file, **{"element": rel})
diff --git a/src/ifcopenshell-python/ifcopenshell/api/group/update_group_products.py b/src/ifcopenshell-python/ifcopenshell/api/group/update_group_products.py
index 61b3ec7657..468c193ff7 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/group/update_group_products.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/group/update_group_products.py
@@ -45,24 +45,19 @@ def update_group_products(
ifcopenshell.api.group.update_group_products(model,
products=model.by_type("IfcFurniture"), group=group)
"""
- settings = {
- "group": group,
- "products": products,
- }
-
- if not settings["group"].IsGroupedBy:
+ if not group.IsGroupedBy:
return file.create_entity(
"IfcRelAssignsToGroup",
**{
"GlobalId": ifcopenshell.guid.new(),
"OwnerHistory": ifcopenshell.api.owner.create_owner_history(file),
- "RelatedObjects": settings["products"],
- "RelatingGroup": settings["group"],
+ "RelatedObjects": products,
+ "RelatingGroup": group,
}
)
else:
- rels = settings["group"].IsGroupedBy
- objects = set(settings["products"])
+ rels = group.IsGroupedBy
+ objects = set(products)
for rel in rels:
objects.update([g for g in rel.RelatedObjects if g.is_a("IfcGroup")])
to_purge = rels[1:]
diff --git a/src/ifcopenshell-python/ifcopenshell/api/layer/edit_layer.py b/src/ifcopenshell-python/ifcopenshell/api/layer/edit_layer.py
index 6f55f5da1d..7203fabb0c 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/layer/edit_layer.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/layer/edit_layer.py
@@ -37,7 +37,5 @@ def edit_layer(file: ifcopenshell.file, layer: ifcopenshell.entity_instance, att
ifcopenshell.api.layer.edit_layer(model,
layer=layer, attributes={"Description": "All walls, based on the AIA standard."})
"""
- settings = {"layer": layer, "attributes": attributes}
-
- for name, value in settings["attributes"].items():
- setattr(settings["layer"], name, value)
+ for name, value in attributes.items():
+ setattr(layer, name, value)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/layer/unassign_layer.py b/src/ifcopenshell-python/ifcopenshell/api/layer/unassign_layer.py
index 97ae094a50..3eb0ed8fa1 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/layer/unassign_layer.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/layer/unassign_layer.py
@@ -61,17 +61,11 @@ def unassign_layer(
# Let's undo it!
ifcopenshell.api.layer.unassign_layer(model, items=[representation.Items[0]], layer=layer)
"""
- settings = {
- "items": items,
- "layer": layer,
- }
-
- layer = settings["layer"]
assigned_items = set(layer.AssignedItems) or set()
- items = set(settings["items"])
- if not items.issubset(assigned_items):
+ items_set = set(items)
+ if not items_set.issubset(assigned_items):
return
- assigned_items = list(assigned_items - items)
+ assigned_items = list(assigned_items - items_set)
# keep IFC valid in case if there are no items left
if assigned_items:
diff --git a/src/ifcopenshell-python/ifcopenshell/api/library/edit_library.py b/src/ifcopenshell-python/ifcopenshell/api/library/edit_library.py
index b3bc87b1c3..4e12195bda 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/library/edit_library.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/library/edit_library.py
@@ -28,11 +28,8 @@ def edit_library(file: ifcopenshell.file, library: ifcopenshell.entity_instance,
IfcLibraryInformation, consult the IFC documentation.
:param library: The IfcLibraryInformation entity you want to edit
- :type library: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
diff --git a/src/ifcopenshell-python/ifcopenshell/api/library/edit_reference.py b/src/ifcopenshell-python/ifcopenshell/api/library/edit_reference.py
index f3016fd9cf..e6acacbd8f 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/library/edit_reference.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/library/edit_reference.py
@@ -28,11 +28,8 @@ def edit_reference(
IfcLibraryReference, consult the IFC documentation.
:param reference: The IfcLibraryReference entity you want to edit
- :type reference: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -44,7 +41,5 @@ def edit_reference(
ifcopenshell.api.library.edit_reference(model,
reference=reference, attributes={"Identification": "http://example.org/digitaltwin#AHU01"})
"""
- settings = {"reference": reference, "attributes": attributes}
-
- for name, value in settings["attributes"].items():
- setattr(settings["reference"], name, value)
+ for name, value in attributes.items():
+ setattr(reference, name, value)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/material/assign_profile.py b/src/ifcopenshell-python/ifcopenshell/api/material/assign_profile.py
index 7719fd86c8..24fa93487b 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/material/assign_profile.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/material/assign_profile.py
@@ -17,6 +17,7 @@
# along with IfcOpenShell. If not, see .
import ifcopenshell.util.representation
+from typing import Any
def assign_profile(
@@ -97,6 +98,7 @@ def assign_profile(
class Usecase:
file: ifcopenshell.file
+ settings: dict[str, Any]
def execute(self) -> None:
# TODO: handle composite profiles
diff --git a/src/ifcopenshell-python/ifcopenshell/api/material/edit_assigned_material.py b/src/ifcopenshell-python/ifcopenshell/api/material/edit_assigned_material.py
index 939e995a06..9a01322743 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/material/edit_assigned_material.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/material/edit_assigned_material.py
@@ -28,11 +28,8 @@ def edit_assigned_material(
IfcMaterial, consult the IFC documentation.
:param element: The IfcMaterial entity you want to edit
- :type element: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -42,7 +39,5 @@ def edit_assigned_material(
ifcopenshell.api.material.edit_assigned_material(model,
element=concrete, attributes={"Description": "40MPA concrete with broom finish"})
"""
- settings = {"element": element, "attributes": attributes}
-
- for name, value in settings["attributes"].items():
- setattr(settings["element"], name, value)
+ for name, value in attributes.items():
+ setattr(element, name, value)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/material/edit_constituent.py b/src/ifcopenshell-python/ifcopenshell/api/material/edit_constituent.py
index eda33d349b..a7398ca5f0 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/material/edit_constituent.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/material/edit_constituent.py
@@ -31,13 +31,9 @@ def edit_constituent(
IfcMaterialConstituent, consult the IFC documentation.
:param constituent: The IfcMaterialConstituent entity you want to edit
- :type constituent: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict, optional
:param material: The IfcMaterial entity you want to change the constituent to
- :type material: ifcopenshell.entity_instance, optional
:return: None
- :rtype: None
Example:
@@ -65,8 +61,6 @@ def edit_constituent(
ifcopenshell.api.material.edit_constituent(model,
constituent=constituent, attributes={"Name": "Glazing"})
"""
- settings = {"constituent": constituent, "attributes": attributes or {}, "material": material}
-
- for name, value in settings["attributes"].items():
- setattr(settings["constituent"], name, value)
- settings["constituent"].Material = settings["material"]
+ for name, value in (attributes or {}).items():
+ setattr(constituent, name, value)
+ constituent.Material = material
diff --git a/src/ifcopenshell-python/ifcopenshell/api/material/edit_layer.py b/src/ifcopenshell-python/ifcopenshell/api/material/edit_layer.py
index d691d6b154..68f3c6d832 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/material/edit_layer.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/material/edit_layer.py
@@ -31,14 +31,10 @@ def edit_layer(
IfcMaterialLayer, consult the IFC documentation.
:param layer: The IfcMaterialLayer entity you want to edit
- :type layer: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict, optional
:param material: The IfcMaterial entity you want the layer to be made
from.
- :type material: ifcopenshell.entity_instance, optional
:return: None
- :rtype: None
Example:
@@ -63,9 +59,7 @@ def edit_layer(
layer = ifcopenshell.api.material.add_layer(model, layer_set=material_set, material=gypsum)
ifcopenshell.api.material.edit_layer(model, layer=layer, attributes={"LayerThickness": 13})
"""
- settings = {"layer": layer, "attributes": attributes or {}, "material": material}
-
- for name, value in settings["attributes"].items():
- setattr(settings["layer"], name, value)
- if settings["material"]:
- settings["layer"].Material = settings["material"]
+ for name, value in (attributes or {}).items():
+ setattr(layer, name, value)
+ if material:
+ layer.Material = material
diff --git a/src/ifcopenshell-python/ifcopenshell/api/material/edit_layer_usage.py b/src/ifcopenshell-python/ifcopenshell/api/material/edit_layer_usage.py
index 6c581c1374..9d1ffb14ec 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/material/edit_layer_usage.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/material/edit_layer_usage.py
@@ -29,11 +29,8 @@ def edit_layer_usage(file: ifcopenshell.file, usage: ifcopenshell.entity_instanc
IfcMaterialLayerSetUsage, consult the IFC documentation.
:param usage: The IfcMaterialLayerSetUsage entity you want to edit
- :type usage: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -75,7 +72,5 @@ def edit_layer_usage(file: ifcopenshell.file, usage: ifcopenshell.entity_instanc
ifcopenshell.api.material.edit_layer_usage(model,
usage=rel.RelatingMaterial, attributes={"OffsetFromReferenceLine": 200})
"""
- settings = {"usage": usage, "attributes": attributes}
-
- for name, value in settings["attributes"].items():
- setattr(settings["usage"], name, value)
+ for name, value in attributes.items():
+ setattr(usage, name, value)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/material/edit_profile.py b/src/ifcopenshell-python/ifcopenshell/api/material/edit_profile.py
index 17f925997e..c35755a960 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/material/edit_profile.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/material/edit_profile.py
@@ -34,17 +34,12 @@ def edit_profile(
IfcMaterialProfile, consult the IFC documentation.
:param profile: The IfcMaterialProfile entity you want to edit
- :type profile: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict, optional
:param profile_def: The IfcProfileDef entity the profile curve should be
extruded from.
- :type profile_def: ifcopenshell.entity_instance, optional
:param material: The IfcMaterial entity you want to change the profile
to be made from.
- :type material: ifcopenshell.entity_instance, optional
:return: None
- :rtype: None
Example:
@@ -80,16 +75,9 @@ def edit_profile(
ifcopenshell.api.material.edit_profile(model,
profile=profile_item, profile_def=hea200, material=steel2)
"""
- settings = {
- "profile": profile,
- "attributes": attributes or {},
- "profile_def": profile_def,
- "material": material,
- }
-
- for name, value in settings["attributes"].items():
- setattr(settings["profile"], name, value)
- if settings["material"]:
- settings["profile"].Material = settings["material"]
- if settings["profile_def"]:
- settings["profile"].Profile = settings["profile_def"]
+ for name, value in (attributes or {}).items():
+ setattr(profile, name, value)
+ if material:
+ profile.Material = material
+ if profile_def:
+ profile.Profile = profile_def
diff --git a/src/ifcopenshell-python/ifcopenshell/api/material/edit_profile_usage.py b/src/ifcopenshell-python/ifcopenshell/api/material/edit_profile_usage.py
index f9894db5b3..4a659f251c 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/material/edit_profile_usage.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/material/edit_profile_usage.py
@@ -17,6 +17,7 @@
# along with IfcOpenShell. If not, see .
import ifcopenshell.geom
import ifcopenshell.util.representation
+from ifcopenshell.geom import ShapeType
from typing import Any
@@ -34,11 +35,8 @@ def edit_profile_usage(
IfcMaterialProfileSetUsage, consult the IFC documentation.
:param usage: The IfcMaterialProfileSetUsage entity you want to edit
- :type usage: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -98,16 +96,19 @@ def edit_profile_usage(
class Usecase:
- def execute(self):
- self.cardinal_point = self.settings["attributes"].get("CardinalPoint")
- if self.cardinal_point and self.cardinal_point != self.settings["usage"].CardinalPoint:
+ file: ifcopenshell.file
+
+ def execute(self, usage: ifcopenshell.entity_instance, attributes: dict[str, Any]) -> None:
+ self.attributes = attributes
+ self.cardinal_point = attributes.get("CardinalPoint")
+ if self.cardinal_point and self.cardinal_point != usage.CardinalPoint:
self.update_cardinal_point()
- for name, value in self.settings["attributes"].items():
- setattr(self.settings["usage"], name, value)
+ for name, value in attributes.items():
+ setattr(usage, name, value)
def update_cardinal_point(self):
- material_set = self.settings["usage"].ForProfileSet
+ material_set = self.attributes["usage"].ForProfileSet
self.profile = material_set.CompositeProfile
if not self.profile and material_set.MaterialProfiles:
self.profile = material_set.MaterialProfiles[0].Profile
@@ -117,13 +118,13 @@ class Usecase:
self.position = self.calculate_position()
if self.file.schema == "IFC2X3":
- for rel in self.file.get_inverse(self.settings["usage"]):
+ for rel in self.file.get_inverse(self.attributes["usage"]):
if not rel.is_a("IfcRelAssociatesMaterial"):
continue
for element in rel.RelatedObjects:
self.update_representation(element)
else:
- for rel in self.settings["usage"].AssociatedTo:
+ for rel in self.attributes["usage"].AssociatedTo:
for element in rel.RelatedObjects:
self.update_representation(element)
@@ -166,7 +167,7 @@ class Usecase:
elif self.cardinal_point == 9:
return self.get_top_right(shape)
- def get_bottom_left(self, shape):
+ def get_bottom_left(self, shape: ShapeType) -> ifcopenshell.entity_instance:
v = shape.verts
x = [v[i] for i in range(0, len(v), 3)]
y = [v[i + 1] for i in range(0, len(v), 3)]
@@ -174,13 +175,13 @@ class Usecase:
height = max(y) - min(y)
return self.file.createIfcAxis2Placement3D(self.file.createIfcCartesianPoint((-width / 2, height / 2, 0.0)))
- def get_bottom_centre(self, shape):
+ def get_bottom_centre(self, shape: ShapeType) -> ifcopenshell.entity_instance:
v = shape.verts
y = [v[i + 1] for i in range(0, len(v), 3)]
height = max(y) - min(y)
return self.file.createIfcAxis2Placement3D(self.file.createIfcCartesianPoint((0.0, height / 2, 0.0)))
- def get_bottom_right(self, shape):
+ def get_bottom_right(self, shape: ShapeType) -> ifcopenshell.entity_instance:
v = shape.verts
x = [v[i] for i in range(0, len(v), 3)]
y = [v[i + 1] for i in range(0, len(v), 3)]
@@ -188,22 +189,22 @@ class Usecase:
height = max(y) - min(y)
return self.file.createIfcAxis2Placement3D(self.file.createIfcCartesianPoint((width / 2, height / 2, 0.0)))
- def get_mid_depth_left(self, shape):
+ def get_mid_depth_left(self, shape: ShapeType) -> ifcopenshell.entity_instance:
v = shape.verts
x = [v[i] for i in range(0, len(v), 3)]
width = max(x) - min(x)
return self.file.createIfcAxis2Placement3D(self.file.createIfcCartesianPoint((-width / 2, 0.0, 0.0)))
- def get_mid_depth_centre(self, shape):
+ def get_mid_depth_centre(self, shape: ShapeType) -> ifcopenshell.entity_instance:
return self.file.createIfcAxis2Placement3D(self.file.createIfcCartesianPoint((0.0, 0.0, 0.0)))
- def get_mid_depth_right(self, shape):
+ def get_mid_depth_right(self, shape: ShapeType) -> ifcopenshell.entity_instance:
v = shape.verts
x = [v[i] for i in range(0, len(v), 3)]
width = max(x) - min(x)
return self.file.createIfcAxis2Placement3D(self.file.createIfcCartesianPoint((width / 2, 0.0, 0.0)))
- def get_top_left(self, shape):
+ def get_top_left(self, shape: ShapeType) -> ifcopenshell.entity_instance:
v = shape.verts
x = [v[i] for i in range(0, len(v), 3)]
y = [v[i + 1] for i in range(0, len(v), 3)]
@@ -211,13 +212,13 @@ class Usecase:
height = max(y) - min(y)
return self.file.createIfcAxis2Placement3D(self.file.createIfcCartesianPoint((-width / 2, -height / 2, 0.0)))
- def get_top_centre(self, shape):
+ def get_top_centre(self, shape: ShapeType) -> ifcopenshell.entity_instance:
v = shape.verts
y = [v[i + 1] for i in range(0, len(v), 3)]
height = max(y) - min(y)
return self.file.createIfcAxis2Placement3D(self.file.createIfcCartesianPoint((0.0, -height / 2, 0.0)))
- def get_top_right(self, shape):
+ def get_top_right(self, shape: ShapeType) -> ifcopenshell.entity_instance:
v = shape.verts
x = [v[i] for i in range(0, len(v), 3)]
y = [v[i + 1] for i in range(0, len(v), 3)]
@@ -225,7 +226,7 @@ class Usecase:
height = max(y) - min(y)
return self.file.createIfcAxis2Placement3D(self.file.createIfcCartesianPoint((width / 2, -height / 2, 0.0)))
- def update_representation(self, element):
+ def update_representation(self, element: ifcopenshell.entity_instance) -> None:
representation = ifcopenshell.util.representation.get_representation(element, "Model", "Body", "MODEL_VIEW")
if not representation:
return
@@ -234,5 +235,5 @@ class Usecase:
if subelement.is_a("IfcSweptAreaSolid") and subelement.SweptArea == self.profile:
self.update_swept_area_solid(subelement)
- def update_swept_area_solid(self, element):
+ def update_swept_area_solid(self, element: ifcopenshell.entity_instance) -> None:
element.Position = self.position
diff --git a/src/ifcopenshell-python/ifcopenshell/api/material/remove_constituent.py b/src/ifcopenshell-python/ifcopenshell/api/material/remove_constituent.py
index 7521c48a15..d9401cfa6d 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/material/remove_constituent.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/material/remove_constituent.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 ifcopenshell
+import ifcopenshell.util.element
def remove_constituent(
diff --git a/src/ifcopenshell-python/ifcopenshell/api/material/remove_list_item.py b/src/ifcopenshell-python/ifcopenshell/api/material/remove_list_item.py
index cd4f2f1cd6..6af15a7d3a 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/material/remove_list_item.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/material/remove_list_item.py
@@ -54,8 +54,6 @@ def remove_list_item(
# Let's remove the glass
ifcopenshell.api.material.remove_list_item(model, material_list=material_set, material_index=1)
"""
- settings = {"material_list": material_list, "material_index": material_index}
-
- materials = list(settings["material_list"].Materials)
- materials.pop(settings["material_index"])
- settings["material_list"].Materials = materials
+ materials = list(material_list.Materials)
+ materials.pop(material_index)
+ material_list.Materials = materials
diff --git a/src/ifcopenshell-python/ifcopenshell/api/material/reorder_set_item.py b/src/ifcopenshell-python/ifcopenshell/api/material/reorder_set_item.py
index 0015d3558a..aa06433e66 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/material/reorder_set_item.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/material/reorder_set_item.py
@@ -57,16 +57,17 @@ def reorder_set_item(
ifcopenshell.api.material.reorder_set_item(model,
material_set=material_set, old_index=0, new_index=1)
"""
- settings = {"material_set": material_set, "old_index": old_index, "new_index": new_index}
-
- if settings["material_set"].is_a("IfcMaterialConstituentSet"):
+ if material_set.is_a("IfcMaterialConstituentSet"):
set_name = "MaterialConstituents"
- elif settings["material_set"].is_a("IfcMaterialLayerSet"):
+ elif material_set.is_a("IfcMaterialLayerSet"):
set_name = "MaterialLayers"
- elif settings["material_set"].is_a("IfcMaterialProfileSet"):
+ elif material_set.is_a("IfcMaterialProfileSet"):
set_name = "MaterialProfiles"
- elif settings["material_set"].is_a("IfcMaterialList"):
+ elif material_set.is_a("IfcMaterialList"):
set_name = "Materials"
- items = list(getattr(settings["material_set"], set_name) or [])
- items.insert(settings["new_index"], items.pop(settings["old_index"]))
- setattr(settings["material_set"], set_name, items)
+ else:
+ raise ValueError(f"Unexpected material set type: '{material_set.is_a()}'.")
+
+ items = list(getattr(material_set, set_name) or [])
+ items.insert(new_index, items.pop(old_index))
+ setattr(material_set, set_name, items)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/material/unassign_material.py b/src/ifcopenshell-python/ifcopenshell/api/material/unassign_material.py
index 8db2060df0..f8386490c7 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/material/unassign_material.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/material/unassign_material.py
@@ -19,6 +19,7 @@
import ifcopenshell
import ifcopenshell.api.owner
import ifcopenshell.util.element
+from typing import Any
def unassign_material(file: ifcopenshell.file, products: list[ifcopenshell.entity_instance]) -> None:
@@ -58,6 +59,9 @@ def unassign_material(file: ifcopenshell.file, products: list[ifcopenshell.entit
class Usecase:
+ file: ifcopenshell.file
+ settings: dict[str, Any]
+
def execute(self):
self.products = set(self.settings["products"])
if not self.products:
diff --git a/src/ifcopenshell-python/ifcopenshell/api/owner/add_application.py b/src/ifcopenshell-python/ifcopenshell/api/owner/add_application.py
index 991006be01..3f18754287 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/owner/add_application.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/owner/add_application.py
@@ -17,7 +17,7 @@
# along with IfcOpenShell. If not, see .
import ifcopenshell.api
-from typing import Optional
+from typing import Optional, Any
def add_application(
@@ -68,6 +68,9 @@ def add_application(
class Usecase:
+ file: ifcopenshell.file
+ settings: dict[str, Any]
+
def execute(self):
if not self.settings["application_developer"]:
self.settings["application_developer"] = self.create_application_organisation()
diff --git a/src/ifcopenshell-python/ifcopenshell/api/owner/add_role.py b/src/ifcopenshell-python/ifcopenshell/api/owner/add_role.py
index 7105e5e78d..75bb5eb517 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/owner/add_role.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/owner/add_role.py
@@ -48,16 +48,14 @@ def add_role(
identification="AWB", name="Architects Without Ballpens")
ifcopenshell.api.owner.add_role(model, assigned_object=organisation, role="ARCHITECT")
"""
- settings = {"assigned_object": assigned_object, "role": role}
-
- element = file.createIfcActorRole("ARCHITECT")
- if settings["role"]:
+ element = file.create_entity("IfcActorRole", Role="ARCHITECT")
+ if role:
try:
- element.Role = settings["role"]
+ element.Role = role
except:
element.Role = "USERDEFINED"
- element.UserDefinedRole = settings["role"]
- roles = list(settings["assigned_object"].Roles) if settings["assigned_object"].Roles else []
+ element.UserDefinedRole = role
+ roles = list(assigned_object.Roles) if assigned_object.Roles else []
roles.append(element)
- settings["assigned_object"].Roles = roles
+ assigned_object.Roles = roles
return element
diff --git a/src/ifcopenshell-python/ifcopenshell/api/owner/edit_actor.py b/src/ifcopenshell-python/ifcopenshell/api/owner/edit_actor.py
index 799b37462c..8ad238f994 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/owner/edit_actor.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/owner/edit_actor.py
@@ -26,11 +26,8 @@ def edit_actor(file: ifcopenshell.file, actor: ifcopenshell.entity_instance, att
IfcActor, consult the IFC documentation.
:param actor: The IfcActor entity you want to edit
- :type actor: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -49,7 +46,5 @@ def edit_actor(file: ifcopenshell.file, actor: ifcopenshell.entity_instance, att
ifcopenshell.api.actor.edit_actor(model,
actor=actor, attributes={"Description": "Responsible for buildings A, B, and C."})
"""
- settings = {"actor": actor, "attributes": attributes}
-
- for name, value in settings["attributes"].items():
- setattr(settings["actor"], name, value)
+ for name, value in attributes.items():
+ setattr(actor, name, value)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/owner/edit_address.py b/src/ifcopenshell-python/ifcopenshell/api/owner/edit_address.py
index 43776fa711..52e80d6ef1 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/owner/edit_address.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/owner/edit_address.py
@@ -26,11 +26,8 @@ def edit_address(file: ifcopenshell.file, address: ifcopenshell.entity_instance,
IfcAddress, consult the IFC documentation.
:param address: The IfcAddress entity you want to edit
- :type address: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -51,7 +48,5 @@ def edit_address(file: ifcopenshell.file, address: ifcopenshell.entity_instance,
"ElectronicMailAddresses": ["bobthebuilder@example.com"],
"WWWHomePageURL": "https://thinkmoult.com"})
"""
- settings = {"address": address, "attributes": attributes}
-
- for name, value in settings["attributes"].items():
- setattr(settings["address"], name, value)
+ for name, value in attributes.items():
+ setattr(address, name, value)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/owner/edit_organisation.py b/src/ifcopenshell-python/ifcopenshell/api/owner/edit_organisation.py
index 9cfbfff48d..a2bb5e3eb6 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/owner/edit_organisation.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/owner/edit_organisation.py
@@ -28,11 +28,8 @@ def edit_organisation(
IfcOrganization, consult the IFC documentation.
:param organisation: The IfcOrganization entity you want to edit
- :type organisation: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -43,7 +40,5 @@ def edit_organisation(
ifcopenshell.api.owner.edit_organisation(model, organisation=organisation,
attributes={"name": "Architects Without Ballpens"})
"""
- settings = {"organisation": organisation, "attributes": attributes}
-
- for name, value in settings["attributes"].items():
- setattr(settings["organisation"], name, value)
+ for name, value in attributes.items():
+ setattr(organisation, name, value)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/owner/edit_person.py b/src/ifcopenshell-python/ifcopenshell/api/owner/edit_person.py
index 0e4bd15293..6b697bd674 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/owner/edit_person.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/owner/edit_person.py
@@ -26,11 +26,8 @@ def edit_person(file: ifcopenshell.file, person: ifcopenshell.entity_instance, a
IfcPerson, consult the IFC documentation.
:param person: The IfcPerson entity you want to edit
- :type person: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -41,7 +38,5 @@ def edit_person(file: ifcopenshell.file, person: ifcopenshell.entity_instance, a
ifcopenshell.api.owner.edit_person(model, person=person,
attributes={"MiddleNames": ["The"], "FamilyName": "Builder"})
"""
- settings = {"person": person, "attributes": attributes}
-
- for name, value in settings["attributes"].items():
- setattr(settings["person"], name, value)
+ for name, value in attributes.items():
+ setattr(person, name, value)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/owner/edit_role.py b/src/ifcopenshell-python/ifcopenshell/api/owner/edit_role.py
index 885d4b9b9b..fca80a16b0 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/owner/edit_role.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/owner/edit_role.py
@@ -26,11 +26,8 @@ def edit_role(file: ifcopenshell.file, role: ifcopenshell.entity_instance, attri
IfcActorRole, consult the IFC documentation.
:param role: The IfcActorRole entity you want to edit
- :type role: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -45,7 +42,5 @@ def edit_role(file: ifcopenshell.file, role: ifcopenshell.entity_instance, attri
# But Bob is not an architect
ifcopenshell.api.owner.edit_role(model, role=role, attributes={"Role": "CONSTRUCTIONMANAGER"})
"""
- settings = {"role": role, "attributes": attributes}
-
- for name, value in settings["attributes"].items():
- setattr(settings["role"], name, value)
+ for name, value in attributes.items():
+ setattr(role, name, value)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/profile/add_arbitrary_profile.py b/src/ifcopenshell-python/ifcopenshell/api/profile/add_arbitrary_profile.py
index 08892a555b..80f3b8cf71 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/profile/add_arbitrary_profile.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/profile/add_arbitrary_profile.py
@@ -16,12 +16,14 @@
# You should have received a copy of the GNU Lesser General Public License
# along with IfcOpenShell. If not, see .
+import numpy.typing as npt
import ifcopenshell.util.unit
-from typing import Optional
+from ifcopenshell.util.shape_builder import V, SequenceOfVectors, ifc_safe_vector_type
+from typing import Optional, Union
def add_arbitrary_profile(
- file: ifcopenshell.file, profile: list[tuple[float, float]], name: Optional[str] = None
+ file: ifcopenshell.file, profile: SequenceOfVectors, name: Optional[str] = None
) -> ifcopenshell.entity_instance:
"""Adds a new arbitrary polyline-based profile
@@ -33,13 +35,10 @@ def add_arbitrary_profile(
identical.
:param profile: A list of coordinates
- :type profile: list[tuple[float, float]]
:param name: If the profile is semantically significant (i.e. to be
managed and reused by the user) then it must be named. Otherwise,
this may be left as none.
- :type name: str, optional
:return: The newly created IfcArbitraryClosedProfileDef
- :rtype: ifcopenshell.entity_instance
Example:
@@ -53,26 +52,30 @@ def add_arbitrary_profile(
"""
usecase = Usecase()
usecase.file = file
- usecase.settings = {"profile": profile, "name": name}
- return usecase.execute()
+ return usecase.execute(V(profile), name)
class Usecase:
- def execute(self):
- self.settings["unit_scale"] = ifcopenshell.util.unit.calculate_unit_scale(self.file)
- points = [self.convert_si_to_unit(p) for p in self.settings["profile"]]
- if self.file.schema == "IFC2X3":
- curve = self.file.createIfcPolyline([self.file.createIfcCartesianPoint(p) for p in points])
- else:
- dimensions = len(points[0])
- if dimensions == 2:
- ifc_points = self.file.createIfcCartesianPointList2D(points)
- elif dimensions == 3:
- ifc_points = self.file.createIfcCartesianPointList3D(points)
- curve = self.file.createIfcIndexedPolyCurve(ifc_points)
- return self.file.createIfcArbitraryClosedProfileDef("AREA", self.settings["name"], curve)
+ file: ifcopenshell.file
- def convert_si_to_unit(self, co):
- if isinstance(co, (tuple, list)):
- return [self.convert_si_to_unit(o) for o in co]
- return co / self.settings["unit_scale"]
+ def execute(self, profile: npt.NDArray, name: Union[str, None]):
+ self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(self.file)
+ points = self.convert_si_to_unit(profile)
+ if self.file.schema == "IFC2X3":
+ curve = self.file.create_entity(
+ "IfcPolyline",
+ [self.file.create_entity("IfcCartesianPoint", ifc_safe_vector_type(p)) for p in points],
+ )
+ else:
+ dimensions = points.shape[1]
+ if dimensions == 2:
+ ifc_points = self.file.create_entity("IfcCartesianPointList2D", ifc_safe_vector_type(points))
+ elif dimensions == 3:
+ ifc_points = self.file.create_entity("IfcCartesianPointList3D", ifc_safe_vector_type(points))
+ else:
+ assert False, f"Invalid dimensions: {dimensions}."
+ curve = self.file.create_entity("IfcIndexedPolyCurve", ifc_points)
+ return self.file.create_entity("IfcArbitraryClosedProfileDef", "AREA", name, curve)
+
+ def convert_si_to_unit(self, co: npt.NDArray) -> npt.NDArray:
+ return co / self.unit_scale
diff --git a/src/ifcopenshell-python/ifcopenshell/api/profile/add_arbitrary_profile_with_voids.py b/src/ifcopenshell-python/ifcopenshell/api/profile/add_arbitrary_profile_with_voids.py
index 8412d40e23..b813a3c65f 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/profile/add_arbitrary_profile_with_voids.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/profile/add_arbitrary_profile_with_voids.py
@@ -17,13 +17,15 @@
# along with IfcOpenShell. If not, see .
import ifcopenshell.util.unit
-from typing import Optional
+import numpy.typing as npt
+from ifcopenshell.util.shape_builder import SequenceOfVectors, ifc_safe_vector_type, V
+from typing import Optional, Union
def add_arbitrary_profile_with_voids(
file: ifcopenshell.file,
- outer_profile: list[tuple[float, float]],
- inner_profiles: list[list[tuple[float, float]]],
+ outer_profile: SequenceOfVectors,
+ inner_profiles: list[SequenceOfVectors],
name: Optional[str] = None,
) -> ifcopenshell.entity_instance:
"""Adds a new arbitrary polyline-based profile with voids
@@ -41,15 +43,11 @@ def add_arbitrary_profile_with_voids(
provided in SI meters.
:param outer_profile: A list of coordinates
- :type profile: list[tuple[float, float]]
:param inner_profiles: A list of polylines
- :type profile: list[list[tuple[float, float]]]
:param name: If the profile is semantically significant (i.e. to be
managed and reused by the user) then it must be named. Otherwise,
this may be left as none.
- :type name: str, optional
:return: The newly created IfcArbitraryProfileDefWithVoids
- :rtype: ifcopenshell.entity_instance
Example:
@@ -63,37 +61,52 @@ def add_arbitrary_profile_with_voids(
"""
usecase = Usecase()
usecase.file = file
- usecase.settings = {"outer_profile": outer_profile, "inner_profiles": inner_profiles, "name": name}
- return usecase.execute()
+ return usecase.execute(V(outer_profile), [V(p) for p in inner_profiles], name)
class Usecase:
- def execute(self):
- self.settings["unit_scale"] = ifcopenshell.util.unit.calculate_unit_scale(self.file)
- outer_points = [self.convert_si_to_unit(p) for p in self.settings["outer_profile"]]
- inner_points = []
- for inner_profile in self.settings["inner_profiles"]:
- inner_points.append([self.convert_si_to_unit(p) for p in inner_profile])
+ file: ifcopenshell.file
+
+ def execute(
+ self,
+ outer_profile: npt.NDArray,
+ inner_profiles: list[npt.NDArray],
+ name: Union[str, None],
+ ):
+ self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(self.file)
+ outer_points = self.convert_si_to_unit(outer_profile)
+ inner_points: list[npt.NDArray] = []
+ for inner_profile in inner_profiles:
+ inner_points.append(self.convert_si_to_unit(inner_profile))
+
+ inner_curves: list[ifcopenshell.entity_instance] = []
if self.file.schema == "IFC2X3":
- outer_curve = self.file.createIfcPolyline([self.file.createIfcCartesianPoint(p) for p in outer_points])
- inner_curves = []
+ outer_curve = self.file.create_entity(
+ "IfcPolyline",
+ [self.file.create_entity("IfcCartesianPoint", ifc_safe_vector_type(p)) for p in outer_points],
+ )
for inner_point in inner_points:
inner_curves.append(
- self.file.createIfcPolyline([self.file.createIfcCartesianPoint(p) for p in inner_point])
+ self.file.create_entity(
+ "IfcPolyline",
+ [self.file.create_entity("IfcCartesianPoint", ifc_safe_vector_type(p)) for p in inner_point],
+ )
)
else:
- outer_curve = self.file.createIfcIndexedPolyCurve(self.file.createIfcCartesianPointList3D(outer_points))
- inner_curves = []
+ outer_curve = self.file.create_entity(
+ "IfcIndexedPolyCurve",
+ (self.file.create_entity("IfcCartesianPointList3D", ifc_safe_vector_type(outer_points))),
+ )
for inner_point in inner_points:
- dimensions = len(inner_point[0])
+ dimensions = inner_point.shape[1]
if dimensions == 2:
- ifc_points = self.file.createIfcCartesianPointList2D(inner_point)
+ ifc_points = self.file.create_entity("IfcCartesianPointList2D", ifc_safe_vector_type(inner_point))
elif dimensions == 3:
- ifc_points = self.file.createIfcCartesianPointList3D(inner_point)
- inner_curves.append(self.file.createIfcIndexedPolyCurve(ifc_points))
- return self.file.createIfcArbitraryProfileDefWithVoids("AREA", self.settings["name"], outer_curve, inner_curves)
+ ifc_points = self.file.create_entity("IfcCartesianPointList3D", ifc_safe_vector_type(inner_point))
+ else:
+ assert False, f"Invalid dimensions: {dimensions}."
+ inner_curves.append(self.file.create_entity("IfcIndexedPolyCurve", ifc_points))
+ return self.file.create_entity("IfcArbitraryProfileDefWithVoids", "AREA", name, outer_curve, inner_curves)
- def convert_si_to_unit(self, co):
- if isinstance(co, (tuple, list)):
- return [self.convert_si_to_unit(o) for o in co]
- return co / self.settings["unit_scale"]
+ def convert_si_to_unit(self, co: npt.NDArray) -> npt.NDArray:
+ return co / self.unit_scale
diff --git a/src/ifcopenshell-python/ifcopenshell/api/profile/edit_profile.py b/src/ifcopenshell-python/ifcopenshell/api/profile/edit_profile.py
index b1fda065f0..ba7bc3cfeb 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/profile/edit_profile.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/profile/edit_profile.py
@@ -26,11 +26,8 @@ def edit_profile(file: ifcopenshell.file, profile: ifcopenshell.entity_instance,
IfcProfileDef, consult the IFC documentation.
:param profile: The IfcProfileDef entity you want to edit
- :type profile: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -43,7 +40,5 @@ def edit_profile(file: ifcopenshell.file, profile: ifcopenshell.entity_instance,
ifcopenshell.api.profile.edit_profile(model,
profile=circle, attributes={"ProfileName": "1000mm Dia"})
"""
- settings = {"profile": profile, "attributes": attributes}
-
- for name, value in settings["attributes"].items():
- setattr(settings["profile"], name, value)
+ for name, value in attributes.items():
+ setattr(profile, name, value)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/pset/add_pset.py b/src/ifcopenshell-python/ifcopenshell/api/pset/add_pset.py
index ffa31faa8e..db585c3276 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/pset/add_pset.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/pset/add_pset.py
@@ -20,7 +20,7 @@ import ifcopenshell
import ifcopenshell.api.owner
import ifcopenshell.api.pset
import ifcopenshell.guid
-from typing import Optional
+from typing import Optional, Any
def add_pset(
@@ -92,12 +92,11 @@ def add_pset(
# Add a fire rating property standardised by buildingSMART.
ifcopenshell.api.pset.edit_pset(model, pset=pset, properties={"FireRating": "2HR"})
"""
- settings = {"product": product, "name": name}
is_ifc2x3 = file.schema == "IFC2X3"
- if settings["product"].is_a("IfcObject") or settings["product"].is_a("IfcContext"):
- for rel in settings["product"].IsDefinedBy or []:
- if rel.is_a("IfcRelDefinesByProperties") and rel.RelatingPropertyDefinition.Name == settings["name"]:
+ if product.is_a("IfcObject") or product.is_a("IfcContext"):
+ for rel in product.IsDefinedBy or []:
+ if rel.is_a("IfcRelDefinesByProperties") and rel.RelatingPropertyDefinition.Name == name:
return rel.RelatingPropertyDefinition
pset = file.create_entity(
@@ -105,15 +104,15 @@ def add_pset(
**{
"GlobalId": ifcopenshell.guid.new(),
"OwnerHistory": ifcopenshell.api.owner.create_owner_history(file),
- "Name": settings["name"],
+ "Name": name,
},
)
- ifcopenshell.api.pset.assign_pset(file, [settings["product"]], pset)
+ ifcopenshell.api.pset.assign_pset(file, [product], pset)
return pset
- elif settings["product"].is_a("IfcTypeObject"):
- for definition in settings["product"].HasPropertySets or []:
- if definition.Name == settings["name"]:
+ elif product.is_a("IfcTypeObject"):
+ for definition in product.HasPropertySets or []:
+ if definition.Name == name:
return definition
pset = file.create_entity(
@@ -121,42 +120,43 @@ def add_pset(
**{
"GlobalId": ifcopenshell.guid.new(),
"OwnerHistory": ifcopenshell.api.owner.create_owner_history(file),
- "Name": settings["name"],
+ "Name": name,
},
)
- ifcopenshell.api.pset.assign_pset(file, [settings["product"]], pset)
+ ifcopenshell.api.pset.assign_pset(file, [product], pset)
return pset
# in IFC2X3 IfcMaterialDefinition not yet existed
- elif settings["product"].is_a("IfcMaterialDefinition") or settings["product"].is_a("IfcMaterial"):
- kwargs = {"Material": settings["product"]}
+ elif product.is_a("IfcMaterialDefinition") or product.is_a("IfcMaterial"):
+ kwargs: dict[str, Any]
+ kwargs = {"Material": product}
if file.schema == "IFC2X3":
ifc_class = ifc2x3_subclass or "IfcExtendedMaterialProperties"
- definitions = (d for d in file.by_type("IfcMaterialProperties") if d.Material == settings["product"])
+ definitions = (d for d in file.by_type("IfcMaterialProperties") if d.Material == product)
if ifc_class == "IfcExtendedMaterialProperties":
- kwargs["Name"] = settings["name"]
+ kwargs["Name"] = name
else:
ifc_class = "IfcMaterialProperties"
- definitions = settings["product"].HasProperties
- kwargs["Name"] = settings["name"]
+ definitions = product.HasProperties
+ kwargs["Name"] = name
for definition in definitions:
# In IFC2X3 not all IfcMaterialProperties has Name
- if getattr(definition, "Name", None) == settings["name"]:
+ if getattr(definition, "Name", None) == name:
return definition
return file.create_entity(ifc_class, **kwargs)
- elif settings["product"].is_a("IfcProfileDef"):
+ elif product.is_a("IfcProfileDef"):
# in IFC2X3 IfcProfileProperties doesn't have Name and we cannot identify them
if file.schema != "IFC2X3":
- for definition in settings["product"].HasProperties or []:
- if definition.Name == settings["name"]:
+ for definition in product.HasProperties or []:
+ if definition.Name == name:
return definition
kwargs = {}
- kwargs["ProfileDefinition"] = settings["product"]
+ kwargs["ProfileDefinition"] = product
if file.schema != "IFC2X3":
- kwargs["Name"] = settings["name"]
+ kwargs["Name"] = name
if is_ifc2x3:
ifc_class = ifc2x3_subclass or "IfcGeneralProfileProperties"
@@ -164,4 +164,4 @@ def add_pset(
ifc_class = "IfcProfileProperties"
return file.create_entity(ifc_class, **kwargs)
- raise TypeError(f"Class '{settings['product'].is_a(True)}' doesn't support adding a property set.")
+ raise TypeError(f"Class '{product.is_a(True)}' doesn't support adding a property set.")
diff --git a/src/ifcopenshell-python/ifcopenshell/api/pset/add_qto.py b/src/ifcopenshell-python/ifcopenshell/api/pset/add_qto.py
index 15646fe9c7..415b8ec187 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/pset/add_qto.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/pset/add_qto.py
@@ -19,6 +19,7 @@
import ifcopenshell
import ifcopenshell.api.owner
import ifcopenshell.guid
+from typing import Any
def add_qto(file: ifcopenshell.file, product: ifcopenshell.entity_instance, name: str) -> ifcopenshell.entity_instance:
@@ -83,9 +84,15 @@ def add_qto(file: ifcopenshell.file, product: ifcopenshell.entity_instance, name
class Usecase:
+ file: ifcopenshell.file
+ settings: dict[str, Any]
+
def execute(self):
- if self.settings["product"].is_a("IfcObject") or self.settings["product"].is_a("IfcContext"):
- for rel in self.settings["product"].IsDefinedBy or []:
+ product: ifcopenshell.entity_instance = self.settings["product"]
+ name: str = self.settings["name"]
+
+ if product.is_a("IfcObject") or product.is_a("IfcContext"):
+ for rel in product.IsDefinedBy or []:
if (
rel.is_a("IfcRelDefinesByProperties")
and rel.RelatingPropertyDefinition.Name == self.settings["name"]
@@ -103,14 +110,14 @@ class Usecase:
}
)
return qto
- elif self.settings["product"].is_a("IfcTypeObject"):
- for definition in self.settings["product"].HasPropertySets or []:
- if definition.Name == self.settings["name"]:
+ elif product.is_a("IfcTypeObject"):
+ for definition in product.HasPropertySets or []:
+ if definition.Name == name:
return definition
qto = self.create_qto()
- has_property_sets = list(self.settings["product"].HasPropertySets or [])
+ has_property_sets = list(product.HasPropertySets or [])
has_property_sets.append(qto)
- self.settings["product"].HasPropertySets = has_property_sets
+ product.HasPropertySets = has_property_sets
return qto
def create_qto(self):
diff --git a/src/ifcopenshell-python/ifcopenshell/api/pset_template/edit_prop_template.py b/src/ifcopenshell-python/ifcopenshell/api/pset_template/edit_prop_template.py
index 1984506c30..3677a8e63e 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/pset_template/edit_prop_template.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/pset_template/edit_prop_template.py
@@ -28,11 +28,8 @@ def edit_prop_template(
IfcSimplePropertyTemplate, consult the IFC documentation.
:param prop_template: The IfcSimplePropertyTemplate entity you want to edit
- :type prop_template: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
diff --git a/src/ifcopenshell-python/ifcopenshell/api/pset_template/edit_pset_template.py b/src/ifcopenshell-python/ifcopenshell/api/pset_template/edit_pset_template.py
index 1682fa150d..d143b5554e 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/pset_template/edit_pset_template.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/pset_template/edit_pset_template.py
@@ -28,11 +28,8 @@ def edit_pset_template(
IfcPropertySetTemplate, consult the IFC documentation.
:param pset_template: The IfcPropertySetTemplate entity you want to edit
- :type pset_template: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -45,7 +42,5 @@ def edit_pset_template(
ifcopenshell.api.pset_template.edit_pset_template(model,
pset_template=template, attributes={"Name": "ABC_RiskFactors"})
"""
- settings = {"pset_template": pset_template, "attributes": attributes}
-
- for name, value in settings["attributes"].items():
- setattr(settings["pset_template"], name, value)
+ for name, value in attributes.items():
+ setattr(pset_template, name, value)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/resource/add_resource_quantity.py b/src/ifcopenshell-python/ifcopenshell/api/resource/add_resource_quantity.py
index b445c1d1ad..fc67a8d3c7 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/resource/add_resource_quantity.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/resource/add_resource_quantity.py
@@ -36,15 +36,12 @@ def add_resource_quantity(
This base quantity is then used in other calculations.
:param resource: The IfcConstructionResource to add a quantity to.
- :type resource: ifcopenshell.entity_instance
:param ifc_class: The type of quantity to add, chosen from
IfcQuantityArea (for material), IfcQuantityCount (for products),
IfcQuantityLength (for material), IfcQuantityTime (for equipment or
labour), IfcQuantityVolume (for material), and IfcQuantityWeight
(for material).
- :type ifc_class: str,optional
:return: The newly created quantity depending on the IFC class
- :rtype: ifcopenshell.entity_instance
Example:
@@ -65,8 +62,6 @@ def add_resource_quantity(
ifcopenshell.api.resource.edit_resource_quantity(model,
physical_quantity=quantity, attributes={"TimeValue": 8.0})
"""
- settings = {"resource": resource, "ifc_class": ifc_class}
-
resource_type = resource.is_a()
supported_quantities = ifcopenshell.util.resource.RESOURCES_TO_QUANTITIES[resource_type]
if ifc_class not in supported_quantities:
@@ -75,14 +70,14 @@ def add_resource_quantity(
f"Supported quantities: {','.join(supported_quantities)}"
)
- quantity = file.create_entity(settings["ifc_class"], Name="Unnamed")
+ quantity = file.create_entity(ifc_class, Name="Unnamed")
# 3 IfcPhysicalSimpleQuantity Value
- if settings["ifc_class"] == "IfcQuantityCount":
+ if ifc_class == "IfcQuantityCount":
quantity[3] = 0
else:
quantity[3] = 0.0
- old_quantity = settings["resource"].BaseQuantity
- settings["resource"].BaseQuantity = quantity
+ old_quantity = resource.BaseQuantity
+ resource.BaseQuantity = quantity
if old_quantity:
ifcopenshell.util.element.remove_deep(file, old_quantity)
return quantity
diff --git a/src/ifcopenshell-python/ifcopenshell/api/resource/edit_resource.py b/src/ifcopenshell-python/ifcopenshell/api/resource/edit_resource.py
index b5bb899ead..3476032c1a 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/resource/edit_resource.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/resource/edit_resource.py
@@ -26,11 +26,8 @@ def edit_resource(file: ifcopenshell.file, resource: ifcopenshell.entity_instanc
IfcResource, consult the IFC documentation.
:param resource: The IfcResource entity you want to edit
- :type resource: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -42,7 +39,5 @@ def edit_resource(file: ifcopenshell.file, resource: ifcopenshell.entity_instanc
# Change the name of the resource to "Zone A Crew"
ifcopenshell.api.resource.edit_resource(model, resource=resource, attributes={"Name": "Foo"})
"""
- settings = {"resource": resource, "attributes": attributes}
-
- for name, value in settings["attributes"].items():
- setattr(settings["resource"], name, value)
+ for name, value in attributes.items():
+ setattr(resource, name, value)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/resource/edit_resource_quantity.py b/src/ifcopenshell-python/ifcopenshell/api/resource/edit_resource_quantity.py
index af8f55f94f..87a14774d8 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/resource/edit_resource_quantity.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/resource/edit_resource_quantity.py
@@ -28,11 +28,8 @@ def edit_resource_quantity(
IfC quantity, consult the IFC documentation.
:param physical_quantity: The IfC quantity entity you want to edit
- :type physical_quantity: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -53,10 +50,5 @@ def edit_resource_quantity(
ifcopenshell.api.resource.edit_resource_quantity(model,
physical_quantity=time, attributes={"TimeValue": 8.0})
"""
- settings = {
- "physical_quantity": physical_quantity,
- "attributes": attributes,
- }
-
- for name, value in settings["attributes"].items():
- setattr(settings["physical_quantity"], name, value)
+ for name, value in attributes.items():
+ setattr(physical_quantity, name, value)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/resource/edit_resource_time.py b/src/ifcopenshell-python/ifcopenshell/api/resource/edit_resource_time.py
index 687fe0490d..7326a5fd90 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/resource/edit_resource_time.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/resource/edit_resource_time.py
@@ -18,6 +18,9 @@
import ifcopenshell
import ifcopenshell.api.sequence
+import ifcopenshell.util.constraint
+import ifcopenshell.util.date
+import ifcopenshell.util.resource
from typing import Any
@@ -30,11 +33,8 @@ def edit_resource_time(
IfcResourceTime, consult the IFC documentation.
:param resource_time: The IfcResourceTime entity you want to edit
- :type resource_time: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -62,25 +62,23 @@ def edit_resource_time(
"""
usecase = Usecase()
usecase.file = file
- usecase.settings = {"resource_time": resource_time, "attributes": attributes}
- return usecase.execute()
+ return usecase.execute(resource_time, attributes)
class Usecase:
- def execute(self):
- self.resource = self.get_resource()
+ file: ifcopenshell.file
+
+ def execute(self, resource_time: ifcopenshell.entity_instance, attributes: dict[str, Any]) -> None:
+ resource = self.get_resource(resource_time)
# If the user specifies both an end date and a duration, the duration takes priority
- if (
- self.settings["attributes"].get("ScheduleWork", None)
- and "ScheduleFinish" in self.settings["attributes"].keys()
- ):
- del self.settings["attributes"]["ScheduleFinish"]
- if self.settings["attributes"].get("ActualWork", None) and "ActualFinish" in self.settings["attributes"].keys():
- del self.settings["attributes"]["ActualFinish"]
+ if attributes.get("ScheduleWork", None) and "ScheduleFinish" in attributes.keys():
+ del attributes["ScheduleFinish"]
+ if attributes.get("ActualWork", None) and "ActualFinish" in attributes.keys():
+ del attributes["ActualFinish"]
- for name, value in self.settings["attributes"].items():
- metrics = ifcopenshell.util.constraint.get_metric_constraints(self.resource, "Usage." + name)
+ for name, value in attributes.items():
+ metrics = ifcopenshell.util.constraint.get_metric_constraints(resource, "Usage." + name)
if metrics and ifcopenshell.util.constraint.is_hard_constraint(metrics[0]):
continue
if value:
@@ -88,13 +86,13 @@ class Usecase:
value = ifcopenshell.util.date.datetime2ifc(value, "IfcDateTime")
elif name == "ScheduleWork" or name == "ActualWork" or name == "RemainingTime":
value = ifcopenshell.util.date.datetime2ifc(value, "IfcDuration")
- setattr(self.settings["resource_time"], name, value)
+ setattr(resource_time, name, value)
if name == "ScheduleUsage" and ifcopenshell.util.constraint.get_metric_constraints(
- self.resource, "Usage.ScheduleWork"
+ resource, "Usage.ScheduleWork"
):
- task = ifcopenshell.util.resource.get_task_assignments(self.resource)
+ task = ifcopenshell.util.resource.get_task_assignments(resource)
if task:
ifcopenshell.api.sequence.calculate_task_duration(self.file, task=task)
- def get_resource(self):
- return [e for e in self.file.get_inverse(self.settings["resource_time"]) if e.is_a("IfcResource")][0]
+ def get_resource(self, resource_time: ifcopenshell.entity_instance) -> ifcopenshell.entity_instance:
+ return next(e for e in self.file.get_inverse(resource_time) if e.is_a("IfcResource"))
diff --git a/src/ifcopenshell-python/ifcopenshell/api/root/copy_class.py b/src/ifcopenshell-python/ifcopenshell/api/root/copy_class.py
index a55c711e53..6f02a4531d 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/root/copy_class.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/root/copy_class.py
@@ -23,6 +23,7 @@ import ifcopenshell.api.geometry
import ifcopenshell.util.system
import ifcopenshell.util.element
import ifcopenshell.util.placement
+from typing import Any
def copy_class(file: ifcopenshell.file, product: ifcopenshell.entity_instance) -> ifcopenshell.entity_instance:
@@ -74,6 +75,9 @@ def copy_class(file: ifcopenshell.file, product: ifcopenshell.entity_instance) -
class Usecase:
+ file: ifcopenshell.file
+ settings: dict[str, Any]
+
def execute(self):
result = ifcopenshell.util.element.copy(self.file, self.settings["product"])
self.copy_direct_attributes(result)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/root/create_entity.py b/src/ifcopenshell-python/ifcopenshell/api/root/create_entity.py
index a31dc4c00a..67d67ed7f2 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/root/create_entity.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/root/create_entity.py
@@ -19,7 +19,7 @@
import ifcopenshell
import ifcopenshell.api.owner
import ifcopenshell.guid
-from typing import Optional
+from typing import Optional, Any
def create_entity(
@@ -80,6 +80,9 @@ def create_entity(
class Usecase:
+ file: ifcopenshell.file
+ settings: dict[str, Any]
+
def execute(self):
element = self.file.create_entity(
self.settings["ifc_class"],
diff --git a/src/ifcopenshell-python/ifcopenshell/api/root/reassign_class.py b/src/ifcopenshell-python/ifcopenshell/api/root/reassign_class.py
index 3e4cd3faf4..7682856864 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/root/reassign_class.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/root/reassign_class.py
@@ -27,7 +27,7 @@ import ifcopenshell.util.representation
import ifcopenshell.util.type
import ifcopenshell.util.schema
import ifcopenshell.util.element
-from typing import Optional, Union, Literal
+from typing import Optional, Union, Literal, Any
def reassign_class(
@@ -87,6 +87,7 @@ def reassign_class(
class Usecase:
file: ifcopenshell.file
+ settings: dict[str, Any]
def execute(self):
ifc_class: str = self.settings["ifc_class"]
diff --git a/src/ifcopenshell-python/ifcopenshell/api/sequence/add_task_time.py b/src/ifcopenshell-python/ifcopenshell/api/sequence/add_task_time.py
index 89037d4eb0..38d64aa1bc 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/sequence/add_task_time.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/sequence/add_task_time.py
@@ -29,11 +29,8 @@ def add_task_time(
(especially for maintenance tasks).
:param task: The task to add time data to.
- :type task: ifcopenshell.entity_instance
:param is_recurring: Whether or not the time should recur.
- :type is_recurring: bool
:return: The newly created IfcTaskTime.
- :rtype: ifcopenshell.entity_instance
Example:
@@ -61,11 +58,9 @@ def add_task_time(
ifcopenshell.api.sequence.edit_task_time(model,
task_time=time, attributes={"ScheduleStart": "2000-01-01", "ScheduleDuration": "P2D"})
"""
- settings = {"task": task, "is_recurring": is_recurring}
-
- if settings["is_recurring"]:
+ if is_recurring:
task_time = file.create_entity("IfcTaskTimeRecurring")
else:
task_time = file.create_entity("IfcTaskTime")
- settings["task"].TaskTime = task_time
+ task.TaskTime = task_time
return task_time
diff --git a/src/ifcopenshell-python/ifcopenshell/api/sequence/assign_lag_time.py b/src/ifcopenshell-python/ifcopenshell/api/sequence/assign_lag_time.py
index 65ea1db9bd..a5d813756e 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/sequence/assign_lag_time.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/sequence/assign_lag_time.py
@@ -34,17 +34,13 @@ def assign_lag_time(
are allowed.
:param rel_sequence: The IfcRelSequence to assign the lag time to.
- :type rel_sequence: ifcopenshell.entity_instance
:param lag_value: An ISO standardised duration string.
- :type lag_value: str
:param duration_type: Choose from WORKTIME for the associated
calendar-based lag times (this is the most common scenario and is
recommended as a default), or ELAPSEDTIME to not follow the
calendar. You may also choose NOTDEFINED but the behaviour of this
is unclear.
- :type duration_type: str
:return: The newly created IfcLagTime
- :rtype: ifcopenshell.entity_instance
Example:
@@ -84,16 +80,10 @@ def assign_lag_time(
# for whatever reason.
ifcopenshell.api.sequence.assign_lag_time(model, rel_sequence=sequence, lag_value="P1D")
"""
- settings = {
- "rel_sequence": rel_sequence,
- "lag_value": lag_value,
- "duration_type": duration_type,
- }
-
- lag_value = file.createIfcDuration(ifcopenshell.util.date.datetime2ifc(settings["lag_value"], "IfcDuration"))
- lag_time = file.create_entity("IfcLagTime", DurationType=settings["duration_type"], LagValue=lag_value)
- if settings["rel_sequence"].is_a("IfcRelSequence"):
- if settings["rel_sequence"].TimeLag and len(file.get_inverse(settings["rel_sequence"].TimeLag)) == 1:
- file.remove(settings["rel_sequence"].TimeLag)
- settings["rel_sequence"].TimeLag = lag_time
+ lag_value = file.create_entity("IfcDuration", ifcopenshell.util.date.datetime2ifc(lag_value, "IfcDuration"))
+ lag_time = file.create_entity("IfcLagTime", DurationType=duration_type, LagValue=lag_value)
+ if rel_sequence.is_a("IfcRelSequence"):
+ if rel_sequence.TimeLag and len(file.get_inverse(rel_sequence.TimeLag)) == 1:
+ file.remove(rel_sequence.TimeLag)
+ rel_sequence.TimeLag = lag_time
return lag_time
diff --git a/src/ifcopenshell-python/ifcopenshell/api/sequence/assign_recurrence_pattern.py b/src/ifcopenshell-python/ifcopenshell/api/sequence/assign_recurrence_pattern.py
index 0c64fb09e2..333aefb418 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/sequence/assign_recurrence_pattern.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/sequence/assign_recurrence_pattern.py
@@ -65,11 +65,8 @@ def assign_recurrence_pattern(
:param parent: Either an IfcTaskTimeRecurring if you are defining a
recurring schedule for a task, or IfcWorkTime if you are defining a
recurring pattern for a workdays or holidays in a calendar.
- :type parent: ifcopenshell.entity_instance
:param recurrence_type: One of the types of recurrences.
- :type recurrence_type: str
:return: The newly created IfcRecurrencePattern
- :rtype: ifcopenshell.entity_instance
Example:
@@ -108,16 +105,14 @@ def assign_recurrence_pattern(
ifcopenshell.api.sequence.edit_recurrence_pattern(model,
recurrence_pattern=pattern, attributes={"DayComponent": [1], "Interval": 6})
"""
- settings = {"parent": parent, "recurrence_type": recurrence_type}
+ recurrence = file.create_entity("IfcRecurrencePattern", recurrence_type)
- recurrence = file.createIfcRecurrencePattern(settings["recurrence_type"])
-
- if settings["parent"].is_a("IfcWorkTime"):
- if settings["parent"].RecurrencePattern and len(file.get_inverse(settings["parent"].RecurrencePattern)) == 1:
- file.remove(settings["parent"].RecurrencePattern)
- settings["parent"].RecurrencePattern = recurrence
- elif settings["parent"].is_a("IfcTaskTimeRecurring"):
- if recurrence_old := settings["parent"].Recurrence and len(file.get_inverse(recurrence_old)) == 1:
+ if parent.is_a("IfcWorkTime"):
+ if parent.RecurrencePattern and len(file.get_inverse(parent.RecurrencePattern)) == 1:
+ file.remove(parent.RecurrencePattern)
+ parent.RecurrencePattern = recurrence
+ elif parent.is_a("IfcTaskTimeRecurring"):
+ if (recurrence_old := parent.Recurrence) and len(file.get_inverse(recurrence_old)) == 1:
file.remove(recurrence_old)
- settings["parent"].Recurrence = recurrence
+ parent.Recurrence = recurrence
return recurrence
diff --git a/src/ifcopenshell-python/ifcopenshell/api/sequence/assign_sequence.py b/src/ifcopenshell-python/ifcopenshell/api/sequence/assign_sequence.py
index 664d5780ec..65491604aa 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/sequence/assign_sequence.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/sequence/assign_sequence.py
@@ -51,13 +51,10 @@ def assign_sequence(
predecessor and successor tasks in the planning profession.
:param relating_process: The previous / predecessor task.
- :type relating_process: ifcopenshell.entity_instance
:param related_process: The next / successor task.
- :type related_process: ifcopenshell.entity_instance
:param sequence_type: Choose from FINISH_START, FINISH_FINISH,
START_START, or START_FINISH.
:return: The newly created IfcRelSequence
- :rtype: ifcopenshell.entity_instance
Example:
@@ -109,24 +106,18 @@ def assign_sequence(
# to be 2000-01-05.
ifcopenshell.api.sequence.cascade_schedule(model, task=formwork)
"""
- settings = {
- "relating_process": relating_process,
- "related_process": related_process,
- "sequence_type": sequence_type,
- }
-
- for rel in settings["related_process"].IsSuccessorFrom or []:
- if rel.RelatingProcess == settings["relating_process"]:
+ for rel in related_process.IsSuccessorFrom or []:
+ if rel.RelatingProcess == relating_process:
return rel
rel = file.create_entity(
"IfcRelSequence",
**{
"GlobalId": ifcopenshell.guid.new(),
"OwnerHistory": ifcopenshell.api.owner.create_owner_history(file),
- "RelatingProcess": settings["relating_process"],
- "RelatedProcess": settings["related_process"],
- "SequenceType": settings["sequence_type"],
+ "RelatingProcess": relating_process,
+ "RelatedProcess": related_process,
+ "SequenceType": sequence_type,
}
)
- ifcopenshell.api.sequence.cascade_schedule(file, task=settings["relating_process"])
+ ifcopenshell.api.sequence.cascade_schedule(file, task=relating_process)
return rel
diff --git a/src/ifcopenshell-python/ifcopenshell/api/sequence/calculate_task_duration.py b/src/ifcopenshell-python/ifcopenshell/api/sequence/calculate_task_duration.py
index 7c3f821e7e..b8b4d857b6 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/sequence/calculate_task_duration.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/sequence/calculate_task_duration.py
@@ -20,6 +20,7 @@ import math
import ifcopenshell.api.sequence
import ifcopenshell.util.date
import ifcopenshell.util.element
+from typing import Union
def calculate_task_duration(file: ifcopenshell.file, task: ifcopenshell.entity_instance) -> None:
@@ -35,9 +36,7 @@ def calculate_task_duration(file: ifcopenshell.file, task: ifcopenshell.entity_i
then nothing happens.
:param task: The IfcTask to calculate the duration for.
- :type task: ifcopenshell.entity_instance
:return: None
- :rtype: None
Example:
@@ -82,18 +81,20 @@ def calculate_task_duration(file: ifcopenshell.file, task: ifcopenshell.entity_i
"""
usecase = Usecase()
usecase.file = file
- usecase.settings = {"task": task}
- return usecase.execute()
+ return usecase.execute(task)
class Usecase:
- def execute(self):
+ file: ifcopenshell.file
+
+ def execute(self, task: ifcopenshell.entity_instance) -> None:
+ self.task = task
self.seconds_per_workday = self.calculate_seconds_per_workday()
duration = self.calculate_max_resource_usage_duration()
if duration:
self.set_task_duration(duration)
- def calculate_seconds_per_workday(self):
+ def calculate_seconds_per_workday(self) -> float:
def get_work_schedule(task):
for rel in task.HasAssignments or []:
if rel.is_a("IfcRelAssignsToControl") and rel.RelatingControl.is_a("IfcWorkSchedule"):
@@ -102,7 +103,7 @@ class Usecase:
return get_work_schedule(rel.RelatingObject)
default_seconds_per_workday = 8 * 60 * 60
- work_schedule = get_work_schedule(self.settings["task"])
+ work_schedule = get_work_schedule(self.task)
if not work_schedule:
return default_seconds_per_workday
psets = ifcopenshell.util.element.get_psets(work_schedule)
@@ -115,9 +116,9 @@ class Usecase:
work_day_duration = ifcopenshell.util.date.ifc2datetime(psets["Pset_WorkControlCommon"]["WorkDayDuration"])
return work_day_duration.seconds
- def calculate_max_resource_usage_duration(self):
+ def calculate_max_resource_usage_duration(self) -> float:
max_duration = 0
- for rel in self.settings["task"].OperatesOn or []:
+ for rel in self.task.OperatesOn or []:
for related_object in rel.RelatedObjects:
if related_object.is_a("IfcConstructionResource"):
duration = self.calculate_duration_in_days(related_object)
@@ -125,7 +126,7 @@ class Usecase:
max_duration = duration
return max_duration
- def calculate_duration_in_days(self, resource):
+ def calculate_duration_in_days(self, resource: ifcopenshell.entity_instance) -> Union[float, None]:
def is_hourly_work(schedule_work):
return "T" in schedule_work
@@ -140,7 +141,7 @@ class Usecase:
schedule_seconds = (schedule_duration.days + partial_days) * self.seconds_per_workday
return math.ceil((schedule_seconds / self.seconds_per_workday) / schedule_usage)
- def set_task_duration(self, duration):
- if not self.settings["task"].TaskTime:
- ifcopenshell.api.sequence.add_task_time(self.file, task=self.settings["task"])
- self.settings["task"].TaskTime.ScheduleDuration = f"P{duration}D"
+ def set_task_duration(self, duration: float) -> None:
+ if not (task_time := self.task.TaskTime):
+ ifcopenshell.api.sequence.add_task_time(self.file, task=self.task)
+ task_time.ScheduleDuration = f"P{duration}D"
diff --git a/src/ifcopenshell-python/ifcopenshell/api/sequence/create_baseline.py b/src/ifcopenshell-python/ifcopenshell/api/sequence/create_baseline.py
index d0670b76e8..a6637c7a88 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/sequence/create_baseline.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/sequence/create_baseline.py
@@ -24,7 +24,7 @@ import ifcopenshell.guid
import ifcopenshell.util.element
import ifcopenshell.util.sequence
import ifcopenshell.util.system
-from typing import Optional
+from typing import Optional, Union
def create_baseline(
@@ -44,11 +44,8 @@ def create_baseline(
* Same Resource Relationships
:param work_schedule: The planned work_schedule to baseline
- :type work_schedule: ifcopenshell.entity_instance
:param name: baseline work schedule name
- :type name: str, optional
:return: The baseline work_schedule
- :rtype: ifcopenshell.entity_instance
Example:
@@ -62,23 +59,20 @@ def create_baseline(
"""
usecase = Usecase()
usecase.file = file
- usecase.settings = {"work_schedule": work_schedule, "name": name}
- return usecase.execute()
+ return usecase.execute(work_schedule, name)
class Usecase:
- def execute(self):
- result = self.create_baseline_work_schedule(self.settings["work_schedule"])
- return result
+ file: ifcopenshell.file
- def create_baseline_work_schedule(self, work_schedule):
+ def execute(self, work_schedule: ifcopenshell.entity_instance, name: Union[str, None]) -> None:
# create work schedule
if not work_schedule.PredefinedType == "PLANNED":
return
baseline_work_schedule = ifcopenshell.api.sequence.add_work_schedule(
self.file, name=work_schedule.Name, predefined_type="BASELINE"
)
- baseline_work_schedule.Name = self.settings["name"]
+ baseline_work_schedule.Name = name
self.create_baseline_reference(work_schedule, baseline_work_schedule)
for summary_task in ifcopenshell.util.sequence.get_root_tasks(work_schedule):
current, duplicate = ifcopenshell.api.sequence.duplicate_task(self.file, task=summary_task)
@@ -88,7 +82,9 @@ class Usecase:
for i, task in enumerate(current):
self.create_baseline_reference(task, duplicate[i])
- def create_baseline_reference(self, relating_object, related_object):
+ def create_baseline_reference(
+ self, relating_object: ifcopenshell.entity_instance, related_object: ifcopenshell.entity_instance
+ ) -> ifcopenshell.entity_instance:
referenced_by = None
if relating_object.Declares:
referenced_by = relating_object.Declares[0]
diff --git a/src/ifcopenshell-python/ifcopenshell/api/sequence/duplicate_task.py b/src/ifcopenshell-python/ifcopenshell/api/sequence/duplicate_task.py
index db47ccd5ec..7f974bb84e 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/sequence/duplicate_task.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/sequence/duplicate_task.py
@@ -23,9 +23,12 @@ import ifcopenshell.api.owner
import ifcopenshell.api.sequence
import ifcopenshell.util.element
import ifcopenshell.util.sequence
+from typing import Union, Any
-def duplicate_task(file: ifcopenshell.file, task: ifcopenshell.entity_instance) -> ifcopenshell.entity_instance:
+def duplicate_task(
+ file: ifcopenshell.file, task: ifcopenshell.entity_instance
+) -> Union[ifcopenshell.entity_instance, list[ifcopenshell.entity_instance]]:
"""Duplicates a task in the project
The following relationships are also duplicated:
@@ -35,9 +38,7 @@ def duplicate_task(file: ifcopenshell.file, task: ifcopenshell.entity_instance)
* The copy will have duplicated nested tasks
:param task: The task to be duplicated
- :type task: ifcopenshell.entity_instance
:return: The duplicated task or the list of duplicated tasks if the latter has children
- :rtype: ifcopenshell.entity_instance or list of ifcopenshell.entity_instance
Example:
.. code:: python
@@ -55,6 +56,9 @@ def duplicate_task(file: ifcopenshell.file, task: ifcopenshell.entity_instance)
class Usecase:
+ file: ifcopenshell.file
+ settings: dict[str, Any]
+
def execute(self):
self.tracker = {"current": [], "duplicate": []}
self.duplicate_task(self.settings["task"])
diff --git a/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_lag_time.py b/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_lag_time.py
index d3c8a4418a..d55bf0e4b5 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_lag_time.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_lag_time.py
@@ -28,11 +28,8 @@ def edit_lag_time(file: ifcopenshell.file, lag_time: ifcopenshell.entity_instanc
IfcLagTime, consult the IFC documentation.
:param lag_time: The IfcLagTime entity you want to edit
- :type lag_time: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -75,14 +72,12 @@ def edit_lag_time(file: ifcopenshell.file, lag_time: ifcopenshell.entity_instanc
# Or, let's make it 2 days instead.
ifcopenshell.api.sequence.edit_lag_time(model, lag_time=lag, attributes={"LagValue": "P2D"})
"""
- settings = {"lag_time": lag_time, "attributes": attributes}
-
- for name, value in settings["attributes"].items():
+ for name, value in attributes.items():
if name == "LagValue" and value is not None:
if isinstance(value, float):
value = file.createIfcRatioMeasure(value)
else:
value = file.createIfcDuration(ifcopenshell.util.date.datetime2ifc(value, "IfcDuration"))
- setattr(settings["lag_time"], name, value)
- for rel in [r for r in file.get_inverse(settings["lag_time"]) if r.is_a("IfcRelSequence")]:
+ setattr(lag_time, name, value)
+ for rel in [r for r in file.get_inverse(lag_time) if r.is_a("IfcRelSequence")]:
ifcopenshell.api.sequence.cascade_schedule(file, task=rel.RelatedProcess)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_recurrence_pattern.py b/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_recurrence_pattern.py
index 6b165f716a..519c5cdf25 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_recurrence_pattern.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_recurrence_pattern.py
@@ -30,11 +30,8 @@ def edit_recurrence_pattern(
IfcRecurrencePattern, consult the IFC documentation.
:param recurrence_pattern: The IfcRecurrencePattern entity you want to edit
- :type recurrence_pattern: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -55,13 +52,8 @@ def edit_recurrence_pattern(
ifcopenshell.api.sequence.edit_recurrence_pattern(model,
recurrence_pattern=pattern, attributes={"WeekdayComponent": [1, 2, 3, 4, 5]})
"""
- settings = {
- "recurrence_pattern": recurrence_pattern,
- "attributes": attributes,
- }
-
- for name, value in settings["attributes"].items():
- setattr(settings["recurrence_pattern"], name, value)
+ for name, value in attributes.items():
+ setattr(recurrence_pattern, name, value)
ifcopenshell.util.sequence.is_working_day.cache_clear()
ifcopenshell.util.sequence.is_calendar_applicable.cache_clear()
diff --git a/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_sequence.py b/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_sequence.py
index dee8a32e64..2686ec5ace 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_sequence.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_sequence.py
@@ -30,11 +30,8 @@ def edit_sequence(
IfcRelSequence, consult the IFC documentation.
:param rel_sequence: The IfcRelSequence entity you want to edit
- :type rel_sequence: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -62,9 +59,7 @@ def edit_sequence(
ifcopenshell.api.sequence.edit_sequence(model,
rel_sequence=sequence, attributes={"SequenceType": "START_START"})
"""
- settings = {"rel_sequence": rel_sequence, "attributes": attributes}
-
- for name, value in settings["attributes"].items():
- setattr(settings["rel_sequence"], name, value)
- if "SequenceType" in settings["attributes"].keys():
- ifcopenshell.api.sequence.cascade_schedule(file, task=settings["rel_sequence"].RelatedProcess)
+ for name, value in attributes.items():
+ setattr(rel_sequence, name, value)
+ if "SequenceType" in attributes.keys():
+ ifcopenshell.api.sequence.cascade_schedule(file, task=rel_sequence.RelatedProcess)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_task.py b/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_task.py
index dcd218059f..3fa1b88caf 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_task.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_task.py
@@ -26,11 +26,8 @@ def edit_task(file: ifcopenshell.file, task: ifcopenshell.entity_instance, attri
IfcTask, consult the IFC documentation.
:param task: The IfcTask entity you want to edit
- :type task: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -48,7 +45,5 @@ def edit_task(file: ifcopenshell.file, task: ifcopenshell.entity_instance, attri
# Change the identification
ifcopenshell.api.sequence.edit_task(model, task=task, attributes={"Identification": "M"})
"""
- settings = {"task": task, "attributes": attributes or {}}
-
- for name, value in settings["attributes"].items():
- setattr(settings["task"], name, value)
+ for name, value in attributes.items():
+ setattr(task, name, value)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_task_time.py b/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_task_time.py
index 6d9d3404d1..119ab82a14 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_task_time.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_task_time.py
@@ -36,11 +36,8 @@ def edit_task_time(
IfcTaskTime, consult the IFC documentation.
:param task_time: The IfcTaskTime entity you want to edit
- :type task_time: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -61,94 +58,89 @@ def edit_task_time(
"""
usecase = Usecase()
usecase.file = file
- usecase.settings = {"task_time": task_time, "attributes": attributes}
- return usecase.execute()
+ return usecase.execute(task_time, attributes)
class Usecase:
- def execute(self):
+ file: ifcopenshell.file
+
+ def execute(self, task_time: ifcopenshell.entity_instance, attributes: dict[str, Any]) -> None:
+ self.task_time = task_time
self.task = self.get_task()
self.calendar = ifcopenshell.util.sequence.derive_calendar(self.task)
# If the user specifies both an end date and a duration, the duration takes priority
- if (
- self.settings["attributes"].get("ScheduleDuration", None)
- and "ScheduleFinish" in self.settings["attributes"].keys()
- ):
- del self.settings["attributes"]["ScheduleFinish"]
+ if attributes.get("ScheduleDuration", None) and "ScheduleFinish" in attributes.keys():
+ del attributes["ScheduleFinish"]
- duration_type = self.settings["attributes"].get("DurationType", self.settings["task_time"].DurationType)
- finish = self.settings["attributes"].get("ScheduleFinish", None)
+ duration_type = attributes.get("DurationType", self.task_time.DurationType)
+ finish = attributes.get("ScheduleFinish", None)
if finish:
if isinstance(finish, str):
finish = datetime.datetime.fromisoformat(finish)
- self.settings["attributes"]["ScheduleFinish"] = datetime.datetime.combine(
+ attributes["ScheduleFinish"] = datetime.datetime.combine(
ifcopenshell.util.sequence.get_soonest_working_day(finish, duration_type, self.calendar),
datetime.time(17),
)
- start = self.settings["attributes"].get("ScheduleStart", None)
+ start = attributes.get("ScheduleStart", None)
if start:
if isinstance(start, str):
start = datetime.datetime.fromisoformat(start)
- self.settings["attributes"]["ScheduleStart"] = datetime.datetime.combine(
+ attributes["ScheduleStart"] = datetime.datetime.combine(
ifcopenshell.util.sequence.get_soonest_working_day(start, duration_type, self.calendar),
datetime.time(9),
)
- for name, value in self.settings["attributes"].items():
+ for name, value in attributes.items():
if value is not None:
if "Start" in name or "Finish" in name or name == "StatusTime":
value = ifcopenshell.util.date.datetime2ifc(value, "IfcDateTime")
elif name == "ScheduleDuration" or name == "ActualDuration" or name == "RemainingTime":
value = ifcopenshell.util.date.datetime2ifc(value, "IfcDuration")
- setattr(self.settings["task_time"], name, value)
+ setattr(self.task_time, name, value)
- if (
- "ScheduleDuration" in self.settings["attributes"].keys()
- and self.settings["task_time"].ScheduleDuration
- and self.settings["task_time"].ScheduleStart
- ):
+ if "ScheduleDuration" in attributes.keys() and task_time.ScheduleDuration and task_time.ScheduleStart:
self.calculate_finish()
- elif self.settings["attributes"].get("ScheduleStart", None) and self.settings["task_time"].ScheduleDuration:
+ elif attributes.get("ScheduleStart", None) and task_time.ScheduleDuration:
self.calculate_finish()
- elif self.settings["attributes"].get("ScheduleFinish", None) and self.settings["task_time"].ScheduleStart:
+ elif attributes.get("ScheduleFinish", None) and task_time.ScheduleStart:
self.calculate_duration()
- if self.settings["task_time"].ScheduleDuration and (
- "ScheduleStart" in self.settings["attributes"].keys()
- or "ScheduleFinish" in self.settings["attributes"].keys()
- or "ScheduleDuration" in self.settings["attributes"].keys()
+ if task_time.ScheduleDuration and (
+ "ScheduleStart" in attributes.keys()
+ or "ScheduleFinish" in attributes.keys()
+ or "ScheduleDuration" in attributes.keys()
):
ifcopenshell.api.sequence.cascade_schedule(self.file, task=self.task)
- if self.settings["task_time"].ScheduleDuration:
+ if task_time.ScheduleDuration:
self.handle_resource_calculation()
def calculate_finish(self):
finish = ifcopenshell.util.sequence.get_start_or_finish_date(
- ifcopenshell.util.date.ifc2datetime(self.settings["task_time"].ScheduleStart),
- ifcopenshell.util.date.ifc2datetime(self.settings["task_time"].ScheduleDuration),
- self.settings["task_time"].DurationType,
+ ifcopenshell.util.date.ifc2datetime(self.task_time.ScheduleStart),
+ ifcopenshell.util.date.ifc2datetime(self.task_time.ScheduleDuration),
+ self.task_time.DurationType,
self.calendar,
date_type="FINISH",
)
- self.settings["task_time"].ScheduleFinish = ifcopenshell.util.date.datetime2ifc(finish, "IfcDateTime")
+ self.task_time.ScheduleFinish = ifcopenshell.util.date.datetime2ifc(finish, "IfcDateTime")
def calculate_duration(self):
- start = ifcopenshell.util.date.ifc2datetime(self.settings["task_time"].ScheduleStart)
- finish = ifcopenshell.util.date.ifc2datetime(self.settings["task_time"].ScheduleFinish)
+ start = ifcopenshell.util.date.ifc2datetime(self.task_time.ScheduleStart)
+ finish = ifcopenshell.util.date.ifc2datetime(self.task_time.ScheduleFinish)
current_date = datetime.date(start.year, start.month, start.day)
finish_date = datetime.date(finish.year, finish.month, finish.day)
duration = datetime.timedelta(days=1)
while current_date < finish_date:
- if self.settings["task_time"].DurationType == "ELAPSEDTIME" or not self.calendar:
+ if self.task_time.DurationType == "ELAPSEDTIME" or not self.calendar:
duration += datetime.timedelta(days=1)
elif ifcopenshell.util.sequence.is_working_day(current_date, self.calendar):
duration += datetime.timedelta(days=1)
current_date += datetime.timedelta(days=1)
- self.settings["task_time"].ScheduleDuration = ifcopenshell.util.date.datetime2ifc(duration, "IfcDuration")
+ self.task_time.ScheduleDuration = ifcopenshell.util.date.datetime2ifc(duration, "IfcDuration")
def get_task(self) -> ifcopenshell.entity_instance:
- return next(e for e in self.file.get_inverse(self.settings["task_time"]) if e.is_a("IfcTask"))
+ return next(e for e in self.file.get_inverse(self.task_time) if e.is_a("IfcTask"))
def handle_resource_calculation(self):
resources = ifcopenshell.util.sequence.get_task_resources(self.task, is_deep=False)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_work_calendar.py b/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_work_calendar.py
index f82f53e534..83e56a4372 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_work_calendar.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_work_calendar.py
@@ -28,11 +28,8 @@ def edit_work_calendar(
IfcWorkCalendar, consult the IFC documentation.
:param work_calendar: The IfcWorkCalendar entity you want to edit
- :type work_calendar: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -45,7 +42,5 @@ def edit_work_calendar(
ifcopenshell.api.sequence.edit_work_calendar(model,
work_calendar=calendar, attributes={"Description": "Monday to Friday 8 hour days"})
"""
- settings = {"work_calendar": work_calendar, "attributes": attributes}
-
- for name, value in settings["attributes"].items():
- setattr(settings["work_calendar"], name, value)
+ for name, value in attributes.items():
+ setattr(work_calendar, name, value)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_work_plan.py b/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_work_plan.py
index 920e2c671e..145460e11c 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_work_plan.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_work_plan.py
@@ -29,11 +29,8 @@ def edit_work_plan(
IfcWorkPlan, consult the IFC documentation.
:param work_plan: The IfcWorkPlan entity you want to edit
- :type work_plan: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -46,12 +43,10 @@ def edit_work_plan(
ifcopenshell.api.sequence.edit_work_plan(model,
work_plan=work_plan, attributes={"Description": "Construction of phase 1"})
"""
- settings = {"work_plan": work_plan, "attributes": attributes}
-
- for name, value in settings["attributes"].items():
+ for name, value in attributes.items():
if value:
if "Date" in name or "Time" in name:
value = ifcopenshell.util.date.datetime2ifc(value, "IfcDateTime")
elif name == "Duration" or name == "TotalFloat":
value = ifcopenshell.util.date.datetime2ifc(value, "IfcDuration")
- setattr(settings["work_plan"], name, value)
+ setattr(work_plan, name, value)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_work_schedule.py b/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_work_schedule.py
index 5ed392ddff..98905b9a1f 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_work_schedule.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_work_schedule.py
@@ -29,11 +29,8 @@ def edit_work_schedule(
IfcWorkSchedule, consult the IFC documentation.
:param work_schedule: The IfcWorkSchedule entity you want to edit
- :type work_schedule: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -50,12 +47,10 @@ def edit_work_schedule(
ifcopenshell.api.sequence.edit_work_schedule(model,
work_schedule=work_schedule, attributes={"Description": "3 crane design option"})
"""
- settings = {"work_schedule": work_schedule, "attributes": attributes}
-
- for name, value in settings["attributes"].items():
+ for name, value in attributes.items():
if value:
if "Date" in name or "Time" in name:
value = ifcopenshell.util.date.datetime2ifc(value, "IfcDateTime")
elif name == "Duration" or name == "TotalFloat":
value = ifcopenshell.util.date.datetime2ifc(value, "IfcDuration")
- setattr(settings["work_schedule"], name, value)
+ setattr(work_schedule, name, value)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_work_time.py b/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_work_time.py
index 07c1f818d5..7fae8b4c18 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_work_time.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_work_time.py
@@ -31,11 +31,8 @@ def edit_work_time(
IfcWorkTime, consult the IFC documentation.
:param work_time: The IfcWorkTime entity you want to edit
- :type work_time: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -54,16 +51,14 @@ def edit_work_time(
ifcopenshell.api.sequence.edit_work_time(model,
work_time=work_time, attributes={"StartDate": "2000-01-01", "FinishDate": "2000-01-02"})
"""
- settings = {"work_time": work_time, "attributes": attributes}
-
- for name, value in settings["attributes"].items():
+ for name, value in attributes.items():
if name in ("Start", "StartDate"):
value = ifcopenshell.util.date.datetime2ifc(value, "IfcDate")
# 4 IfcWorktime Start
- settings["work_time"][4] = value
+ work_time[4] = value
elif name in ("Finish", "FinishDate"):
value = ifcopenshell.util.date.datetime2ifc(value, "IfcDate")
# 5 IfcWorktime Finish
- settings["work_time"][5] = value
+ work_time[5] = value
else:
- setattr(settings["work_time"], name, value)
+ setattr(work_time, name, value)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/sequence/recalculate_schedule.py b/src/ifcopenshell-python/ifcopenshell/api/sequence/recalculate_schedule.py
index a7fb9d01e6..14e82822e3 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/sequence/recalculate_schedule.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/sequence/recalculate_schedule.py
@@ -35,9 +35,7 @@ def recalculate_schedule(file: ifcopenshell.file, work_schedule: ifcopenshell.en
error.
:param work_schedule: The IfcWorkSchedule to perform the calculation on.
- :type work_schedule: ifcopenshell.entity_instance
:return: None
- :rtype: None
Example:
@@ -50,12 +48,14 @@ def recalculate_schedule(file: ifcopenshell.file, work_schedule: ifcopenshell.en
"""
usecase = Usecase()
usecase.file = file
- usecase.settings = {"work_schedule": work_schedule}
- return usecase.execute()
+ return usecase.execute(work_schedule)
class Usecase:
- def execute(self):
+ file: ifcopenshell.file
+
+ def execute(self, work_schedule: ifcopenshell.entity_instance) -> None:
+ self.work_schedule = work_schedule
# The method implemented is the same as shown here:
# https://www.youtube.com/watch?v=qTErIV6OqLg
self.start_dates = []
@@ -88,7 +88,6 @@ class Usecase:
if is_cyclic:
raise RecursionError("Task graph is cyclic and so critical path method cannot be performed.")
- return
self.pending_nodes = set(self.g.nodes)
while self.pending_nodes:
@@ -100,7 +99,7 @@ class Usecase:
self.update_task_times()
- def build_network_graph(self):
+ def build_network_graph(self) -> None:
self.sequence_type_map = {
None: "FS",
"START_START": "SS",
@@ -114,14 +113,14 @@ class Usecase:
self.edges = []
self.g.add_node("start", duration=0, duration_type="ELAPSEDTIME", calendar=None)
self.g.add_node("finish", duration=0, duration_type="ELAPSEDTIME", calendar=None)
- for rel in self.settings["work_schedule"].Controls:
+ for rel in self.work_schedule.Controls:
for related_object in rel.RelatedObjects:
if not related_object.is_a("IfcTask"):
continue
self.add_node(related_object)
self.g.add_edges_from(self.edges)
- def add_node(self, task):
+ def add_node(self, task: ifcopenshell.entity_instance) -> None:
if task.IsNestedBy:
for rel in task.IsNestedBy:
[self.add_node(o) for o in rel.RelatedObjects]
@@ -176,7 +175,7 @@ class Usecase:
if not successor_types:
self.edges.append((task.id(), "finish", {"lag_time": 0, "type": "FF"}))
- def update_task_times(self):
+ def update_task_times(self) -> None:
for ifc_definition_id in self.g.nodes:
if ifc_definition_id in ("start", "finish"):
continue
@@ -198,12 +197,12 @@ class Usecase:
},
)
- def offset_date(self, date, days, node):
+ def offset_date(self, date: datetime.datetime, days: int, node: dict) -> datetime.datetime:
return ifcopenshell.util.sequence.offset_date(
date, datetime.timedelta(days=days), node["duration_type"], node["calendar"]
)
- def forward_pass(self, node):
+ def forward_pass(self, node) -> bool:
successors = self.g.successors(node)
predecessors = list(self.g.predecessors(node))
data = self.g.nodes[node]
@@ -326,7 +325,7 @@ class Usecase:
return True
- def backward_pass(self, node):
+ def backward_pass(self, node) -> bool:
successors = list(self.g.successors(node))
predecessors = self.g.predecessors(node)
data = self.g.nodes[node]
@@ -496,12 +495,12 @@ class Usecase:
def calculate_free_float(
self,
- predecessor_date,
- successor_date,
- lag_time,
- predecessor_data,
- successor_data,
- ):
+ predecessor_date: datetime.datetime,
+ successor_date: datetime.datetime,
+ lag_time: int,
+ predecessor_data: dict,
+ successor_data: dict,
+ ) -> datetime.timedelta:
if not lag_time:
min_successor_date = successor_date
else:
diff --git a/src/ifcopenshell-python/ifcopenshell/api/spatial/dereference_structure.py b/src/ifcopenshell-python/ifcopenshell/api/spatial/dereference_structure.py
index bb31cd7c7d..abd66e7fa8 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/spatial/dereference_structure.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/spatial/dereference_structure.py
@@ -29,12 +29,10 @@ def dereference_structure(
"""Dereferences a list of products and space
:param products: The list of physical IfcElements that exists in the space.
- :type products: list[ifcopenshell.entity_instance]
:param relating_structure: The IfcSpatialStructureElement element, such
as IfcBuilding, IfcBuildingStorey, or IfcSpace that the element
exists in.
:return: None
- :rtype: None
Example:
@@ -68,14 +66,12 @@ def dereference_structure(
# Actually, it only goes up to storey 2.
ifcopenshell.api.spatial.dereference_structure(model, products=[column], relating_structure=storey3)
"""
- settings = {"products": products, "relating_structure": relating_structure}
-
- products = set(settings["products"])
- for rel in settings["relating_structure"].ReferencesElements:
+ products_set = set(products)
+ for rel in relating_structure.ReferencesElements:
related_elements = set(rel.RelatedElements)
- if not related_elements.intersection(products):
+ if not related_elements.intersection(products_set):
continue
- related_elements = related_elements - products
+ related_elements = related_elements - products_set
if related_elements:
rel.RelatedElements = list(related_elements)
ifcopenshell.api.owner.update_owner_history(file, **{"element": rel})
diff --git a/src/ifcopenshell-python/ifcopenshell/api/spatial/reference_structure.py b/src/ifcopenshell-python/ifcopenshell/api/spatial/reference_structure.py
index 2897219e68..41452244d1 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/spatial/reference_structure.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/spatial/reference_structure.py
@@ -46,14 +46,11 @@ def reference_structure(
spaces simultaneously.
:param products: The list of physical IfcElements that exists in the space.
- :type products: list[ifcopenshell.entity_instance]
:param relating_structure: The IfcSpatialStructureElement element, such
as IfcBuilding, IfcBuildingStorey, or IfcSpace that the element
exists in.
- :type relating_structure: ifcopenshell.entity_instance
:return: The IfcRelReferencedInSpatialStructure relationship instance
or `None` if `products` was an empty list.
- :rtype: Union[ifcopenshell.entity_instance, None]
Example:
@@ -85,19 +82,16 @@ def reference_structure(
model, products=[column], relating_structure=[storey2, storey3]
)
"""
- settings = {
- "products": products,
- "relating_structure": relating_structure,
- }
- structure = settings["relating_structure"]
- products = set(settings["products"])
+ structure = relating_structure
+ products_set = set(products)
- if not products:
+ if not products_set:
return
referenced = ifcopenshell.util.element.get_structure_referenced_elements(structure)
- products_to_assign = products - referenced
+ products_to_assign = products_set - referenced
+ rel: Union[ifcopenshell.entity_instance, None]
rel = next(iter(structure.ReferencesElements), None)
if not products_to_assign:
diff --git a/src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_analysis_model.py b/src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_analysis_model.py
index 4b7d94a4a2..65c03eb238 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_analysis_model.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_analysis_model.py
@@ -28,14 +28,8 @@ def edit_structural_analysis_model(
IfcStructuralAnalysisModel, consult the IFC documentation.
:param structural_analysis_model: The IfcStructuralAnalysisModel entity you want to edit
- :type structural_analysis_model: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
"""
- settings = {"structural_analysis_model": structural_analysis_model, "attributes": attributes or {}}
-
- for name, value in settings["attributes"].items():
- setattr(settings["structural_analysis_model"], name, value)
- return settings["structural_analysis_model"]
+ for name, value in attributes.items():
+ setattr(structural_analysis_model, name, value)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_boundary_condition.py b/src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_boundary_condition.py
index 54963415df..3d33e4e8ad 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_boundary_condition.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_boundary_condition.py
@@ -28,19 +28,14 @@ def edit_structural_boundary_condition(
IfcBoundaryCondition, consult the IFC documentation.
:param condition: The IfcBoundaryCondition entity you want to edit
- :type condition: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
"""
- settings = {"condition": condition, "attributes": attributes}
-
- for name, data in settings["attributes"].items():
+ for name, data in attributes.items():
if data["type"] == "string" or data["type"] == "null":
value = data["value"]
elif data["type"] == "IfcBoolean":
value = file.createIfcBoolean(data["value"])
else:
value = file.create_entity(data["type"], data["value"])
- setattr(settings["condition"], name, value)
+ setattr(condition, name, value)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_item_axis.py b/src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_item_axis.py
index 8b90457a47..1b7105d95d 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_item_axis.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_item_axis.py
@@ -16,25 +16,21 @@
# You should have received a copy of the GNU Lesser General Public License
# along with IfcOpenShell. If not, see .
import ifcopenshell
+from ifcopenshell.util.shape_builder import VectorType, ifc_safe_vector_type
def edit_structural_item_axis(
file: ifcopenshell.file,
structural_item: ifcopenshell.entity_instance,
- axis: tuple[float, float, float] = (0.0, 0.0, 1.0),
+ axis: VectorType = (0.0, 0.0, 1.0),
) -> None:
"""Edits the coordinate system of a structural connection
:param structural_item: The IfcStructuralItem you want to modify.
- :type structural_item: ifcopenshell.entity_instance
:param axis: The unit Z axis vector defined as a list of 3 floats.
Defaults to (0., 0., 1.).
- :type axis: tuple[float, float, float]
:return: None
- :rtype: None
"""
- settings = {"structural_item": structural_item, "axis": axis}
-
- if len(file.get_inverse(settings["structural_item"].Axis)) == 1:
- file.remove(settings["structural_item"].Axis)
- settings["structural_item"].Axis = file.createIfcDirection(settings["axis"])
+ if len(file.get_inverse(axis_dir := structural_item.Axis)) == 1:
+ file.remove(axis_dir)
+ structural_item.Axis = file.create_entity("IfcDirection", ifc_safe_vector_type(axis))
diff --git a/src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_load.py b/src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_load.py
index 20298d1c0f..faa218a7a3 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_load.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_load.py
@@ -28,13 +28,8 @@ def edit_structural_load(
IfcStructuralLoad, consult the IFC documentation.
:param structural_load: The IfcStructuralLoad entity you want to edit
- :type structural_load: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
"""
- settings = {"structural_load": structural_load, "attributes": attributes or {}}
-
- for name, value in settings["attributes"].items():
- setattr(settings["structural_load"], name, value)
+ for name, value in attributes.items():
+ setattr(structural_load, name, value)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_load_case.py b/src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_load_case.py
index 59231fb9e4..02948c637d 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_load_case.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_load_case.py
@@ -28,13 +28,8 @@ def edit_structural_load_case(
IfcStructuralLoadCase, consult the IFC documentation.
:param load_case: The IfcStructuralLoadCase entity you want to edit
- :type load_case: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
"""
- settings = {"load_case": load_case, "attributes": attributes or {}}
-
- for name, value in settings["attributes"].items():
- setattr(settings["load_case"], name, value)
+ for name, value in attributes.items():
+ setattr(load_case, name, value)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/style/add_surface_style.py b/src/ifcopenshell-python/ifcopenshell/api/style/add_surface_style.py
index 408f8e7906..64d38cfd2f 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/style/add_surface_style.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/style/add_surface_style.py
@@ -82,17 +82,13 @@ def add_surface_style(
:param style: The IfcSurfaceStyle you want to add to presentation item
to. See ifcopenshell.api.style.add_style.
- :type style: ifcopenshell.entity_instance
:param ifc_class: Choose from IfcSurfaceStyleShading,
IfcSurfaceStyleRendering, IfcSurfaceStyleWithTextures,
IfcSurfaceStyleLighting, IfcSurfaceStyleReflectance, or
IfcExternallyDefinedSurfaceStyle.
- :type ifc_class: str
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict, optional
:return: The newly created presentation item based on the provided
ifc_class.
- :rtype: ifcopenshell.entity_instance
Example:
diff --git a/src/ifcopenshell-python/ifcopenshell/api/style/assign_material_style.py b/src/ifcopenshell-python/ifcopenshell/api/style/assign_material_style.py
index 3ecc91177f..f870a3006e 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/style/assign_material_style.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/style/assign_material_style.py
@@ -19,6 +19,7 @@
import ifcopenshell
import ifcopenshell.api.style
import ifcopenshell.util.element
+from typing import Any
def assign_material_style(
@@ -115,6 +116,9 @@ def assign_material_style(
class Usecase:
+ file: ifcopenshell.file
+ settings: dict[str, Any]
+
def execute(self):
self.style = self.settings["style"]
if self.file.schema == "IFC2X3" or self.settings["should_use_presentation_style_assignment"]:
diff --git a/src/ifcopenshell-python/ifcopenshell/api/style/edit_presentation_style.py b/src/ifcopenshell-python/ifcopenshell/api/style/edit_presentation_style.py
index d1a42e5d9e..7a39629528 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/style/edit_presentation_style.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/style/edit_presentation_style.py
@@ -28,11 +28,8 @@ def edit_presentation_style(
IfcPresentationStyle, consult the IFC documentation.
:param style: The IfcPresentationStyle entity you want to edit
- :type style: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -44,7 +41,5 @@ def edit_presentation_style(
# Change the name of the style to "Foo"
ifcopenshell.api.style.edit_presentation_style(model, style=style, attributes={"Name": "Foo"})
"""
- settings = {"style": style, "attributes": attributes or {}}
-
- for name, value in settings["attributes"].items():
- setattr(settings["style"], name, value)
+ for name, value in attributes.items():
+ setattr(style, name, value)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/style/edit_surface_style.py b/src/ifcopenshell-python/ifcopenshell/api/style/edit_surface_style.py
index c5be1d757f..40f4fcedf4 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/style/edit_surface_style.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/style/edit_surface_style.py
@@ -16,7 +16,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with IfcOpenShell. If not, see .
import ifcopenshell
-from typing import Any
+from typing import Any, Union
def edit_surface_style(
@@ -36,11 +36,8 @@ def edit_surface_style(
example below.
:param style: The IfcPresentationStyle entity you want to edit
- :type style: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -74,14 +71,18 @@ def edit_surface_style(
"""
usecase = Usecase()
usecase.file = file
- usecase.settings = {"style": style, "attributes": attributes or {}}
- return usecase.execute()
+ return usecase.execute(style, attributes)
class Usecase:
- def execute(self):
+ file: ifcopenshell.file
+ settings: dict[str, Any]
+
+ def execute(self, style: ifcopenshell.entity_instance, attributes: dict[str, Any]) -> None:
+ self.style = style
+
attributes = {}
- for attribute in self.settings["style"].wrapped_data.declaration().as_entity().all_attributes():
+ for attribute in style.wrapped_data.declaration().as_entity().all_attributes():
attribute_type = attribute.type_of_attribute()
if attribute_type.as_aggregation_type() is None:
attribute_type = attribute_type.declared_type().name()
@@ -90,7 +91,7 @@ class Usecase:
attribute_type = attribute_type.type_of_element()
attributes[attribute.name()] = attribute_type
- for key, value in self.settings["attributes"].items():
+ for key, value in attributes.items():
attribute_class = attributes.get(key)
if attribute_class == "IfcColourRgb":
self.edit_colour_rgb(key, value)
@@ -101,39 +102,37 @@ class Usecase:
else:
setattr(self.settings["style"], key, value)
- def edit_colour_rgb(self, name, value: dict):
- if (attribute := getattr(self.settings["style"], name)) is None:
+ def edit_colour_rgb(self, name: str, value: dict[str, Any]):
+ if (attribute := getattr(self.style, name)) is None:
attribute = self.file.createIfcColourRgb()
- setattr(self.settings["style"], name, attribute)
+ setattr(self.style, name, attribute)
attribute.Name = value.get("Name", None)
attribute.Red = value["Red"]
attribute.Green = value["Green"]
attribute.Blue = value["Blue"]
- def edit_colour_or_factor(self, name, value):
+ def edit_colour_or_factor(self, name: str, value: Union[dict[str, Any], ifcopenshell.entity_instance, None]):
if isinstance(value, dict):
- attribute = getattr(self.settings["style"], name)
+ attribute = getattr(self.style, name)
if not attribute or not attribute.is_a("IfcColourRgb"):
colour = self.file.createIfcColourRgb(None, 0, 0, 0)
- setattr(self.settings["style"], name, colour)
- attribute = getattr(self.settings["style"], name)
+ setattr(self.style, name, colour)
+ attribute = getattr(self.style, name)
attribute[1] = value["Red"]
attribute[2] = value["Green"]
attribute[3] = value["Blue"]
else: # assume it's float value for IfcNormalisedRatioMeasure or None
- existing_value = getattr(self.settings["style"], name)
+ existing_value = getattr(self.style, name)
if existing_value and existing_value.id():
self.file.remove(existing_value)
if value is not None:
- value = self.file.createIfcNormalisedRatioMeasure(value)
- setattr(self.settings["style"], name, value)
+ value = self.file.create_entity("IfcNormalisedRatioMeasure", value)
+ setattr(self.style, name, value)
- def edit_specular_highlight(self, value):
+ def edit_specular_highlight(self, value: Union[dict[str, Any], None]) -> None:
if value is None:
- self.settings["style"].SpecularHighlight = None
+ self.style.SpecularHighlight = None
elif value.get("IfcSpecularExponent", None):
- self.settings["style"].SpecularHighlight = self.file.createIfcSpecularExponent(value["IfcSpecularExponent"])
+ self.style.SpecularHighlight = self.file.createIfcSpecularExponent(value["IfcSpecularExponent"])
elif value.get("IfcSpecularRoughness", None):
- self.settings["style"].SpecularHighlight = self.file.createIfcSpecularRoughness(
- value["IfcSpecularRoughness"]
- )
+ self.style.SpecularHighlight = self.file.createIfcSpecularRoughness(value["IfcSpecularRoughness"])
diff --git a/src/ifcopenshell-python/ifcopenshell/api/style/remove_style.py b/src/ifcopenshell-python/ifcopenshell/api/style/remove_style.py
index 3ee4cbf6d5..c72cca657e 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/style/remove_style.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/style/remove_style.py
@@ -41,7 +41,6 @@ def remove_style(file: ifcopenshell.file, style: ifcopenshell.entity_instance) -
"""
usecase = Usecase()
usecase.file = file
- usecase.settings = {"style": style}
return usecase.execute(style)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/style/remove_surface_style.py b/src/ifcopenshell-python/ifcopenshell/api/style/remove_surface_style.py
index bad29c878f..19bb9e1b79 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/style/remove_surface_style.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/style/remove_surface_style.py
@@ -24,9 +24,7 @@ def remove_surface_style(file: ifcopenshell.file, style: ifcopenshell.entity_ins
"""Removes a presentation item from a presentation style
:param style: The IfcPresentationItem to remove.
- :type style: ifcopenshell.entity_instance
:return: None
- :rtype: None
Example:
diff --git a/src/ifcopenshell-python/ifcopenshell/api/style/unassign_representation_styles.py b/src/ifcopenshell-python/ifcopenshell/api/style/unassign_representation_styles.py
index f56fad763c..4141adbacc 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/style/unassign_representation_styles.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/style/unassign_representation_styles.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 ifcopenshell
+from typing import Any
def unassign_representation_styles(
@@ -63,6 +64,9 @@ def unassign_representation_styles(
class Usecase:
+ file: ifcopenshell.file
+ settings: dict[str, Any]
+
def execute(self):
if not self.settings["styles"]:
return []
diff --git a/src/ifcopenshell-python/ifcopenshell/api/system/connect_port.py b/src/ifcopenshell-python/ifcopenshell/api/system/connect_port.py
index 9a1bc76f43..b0b39cfd2b 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/system/connect_port.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/system/connect_port.py
@@ -20,7 +20,7 @@ import ifcopenshell
import ifcopenshell.api.owner
import ifcopenshell.guid
import ifcopenshell.util.element
-from typing import Optional
+from typing import Optional, Any
def connect_port(
@@ -110,6 +110,9 @@ def connect_port(
class Usecase:
+ file: ifcopenshell.file
+ settings: dict[str, Any]
+
def execute(self):
# Note: there are a number of ambiguities with port connectivity. We
# assume system topology is represented by a directed graph. In other
diff --git a/src/ifcopenshell-python/ifcopenshell/api/system/edit_system.py b/src/ifcopenshell-python/ifcopenshell/api/system/edit_system.py
index 00311b7ac0..c90894ec7f 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/system/edit_system.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/system/edit_system.py
@@ -26,11 +26,8 @@ def edit_system(file: ifcopenshell.file, system: ifcopenshell.entity_instance, a
IfcSystem, consult the IFC documentation.
:param system: The IfcSystem entity you want to edit
- :type system: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -42,8 +39,5 @@ def edit_system(file: ifcopenshell.file, system: ifcopenshell.entity_instance, a
# Change the name of the system to "HW" for Hot Water
ifcopenshell.api.system.edit_system(model, system=system, attributes={"Name": "HW"})
"""
-
- settings = {"system": system, "attributes": attributes or {}}
-
- for name, value in settings["attributes"].items():
- setattr(settings["system"], name, value)
+ for name, value in attributes.items():
+ setattr(system, name, value)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/system/unassign_port.py b/src/ifcopenshell-python/ifcopenshell/api/system/unassign_port.py
index 1bf459920f..b5b69e276c 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/system/unassign_port.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/system/unassign_port.py
@@ -19,6 +19,7 @@
import ifcopenshell
import ifcopenshell.api.owner
import ifcopenshell.util.element
+from typing import Any
def unassign_port(
@@ -62,6 +63,9 @@ def unassign_port(
class Usecase:
+ file: ifcopenshell.file
+ settings: dict[str, Any]
+
def execute(self):
if self.file.schema == "IFC2X3":
return self.execute_ifc2x3()
diff --git a/src/ifcopenshell-python/ifcopenshell/api/type/assign_type.py b/src/ifcopenshell-python/ifcopenshell/api/type/assign_type.py
index 2a20f57f2f..f4bfae022e 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/type/assign_type.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/type/assign_type.py
@@ -22,7 +22,7 @@ import ifcopenshell.api.owner
import ifcopenshell.api.material
import ifcopenshell.guid
import ifcopenshell.util.element
-from typing import Union, Iterable
+from typing import Union, Iterable, Any
def assign_type(
@@ -186,6 +186,9 @@ def assign_type(
class Usecase:
+ file: ifcopenshell.file
+ settings: dict[str, Any]
+
def execute(self):
if not self.settings["related_objects"]:
return
diff --git a/src/ifcopenshell-python/ifcopenshell/api/unit/add_derived_unit.py b/src/ifcopenshell-python/ifcopenshell/api/unit/add_derived_unit.py
index 8a68e5727f..0fba187c75 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/unit/add_derived_unit.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/unit/add_derived_unit.py
@@ -46,11 +46,8 @@ def add_derived_unit(
:type unit_type: str
:param userdefinedtype: The user defined type in case of choosing USERDEFINED, or None for no
user defined type.
- :type userdefinedtype: str or None
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: The newly created IfcDerivedUnit
- :rtype: ifcopenshell.entity_instance
Example:
@@ -69,15 +66,13 @@ def add_derived_unit(
#12=IfcDerivedUnit((#10,#11),.LINEARVELOCITY.,$)
"""
- settings = {"unit_type": unit_type, "attributes": attributes}
-
derive_unit_elements = []
- for named_unit in settings["attributes"]:
+ for named_unit in attributes:
derive_unit_elements.append(
- file.create_entity("IfcDerivedUnitElement", Unit=named_unit, Exponent=settings["attributes"][named_unit])
+ file.create_entity("IfcDerivedUnitElement", Unit=named_unit, Exponent=attributes[named_unit])
)
return file.create_entity(
- "IfcDerivedUnit", Elements=derive_unit_elements, UnitType=settings["unit_type"], UserDefinedType=userdefinedtype
+ "IfcDerivedUnit", Elements=derive_unit_elements, UnitType=unit_type, UserDefinedType=userdefinedtype
)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/unit/assign_unit.py b/src/ifcopenshell-python/ifcopenshell/api/unit/assign_unit.py
index 4e2dc3f848..d57acbd435 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/unit/assign_unit.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/unit/assign_unit.py
@@ -18,7 +18,7 @@
import ifcopenshell
import ifcopenshell.util.unit
-from typing import Optional
+from typing import Optional, Any
def assign_unit(
@@ -75,6 +75,9 @@ def assign_unit(
class Usecase:
+ file: ifcopenshell.file
+ settings: dict[str, Any]
+
def execute(self):
# We're going to refactor this to split unit creation and assignment
if self.settings["units"]:
diff --git a/src/ifcopenshell-python/ifcopenshell/api/unit/edit_derived_unit.py b/src/ifcopenshell-python/ifcopenshell/api/unit/edit_derived_unit.py
index a8b3316dbd..5bc9bbd316 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/unit/edit_derived_unit.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/unit/edit_derived_unit.py
@@ -26,13 +26,8 @@ def edit_derived_unit(file: ifcopenshell.file, unit: ifcopenshell.entity_instanc
IfcDerivedUnit, consult the IFC documentation.
:param unit: The IfcDerivedUnit entity you want to edit
- :type unit: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
"""
- settings = {"unit": unit, "attributes": attributes or {}}
-
- for name, value in settings["attributes"].items():
- setattr(settings["unit"], name, value)
+ for name, value in attributes.items():
+ setattr(unit, name, value)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/unit/edit_monetary_unit.py b/src/ifcopenshell-python/ifcopenshell/api/unit/edit_monetary_unit.py
index 4fdfe6ec29..bccc61afc0 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/unit/edit_monetary_unit.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/unit/edit_monetary_unit.py
@@ -26,11 +26,8 @@ def edit_monetary_unit(file: ifcopenshell.file, unit: ifcopenshell.entity_instan
IfcMonetaryUnit, consult the IFC documentation.
:param unit: The IfcMonetaryUnit entity you want to edit
- :type unit: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -43,7 +40,5 @@ def edit_monetary_unit(file: ifcopenshell.file, unit: ifcopenshell.entity_instan
# Ah who are we kidding
ifcopenshell.api.unit.edit_monetary_unit(model, unit=zwl, attributes={"Currency": "USD"})
"""
- settings = {"unit": unit, "attributes": attributes or {}}
-
- for name, value in settings["attributes"].items():
- setattr(settings["unit"], name, value)
+ for name, value in attributes.items():
+ setattr(unit, name, value)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/unit/edit_named_unit.py b/src/ifcopenshell-python/ifcopenshell/api/unit/edit_named_unit.py
index e439e2c476..ccd0e96d54 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/unit/edit_named_unit.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/unit/edit_named_unit.py
@@ -29,11 +29,8 @@ def edit_named_unit(file: ifcopenshell.file, unit: ifcopenshell.entity_instance,
IfcNamedUnit, consult the IFC documentation.
:param unit: The IfcNamedUnit entity you want to edit
- :type unit: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
- :type attributes: dict
:return: None
- :rtype: None
Example:
@@ -45,15 +42,13 @@ def edit_named_unit(file: ifcopenshell.file, unit: ifcopenshell.entity_instance,
# Uh, crates? Boxes? Whatever.
ifcopenshell.api.unit.edit_named_unit(model, unit=unit, attibutes={"Name": "CRATES"})
"""
- settings = {"unit": unit, "attributes": attributes or {}}
-
- for name, value in settings["attributes"].items():
+ for name, value in attributes.items():
if name == "Dimensions":
- dimensions = settings["unit"].Dimensions
+ dimensions = unit.Dimensions
if len(file.get_inverse(dimensions)) > 1:
- settings["unit"].Dimensions = file.createIfcDimensionalExponents(*value)
+ unit.Dimensions = file.createIfcDimensionalExponents(*value)
else:
for i, exponent in enumerate(value):
dimensions[i] = exponent
continue
- setattr(settings["unit"], name, value)
+ setattr(unit, name, value)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/unit/unassign_unit.py b/src/ifcopenshell-python/ifcopenshell/api/unit/unassign_unit.py
index 17eee6d4be..8e0335b77e 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/unit/unassign_unit.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/unit/unassign_unit.py
@@ -23,9 +23,7 @@ def unassign_unit(file: ifcopenshell.file, units: Optional[list[ifcopenshell.ent
"""Unassigns units as default units for the project
:param units: A list of units to assign as project defaults.
- :type units: list[ifcopenshell.entity_instance],optional
:return: None
- :rtype: None
Example:
@@ -44,15 +42,12 @@ def unassign_unit(file: ifcopenshell.file, units: Optional[list[ifcopenshell.ent
# Actually, we don't need areas.
ifcopenshell.api.unit.unassign_unit(model, units=[area])
"""
- settings = {"units": units}
-
- unit_assignment = file.by_type("IfcUnitAssignment")
- if not unit_assignment:
+ unit_assignments = file.by_type("IfcUnitAssignment")
+ if not unit_assignments:
return
- unit_assignment = unit_assignment[0]
- units = set(unit_assignment.Units or [])
- units = units - set(settings["units"])
- if units:
- unit_assignment.Units = list(units)
- return unit_assignment
+ unit_assignment = unit_assignments[0]
+ units_set = set(unit_assignment.Units or [])
+ units_set = units_set - set(units or [])
+ if units_set:
+ unit_assignment.Units = list(units_set)
file.remove(unit_assignment)
diff --git a/src/ifcopenshell-python/ifcopenshell/file.py b/src/ifcopenshell-python/ifcopenshell/file.py
index 04c6c2ce50..d3c94b616d 100644
--- a/src/ifcopenshell-python/ifcopenshell/file.py
+++ b/src/ifcopenshell-python/ifcopenshell/file.py
@@ -24,6 +24,7 @@ import zipfile
import functools
import ifcopenshell
from pathlib import Path
+from typing import Any
from typing import Callable
from typing import Generator
from typing import Optional
diff --git a/src/ifcopenshell-python/ifcopenshell/util/placement.py b/src/ifcopenshell-python/ifcopenshell/util/placement.py
index d6caa1b657..5f8ad154b6 100644
--- a/src/ifcopenshell-python/ifcopenshell/util/placement.py
+++ b/src/ifcopenshell-python/ifcopenshell/util/placement.py
@@ -137,9 +137,7 @@ def get_cartesiantransformationoperator3d(inst: ifcopenshell.entity_instance) ->
``get_mappeditem_transformation`` instead.
:param item: The IfcCartesianTransformationOperator entity
- :type item: ifcopenshell.entity_instance
:return: A 4x4 numpy transformation matrix
- :rtype: MatrixType
"""
origin = np.array(inst.LocalOrigin.Coordinates)
axis1 = np.array((1.0, 0.0, 0.0))