From 291d7d84415250a37df497bdf25b829627d9f62f Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Sun, 26 Jul 2026 18:03:09 +1000 Subject: [PATCH] black . --- nix/build-all.py | 15 +-- src/bonsai/bonsai/bim/module/cost/data.py | 7 +- .../bonsai/bim/module/drawing/operator.py | 4 +- src/bonsai/bonsai/core/drawing.py | 4 +- .../scripts/standalone_blender_import.py | 1 + .../model/test_mep_distribution_fit_smoke.py | 8 +- .../module/model/test_mep_segment_edition.py | 5 +- .../test_preview_cancel_ops_forward_compat.py | 3 +- src/bonsaiviewer-autodesk/packaging/build.py | 10 +- src/ifc5d/ifc5d/csv2ifc.py | 8 +- src/ifc5d/ifc5d/ifc2json.py | 7 +- .../ifcopenshell/__init__.py | 1 + .../ifcopenshell/api/alignment/create.py | 4 +- .../alignment/distance_along_from_station.py | 5 +- .../ifcopenshell/express/bootstrap.py | 21 ++- .../ifcopenshell/express/cat.py | 11 +- .../ifcopenshell/express/codegen.py | 2 +- .../ifcopenshell/express/header.py | 34 +++-- .../ifcopenshell/express/implementation.py | 49 ++++--- .../ifcopenshell/express/nodes.py | 100 ++++++++------ .../ifcopenshell/express/rule_compiler.py | 4 +- .../ifcopenshell/express/schema.py | 18 ++- .../ifcopenshell/express/schema_class.py | 126 ++++++++++-------- .../ifcopenshell/express/templates.py | 62 +++------ .../ifcopenshell/geom/app.py | 12 +- .../ifcopenshell/geom/main.py | 15 ++- .../ifcopenshell/ifcopenshell_wrapper.pyi | 19 +-- src/ifcopenshell-python/ifcopenshell/sql.py | 2 +- .../ifcopenshell/util/cost.py | 6 +- .../ifcopenshell/util/selector.py | 18 +-- .../alignment/test_add_segment_to_layout.py | 1 - .../test_add_stationing_to_alignment.py | 1 - .../alignment/test_add_vertical_alignment.py | 1 - .../test/api/alignment/test_create.py | 1 - .../alignment/test_create_as_offset_curve.py | 1 - .../api/alignment/test_create_as_polyline.py | 1 - .../api/alignment/test_create_by_pi_method.py | 1 - .../alignment/test_create_layout_segment.py | 1 - .../api/alignment/test_create_no_geometry.py | 1 - .../test_distance_along_from_station.py | 1 - .../test/api/alignment/test_get_alignment.py | 1 - .../api/alignment/test_get_basis_curve.py | 1 - .../test/api/alignment/test_get_curve.py | 1 - .../api/alignment/test_get_layout_curve.py | 1 - .../alignment/test_has_zero_length_segment.py | 1 - .../test_horizontal_layout_by_pi_method.py | 1 - .../test_map_alignment_cant_segment.py | 1 + .../test_map_alignment_horizontal_segment.py | 1 + .../test_map_alignment_vertical_segment.py | 1 + .../test/api/alignment/test_name_segments.py | 1 - .../test/api/alignment/test_referent_names.py | 1 - ...st_update_curve_segment_transition_code.py | 1 + .../test_update_fallback_position.py | 1 - .../test_vertical_layout_by_pi_method.py | 1 - .../test/api/cogo/test_add_survey_point.py | 1 - .../test/api/cogo/test_assign_survey_point.py | 1 - .../test/api/cogo/test_edit_survey_point.py | 1 - .../test/test_entity_instance.py | 15 ++- src/ifcopenshell-python/test/test_file.py | 11 +- src/ifcopenshell-python/test/test_parse.py | 1 + src/ifcopenshell-python/test/test_rules.py | 3 +- .../test/test_shape_stats.py | 9 +- .../test/util/test_alignment.py | 1 - .../ifcpatch/recipes/ExtractElements.py | 2 +- .../test/test_DowngradeIndexedPolyCurve.py | 12 +- src/ifctester/ifctester/facet.py | 4 +- src/ifcviewer-web/make_sample.py | 49 ++++--- src/wrappergen/clang_frontend.py | 26 +++- src/wrappergen/conventions.py | 6 +- src/wrappergen/emit.py | 56 +++++--- src/wrappergen/generate.py | 6 +- .../generated/ifcopenshell_experimental.py | 45 ++++++- 72 files changed, 477 insertions(+), 377 deletions(-) diff --git a/nix/build-all.py b/nix/build-all.py index 9f9fa458e8..34f1a92147 100644 --- a/nix/build-all.py +++ b/nix/build-all.py @@ -814,17 +814,12 @@ def install_qt6() -> str: # the supported flow is a pre-installed Qt6 advertised via QT_DIR. preset_qt_dir = os.environ.get("QT_DIR", "").strip() if preset_qt_dir: - preset_qt_config = ( - Path(preset_qt_dir) / "lib" / "cmake" / "Qt6" / "Qt6Config.cmake" - ) + preset_qt_config = Path(preset_qt_dir) / "lib" / "cmake" / "Qt6" / "Qt6Config.cmake" if preset_qt_config.exists(): - logger.info( - f"Using pre-set QT_DIR={preset_qt_dir}, skipping aqt install" - ) + logger.info(f"Using pre-set QT_DIR={preset_qt_dir}, skipping aqt install") return preset_qt_dir logger.warning( - f"QT_DIR={preset_qt_dir} is set but {preset_qt_config} not found; " - f"falling through to aqtinstall" + f"QT_DIR={preset_qt_dir} is set but {preset_qt_config} not found; " f"falling through to aqtinstall" ) host, qt_arch, install_suffix = get_qt6_aqt_config() @@ -1463,8 +1458,8 @@ elif "occ" in targets: cmake_args.extend(["-DOCC_INCLUDE_DIR=" + occ_include_dir, "-DOCC_LIBRARY_DIR=" + occ_library_dir]) if "manifold" in targets: - cmake_args_prefix_path.append(f"{DEPS_DIR}/install/manifold-{MANIFOLD_VERSION}") - cmake_args.append("-DWITH_MANIFOLD=On") + cmake_args_prefix_path.append(f"{DEPS_DIR}/install/manifold-{MANIFOLD_VERSION}") + cmake_args.append("-DWITH_MANIFOLD=On") if "OpenCOLLADA" in targets: # pcre is a dependency of OpenCOLLADA, but since we `find_package`, diff --git a/src/bonsai/bonsai/bim/module/cost/data.py b/src/bonsai/bonsai/bim/module/cost/data.py index 14967d032d..8ff305d3cf 100644 --- a/src/bonsai/bonsai/bim/module/cost/data.py +++ b/src/bonsai/bonsai/bim/module/cost/data.py @@ -206,12 +206,7 @@ class CostSchedulesData: data["UnitSymbol"] = ifcopenshell.util.unit.get_unit_symbol(unit) if quantity.is_a("IfcPhysicalSimpleQuantity"): measure_class = ( - quantity.declaration - .as_entity() - .attribute_by_index(3) - .type_of_attribute() - .declared_type() - .name() + quantity.declaration.as_entity().attribute_by_index(3).type_of_attribute().declared_type().name() ) if "Count" in measure_class: data["UnitSymbol"] = "U" diff --git a/src/bonsai/bonsai/bim/module/drawing/operator.py b/src/bonsai/bonsai/bim/module/drawing/operator.py index 5987b430a2..a032614aa6 100644 --- a/src/bonsai/bonsai/bim/module/drawing/operator.py +++ b/src/bonsai/bonsai/bim/module/drawing/operator.py @@ -1057,7 +1057,9 @@ class CreateDrawing(bpy.types.Operator): # Specifically for PLAN_VIEW and REFLECTED_PLAN_VIEW, any Plan context is also prioritised. contexts = self.get_linework_contexts(ifc, target_view) self.serialize_contexts_elements(ifc, tree, contexts, "body", drawing_elements, target_view, link_matrix) - self.serialize_contexts_elements(ifc, tree, contexts, "annotation", drawing_elements, target_view, link_matrix) + self.serialize_contexts_elements( + ifc, tree, contexts, "annotation", drawing_elements, target_view, link_matrix + ) if tool.Ifc.get() == ifc and self.camera_element not in drawing_elements: with profile("Camera element"): diff --git a/src/bonsai/bonsai/core/drawing.py b/src/bonsai/bonsai/core/drawing.py index 64df0026bd..c3d6e9c8ef 100644 --- a/src/bonsai/bonsai/core/drawing.py +++ b/src/bonsai/bonsai/core/drawing.py @@ -308,9 +308,9 @@ def add_drawing( group = ifc.run("group.add_group") ifc.run("group.edit_group", group=group, attributes={"Name": drawing_name, "ObjectType": "DRAWING"}) ifc.run("group.assign_group", group=group, products=[element]) - + ifc.run("group.assign_group", group=drawings_parent_group, products=[group]) - + collector.assign(camera) pset = ifc.run("pset.add_pset", product=element, name="EPset_Drawing") if drawing.get_unit_system() == "METRIC": diff --git a/src/bonsai/scripts/standalone_blender_import.py b/src/bonsai/scripts/standalone_blender_import.py index 088722c8a2..583e6d7366 100644 --- a/src/bonsai/scripts/standalone_blender_import.py +++ b/src/bonsai/scripts/standalone_blender_import.py @@ -109,4 +109,5 @@ class BlenderImporter: print("Done creating geometry") return results + BlenderImporter().execute() diff --git a/src/bonsai/test/bim/module/model/test_mep_distribution_fit_smoke.py b/src/bonsai/test/bim/module/model/test_mep_distribution_fit_smoke.py index 55d325d76c..327e71e34a 100644 --- a/src/bonsai/test/bim/module/model/test_mep_distribution_fit_smoke.py +++ b/src/bonsai/test/bim/module/model/test_mep_distribution_fit_smoke.py @@ -146,7 +146,9 @@ def test_fit_flow_segments_with_single_segment_dispatches_obstruction(): mep.tool.Model, "get_flow_segment_profile", return_value=segment_profile ), patch.object(mep.MEPAddObstruction, "_execute", return_value=None) as obstruction, patch.object( mep.MEPAddBend, "_execute", return_value=None - ) as bend, patch.object(mep.MEPAddTransition, "_execute", return_value=None) as transition: + ) as bend, patch.object( + mep.MEPAddTransition, "_execute", return_value=None + ) as transition: mep.FitFlowSegments._execute(op, context=context) assert obstruction.call_count == 1 @@ -178,7 +180,9 @@ def test_fit_flow_segments_refuses_mixed_pipe_and_duct(): mep.tool.Model, "get_flow_segment_profile", return_value=profile ), patch.object(mep.MEPAddObstruction, "_execute", return_value=None) as obstruction, patch.object( mep.MEPAddBend, "_execute", return_value=None - ) as bend, patch.object(mep.MEPAddTransition, "_execute", return_value=None) as transition: + ) as bend, patch.object( + mep.MEPAddTransition, "_execute", return_value=None + ) as transition: mep.FitFlowSegments._execute(op, context=context) obstruction.assert_not_called() diff --git a/src/bonsai/test/bim/module/model/test_mep_segment_edition.py b/src/bonsai/test/bim/module/model/test_mep_segment_edition.py index 2451ceb7e2..ecadf11d45 100644 --- a/src/bonsai/test/bim/module/model/test_mep_segment_edition.py +++ b/src/bonsai/test/bim/module/model/test_mep_segment_edition.py @@ -173,8 +173,9 @@ def test_gizmo_group_class_wiring(gizmo_cls_name, bl_idname, is_element_predicat predicate = getattr(tool.Parametric, is_element_predicate) fake_element = Mock() fake_element.is_a.return_value = True - with patch.object(tool.Parametric, is_element_predicate, side_effect=predicate) as p, patch.object( - tool.System, "has_parametric_body", return_value=True + with ( + patch.object(tool.Parametric, is_element_predicate, side_effect=predicate) as p, + patch.object(tool.System, "has_parametric_body", return_value=True), ): cls.is_element_type(fake_element) assert p.called, f"{gizmo_cls_name}.is_element_type did not delegate to Parametric.{is_element_predicate}" diff --git a/src/bonsai/test/bim/test_preview_cancel_ops_forward_compat.py b/src/bonsai/test/bim/test_preview_cancel_ops_forward_compat.py index d67f258eaa..5a4b4f244e 100644 --- a/src/bonsai/test/bim/test_preview_cancel_ops_forward_compat.py +++ b/src/bonsai/test/bim/test_preview_cancel_ops_forward_compat.py @@ -139,6 +139,5 @@ def test_every_cancel_ops_entry_has_a_real_preview_propertygroup() -> None: orphaned = [attr for attr, _op in preview_base.PREVIEW_CANCEL_OPS if attr not in declared_attrs] assert not orphaned, ( "PREVIEW_CANCEL_OPS contains entries whose PointerProperty child no longer " - f"exists on {UMBRELLA_CLASS}. Drop the stale tuple(s):\n " - + "\n ".join(orphaned) + f"exists on {UMBRELLA_CLASS}. Drop the stale tuple(s):\n " + "\n ".join(orphaned) ) diff --git a/src/bonsaiviewer-autodesk/packaging/build.py b/src/bonsaiviewer-autodesk/packaging/build.py index 6e53bf1ade..80206d8caa 100644 --- a/src/bonsaiviewer-autodesk/packaging/build.py +++ b/src/bonsaiviewer-autodesk/packaging/build.py @@ -29,11 +29,11 @@ import zipfile from pathlib import Path PROJECT_ROOT = Path(__file__).resolve().parent.parent -DIST_DIR = PROJECT_ROOT / "dist" -TARGET_DIR = PROJECT_ROOT / "target" / "release" +DIST_DIR = PROJECT_ROOT / "dist" +TARGET_DIR = PROJECT_ROOT / "target" / "release" CONNECTOR_FOLDER_NAME = "autodesk" -BINARY_NAME = "bonsaiviewer-autodesk" +BINARY_NAME = "bonsaiviewer-autodesk" def _platform_tag() -> str: @@ -73,9 +73,7 @@ def main() -> None: bin_src = TARGET_DIR / _binary_name_for_host() if not bin_src.exists(): - raise FileNotFoundError( - f"cargo build did not produce expected binary at {bin_src}" - ) + raise FileNotFoundError(f"cargo build did not produce expected binary at {bin_src}") bundle_dir = DIST_DIR / CONNECTOR_FOLDER_NAME bundle_dir.mkdir(parents=True) diff --git a/src/ifc5d/ifc5d/csv2ifc.py b/src/ifc5d/ifc5d/csv2ifc.py index 9f39547d43..fcfc0d119c 100644 --- a/src/ifc5d/ifc5d/csv2ifc.py +++ b/src/ifc5d/ifc5d/csv2ifc.py @@ -57,7 +57,8 @@ class CsvHeader(TypedDict): # Formula Formula: NotRequired[str] - #QuantityClass: NotRequired[str] + # QuantityClass: NotRequired[str] + # Currently we assume that if column is not part of the main header, # then it is a cost value category. So here we list any additional column @@ -97,7 +98,8 @@ class CostItem(TypedDict): Query: Union[str, None] Formula: Union[str, None] - #QuantityClass: Union[str, None] + # QuantityClass: Union[str, None] + class Csv2Ifc: # Inputs. @@ -420,7 +422,7 @@ class Csv2Ifc: products=results, formula=cost_item["Formula"], ifc_class=ifc_quantity_class, - ) + ) self.create_cost_items(cost_item["children"], cost_item["ifc"]) diff --git a/src/ifc5d/ifc5d/ifc2json.py b/src/ifc5d/ifc5d/ifc2json.py index a3938f8d60..80f246e3b0 100644 --- a/src/ifc5d/ifc5d/ifc2json.py +++ b/src/ifc5d/ifc5d/ifc2json.py @@ -168,12 +168,7 @@ class ifc5D2json: data["UnitSymbol"] = ifcopenshell.util.unit.get_unit_symbol(unit) if quantity.is_a("IfcPhysicalSimpleQuantity"): measure_class = ( - quantity.declaration - .as_entity() - .attribute_by_index(3) - .type_of_attribute() - .declared_type() - .name() + quantity.declaration.as_entity().attribute_by_index(3).type_of_attribute().declared_type().name() ) if "Count" in measure_class: data["UnitSymbol"] = "U" diff --git a/src/ifcopenshell-python/ifcopenshell/__init__.py b/src/ifcopenshell-python/ifcopenshell/__init__.py index b059dfb7e0..01cc8eb3c0 100644 --- a/src/ifcopenshell-python/ifcopenshell/__init__.py +++ b/src/ifcopenshell-python/ifcopenshell/__init__.py @@ -107,6 +107,7 @@ else: def optional_logger_args(logger: ifcopenshell_wrapper.logger | None) -> tuple[logger] | tuple[()]: return (logger,) if logger is not None else () + # explicitly specify available imported symbols # (it's a requirement for a typed library) __all__ = [ diff --git a/src/ifcopenshell-python/ifcopenshell/api/alignment/create.py b/src/ifcopenshell-python/ifcopenshell/api/alignment/create.py index 5d7d105ec8..a1b7734af6 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/alignment/create.py +++ b/src/ifcopenshell-python/ifcopenshell/api/alignment/create.py @@ -87,9 +87,7 @@ def create( _create_geometric_representation(file, alignment) referent_name = ifcopenshell.util.alignment.station_as_string(file, start_station) - referent = ifcopenshell.api.alignment.add_stationing_referent( - file, referent_name, alignment, 0.0, start_station - ) + referent = ifcopenshell.api.alignment.add_stationing_referent(file, referent_name, alignment, 0.0, start_station) for layout in alignment_layouts: _add_zero_length_segment(file, layout) diff --git a/src/ifcopenshell-python/ifcopenshell/api/alignment/distance_along_from_station.py b/src/ifcopenshell-python/ifcopenshell/api/alignment/distance_along_from_station.py index 9c08f479be..f4db3e4b4e 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/alignment/distance_along_from_station.py +++ b/src/ifcopenshell-python/ifcopenshell/api/alignment/distance_along_from_station.py @@ -73,7 +73,10 @@ def distance_along_from_station(file: ifcopenshell.file, alignment: entity_insta return station - start_station stations = [ - (_distance_along_of_referent(referent), ifcopenshell.util.element.get_pset(referent, name="Pset_Stationing", prop="Station")) + ( + _distance_along_of_referent(referent), + ifcopenshell.util.element.get_pset(referent, name="Pset_Stationing", prop="Station"), + ) for referent in referent_nest.RelatedObjects ] stations.sort(key=lambda entry: entry[0]) diff --git a/src/ifcopenshell-python/ifcopenshell/express/bootstrap.py b/src/ifcopenshell-python/ifcopenshell/express/bootstrap.py index f0095f83a5..2e2fc2e120 100644 --- a/src/ifcopenshell-python/ifcopenshell/express/bootstrap.py +++ b/src/ifcopenshell-python/ifcopenshell/express/bootstrap.py @@ -161,7 +161,18 @@ keywords = list(filter(operator.attrgetter("is_keyword"), terminals)) # terminals is identity-ordered (no __eq__/__hash__), so sort for determinism keywords.sort(key=lambda x: repr(x)) negated_keywords = map(lambda s: "~%s" % s, keywords) -no_action = {"letter", "digit", "digits", "real_literal", "integer_literal", "string_literal", "simple_string_literal", "letter", "not_quote", "not_paren_star_quote_special"} +no_action = { + "letter", + "digit", + "digits", + "real_literal", + "integer_literal", + "string_literal", + "simple_string_literal", + "letter", + "not_quote", + "not_paren_star_quote_special", +} while True: emitted_in_loop = set() @@ -197,7 +208,9 @@ for id in sorted(to_emit): elif id in to_original_text: stmt = "(original_text_for%s).add_parse_action(token_map(str.lower))" % stmt if id not in no_action and not isinstance(expr.contents, Keyword): - children = list(map(operator.attrgetter('contents'), reduce(lambda x, y: x | y, (find_bytype(e, Keyword) for e in [expr])))) + children = list( + map(operator.attrgetter("contents"), reduce(lambda x, y: x | y, (find_bytype(e, Keyword) for e in [expr]))) + ) has_duplicates = len(children) > len(set(children)) node_type = "ListNode" if ("ZeroOrMore" in stmt or has_duplicates) else "Node" action = ".set_parse_action(%s)" % ( @@ -246,6 +259,4 @@ if __name__ == "__main__": mdl = importlib.import_module(output) mdl.Generator(m).emit() sys.stdout.write(m.schema.name) -""" - % ("\n ".join(statements)) - ) +""" % ("\n ".join(statements))) diff --git a/src/ifcopenshell-python/ifcopenshell/express/cat.py b/src/ifcopenshell-python/ifcopenshell/express/cat.py index d6e7b2c880..373afeb1d5 100644 --- a/src/ifcopenshell-python/ifcopenshell/express/cat.py +++ b/src/ifcopenshell-python/ifcopenshell/express/cat.py @@ -1,15 +1,16 @@ import sys, fileinput -if sys.platform == "win32" and not hasattr(sys.stdout, 'buffer'): +if sys.platform == "win32" and not hasattr(sys.stdout, "buffer"): import os, msvcrt + msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY) files = sys.argv[1:] -if files[0] == '-o': - b = open(files[1], 'wb') +if files[0] == "-o": + b = open(files[1], "wb") files = files[2:] else: - b = getattr(sys.stdout, 'buffer', sys.stdout) + b = getattr(sys.stdout, "buffer", sys.stdout) -for line in fileinput.input(files=files, mode='rb'): +for line in fileinput.input(files=files, mode="rb"): b.write(line) diff --git a/src/ifcopenshell-python/ifcopenshell/express/codegen.py b/src/ifcopenshell-python/ifcopenshell/express/codegen.py index 8e2cf2a956..1d2b2b1262 100644 --- a/src/ifcopenshell-python/ifcopenshell/express/codegen.py +++ b/src/ifcopenshell-python/ifcopenshell/express/codegen.py @@ -27,7 +27,7 @@ def indent(n, s): else: strs = s splitted = itertools.chain.from_iterable(map(functools.partial(str.split, sep="\n"), map(str, strs))) - return "\n".join(" "*n + l for l in splitted) + return "\n".join(" " * n + l for l in splitted) class Base: diff --git a/src/ifcopenshell-python/ifcopenshell/express/header.py b/src/ifcopenshell-python/ifcopenshell/express/header.py index 212f4f5515..9686539ce4 100644 --- a/src/ifcopenshell-python/ifcopenshell/express/header.py +++ b/src/ifcopenshell-python/ifcopenshell/express/header.py @@ -26,6 +26,7 @@ import documentation from collections import defaultdict + class Header(codegen.Base): def __init__(self, mapping): declarations = [] @@ -41,7 +42,12 @@ class Header(codegen.Base): % dict({"documentation": templates.multi_line_comment(documentation.description(kwargs["name"]))}, **kwargs) ) - forward_names = list(mapping.schema.entities.keys()) + list(mapping.schema.simpletypes.keys()) + list(mapping.schema.selects.keys()) + list(mapping.schema.enumerations.keys()) + forward_names = ( + list(mapping.schema.entities.keys()) + + list(mapping.schema.simpletypes.keys()) + + list(mapping.schema.selects.keys()) + + list(mapping.schema.enumerations.keys()) + ) forward_definitions = "".join(["class %s; " % n for n in forward_names]) select_super_types = defaultdict(list) @@ -57,11 +63,14 @@ class Header(codegen.Base): yield x if mapping.schema.is_select(x): yield from visit_select(mapping.schema.selects[x]) - - write(templates.select, - name=name, - template_items="\n".join(templates.select_list_item % {'item_name': nm} for nm in visit_select(type)), - cast_functions="\n".join(templates.select_cast_function % {'name': name, 'item_name': nm} for nm in visit_select(type)), + + write( + templates.select, + name=name, + template_items="\n".join(templates.select_list_item % {"item_name": nm} for nm in visit_select(type)), + cast_functions="\n".join( + templates.select_cast_function % {"name": name, "item_name": nm} for nm in visit_select(type) + ), ) def get_select_super_types(nm, bases=[]): @@ -115,10 +124,15 @@ class Header(codegen.Base): # with the v1 data model we're back to exactly one supertype, no more virtual inheritance to handle selects assert len(superclasses) == 1 superclass_statement = superclasses[0] - superclass_2 = superclass_statement.split('::')[-1] + superclass_2 = superclass_statement.split("::")[-1] write( - templates.simpletype, name=name, type=type_str, attr_type=attr_type, superclass=superclass_statement, superclass_2=superclass_2 + templates.simpletype, + name=name, + type=type_str, + attr_type=attr_type, + superclass=superclass_statement, + superclass_2=superclass_2, ) class_definitions = [] @@ -145,7 +159,7 @@ class Header(codegen.Base): if mapping.make_argument_type(attr) != "ifcopenshell::Argument_UNKNOWN": attr_lines.append("%s %s() const;" % (type_str, attr.name)) attr_lines.append("void set%s(const %s& v);" % (attr.name, type_str)) - if type_str == 'std::optional< std::string >': + if type_str == "std::optional< std::string >": # because a 2-step char[] -> std::string -> optional is not allowed # attr_lines.append("void set%s(const %s& v);" % (attr.name, 'std::string')) pass @@ -182,7 +196,7 @@ class Header(codegen.Base): supertypes = list(map(case_normalize, supertypes)) assert len(supertypes) == 1 superclass = supertypes[0] - superclass_2 = superclass.split('::')[-1] + superclass_2 = superclass.split("::")[-1] argument_count = mapping.argument_count(type) diff --git a/src/ifcopenshell-python/ifcopenshell/express/implementation.py b/src/ifcopenshell-python/ifcopenshell/express/implementation.py index 57d04a313b..165ec32fa5 100644 --- a/src/ifcopenshell-python/ifcopenshell/express/implementation.py +++ b/src/ifcopenshell-python/ifcopenshell/express/implementation.py @@ -67,7 +67,7 @@ class Implementation(codegen.Base): templates.enum_from_string_stmt % dict(context, **locals()) for value in enum.values ), ) - + for name, enum in mapping.schema.selects.items(): write( templates.select_function, @@ -107,21 +107,18 @@ class Implementation(codegen.Base): return templates.get_attr_stmt_nested_array elif arg["is_templated_list"] and not (simple or express): return templates.get_attr_stmt_array - elif arg["argument_type_enum"] == 'ifcopenshell::Argument_ENTITY_INSTANCE': + elif arg["argument_type_enum"] == "ifcopenshell::Argument_ENTITY_INSTANCE": return templates.get_attr_stmt_entity else: return templates.get_attr_stmt null_check = "" if arg["is_optional"]: - attr_check = ( - "if(get_attribute_value(%d).isNull()) { return %%s; }" - % (arg["index"] - 1,) - ) + attr_check = "if(get_attribute_value(%d).isNull()) { return %%s; }" % (arg["index"] - 1,) if "std::optional" in arg["full_type"]: null_check = attr_check % "std::nullopt" else: - null_check = attr_check % (arg['full_type'] + "{}") + null_check = attr_check % (arg["full_type"] + "{}") tmpl = find_template(arg) write_attr( @@ -154,7 +151,7 @@ class Implementation(codegen.Base): return templates.set_attr_stmt_nested_array elif arg["is_templated_list"] and not (simple or express): return templates.set_attr_stmt_array - elif arg["argument_type_enum"] == 'ifcopenshell::Argument_ENTITY_INSTANCE': + elif arg["argument_type_enum"] == "ifcopenshell::Argument_ENTITY_INSTANCE": return templates.set_attr_instance else: return templates.set_attr_stmt @@ -175,7 +172,9 @@ class Implementation(codegen.Base): "non_optional_type": arg["non_optional_type"].replace("::Value", ""), "star_if_optional": "*" if "std::optional" in arg["full_type"] else "", "check_optional_set_begin": "if (v) {" if "std::optional" in arg["full_type"] else "", - "check_optional_set_else": "} else {" if "std::optional" in arg["full_type"] else "if constexpr (false)", + "check_optional_set_else": ( + "} else {" if "std::optional" in arg["full_type"] else "if constexpr (false)" + ), "check_optional_set_end": "}" if "std::optional" in arg["full_type"] else "", }, ) @@ -190,11 +189,15 @@ class Implementation(codegen.Base): tmpl = ( templates.constructor_stmt_array if arg["is_templated_list"] - else templates.constructor_stmt_enum - if arg["is_enum"] - else templates.constructor_stmt_instance - if arg["full_type"].endswith('*') - else templates.constructor_stmt + else ( + templates.constructor_stmt_enum + if arg["is_enum"] + else ( + templates.constructor_stmt_instance + if arg["full_type"].endswith("*") + else templates.constructor_stmt + ) + ) ) impl = tmpl % { "name": deref_name, @@ -236,11 +239,7 @@ class Implementation(codegen.Base): for i in type.inverse ] - superclass = ( - "%s(e)" % type.supertypes[0] - if len(type.supertypes) == 1 - else "express::Entity(e)" - ) + superclass = "%s(e)" % type.supertypes[0] if len(type.supertypes) == 1 else "express::Entity(e)" superclass_num_attrs = ( "%s(const std::weak_ptr&(in_memory_attribute_storage(%%d)))" % type.supertypes[0] @@ -371,7 +370,17 @@ class Implementation(codegen.Base): # ("const std::weak_ptr& e",), # "", # ), - ("", "", initializer, "", ("%s v" % type_str,), ("set_attribute_value(0, %s(v));" % ("cast_vector" if mapping.is_templated_list(type) else ""))), + ( + "", + "", + initializer, + "", + ("%s v" % type_str,), + ( + "set_attribute_value(0, %s(v));" + % ("cast_vector" if mapping.is_templated_list(type) else "") + ), + ), # ("v", "", constructor, "", ("%s v" % type_str,), ""), ("", "", templates.cast_function, type_str, (), simpletype_impl_cast), ), diff --git a/src/ifcopenshell-python/ifcopenshell/express/nodes.py b/src/ifcopenshell-python/ifcopenshell/express/nodes.py index 34d3ef747b..2b8b872c83 100644 --- a/src/ifcopenshell-python/ifcopenshell/express/nodes.py +++ b/src/ifcopenshell-python/ifcopenshell/express/nodes.py @@ -23,6 +23,7 @@ import operator import collections import bootstrap + class Node: def __init__(self, s, loc, tokens, rule=None): self.rule = rule or (type(self).__name__) @@ -58,15 +59,15 @@ class ListNode: rules_as_list = set() for t in self.tokens: - r = getattr(t, 'rule', None) + r = getattr(t, "rule", None) if r: rules_as_list.add(r) self.dict_tokens[r].append(t) - + for r, t in tokens.asDict().items(): if r not in rules_as_list: self.dict_tokens[r].append(t) - + self.flat = sum([getattr(t, "flat", [t]) for t in self.tokens], []) def __repr__(self): @@ -74,7 +75,7 @@ class ListNode: def __iter__(self): return iter(self.tokens) - + # Somehow indexing messes up the pyparsing results, so instead of x[0] use list(x)[0] # def __getitem__(self, i): # return self.tokens[i] @@ -110,7 +111,7 @@ def format_clause(exp): return "".join(whitespace(term) for term in exp.flat) -class TypeDeclaration(Node): +class TypeDeclaration(Node): name = property(lambda self: self.type_id[0]) utype = property(lambda self: self.underlying_type.any().any()) type = property(lambda self: self.utype[0] if isinstance(self.utype, list) else self.utype) @@ -245,7 +246,8 @@ class NamedType(Node): def do_try(fn): try: return fn() - except: pass + except: + pass def get_rule_id(x): @@ -255,8 +257,14 @@ def get_rule_id(x): if matches: return matches[0] + rule_dependencies = { - k: list(map(operator.attrgetter('contents'), bootstrap.reduce(lambda x, y: x | y, (bootstrap.find_bytype(e, bootstrap.Keyword) for e in [v])))) \ + k: list( + map( + operator.attrgetter("contents"), + bootstrap.reduce(lambda x, y: x | y, (bootstrap.find_bytype(e, bootstrap.Keyword) for e in [v])), + ) + ) for k, v in bootstrap.express } @@ -264,16 +272,17 @@ all_rules = [k for k, e in bootstrap.express] rule_definitions = {k: v for k, v in bootstrap.express} + def to_tree(x, key=None): - + def prune(di): # translate class names back to grammar rules if nested actions are encountered di = {get_rule_id(k) or k: v for k, v in di.items()} - + def replace_synonyms(x): for y in x: yield y - if False: # y in di: + if False: # y in di: # production element from grammar is found in parsed data, # return that. @@ -292,19 +301,21 @@ def to_tree(x, key=None): yield S # Do this recursively yield from replace_synonyms([S]) - + # is this a concatenation with zero or more synonyms? then also processs that # @todo catches: # - simple_expression = term { add_like_op term } . # but should probably also work on # - a = b { b } # in which case the second Concat would be eliminated - elif isinstance(rule, bootstrap.Concat) and \ - len(rule.contents) == 2 and \ - is_synonym(rule.contents[0]) and \ - isinstance(rule.contents[1].contents, bootstrap.Repeated) and \ - isinstance(rule.contents[1].contents.contents[0], bootstrap.Concat) and \ - str(rule.contents[1].contents.contents[0].contents[1]) == str(rule.contents[0]): + elif ( + isinstance(rule, bootstrap.Concat) + and len(rule.contents) == 2 + and is_synonym(rule.contents[0]) + and isinstance(rule.contents[1].contents, bootstrap.Repeated) + and isinstance(rule.contents[1].contents.contents[0], bootstrap.Concat) + and str(rule.contents[1].contents.contents[0].contents[1]) == str(rule.contents[0]) + ): S = is_synonym(rule.contents[0]) yield S # Do this recursively @@ -315,13 +326,13 @@ def to_tree(x, key=None): if key == "aggregation_types": # hack hack hack apparently the parser can't distinguish these subrules += list(replace_synonyms(rule_dependencies["general_aggregation_types"])) - + if rule_dependencies[key] and not subrules: # sometimes an intermediate production rule is missing # from the pyparsing output, e.g from parameter to simple_expression # directly. Recover from this. subrules = sum(map(rule_dependencies.__getitem__, rule_dependencies[key]), []) - + if not isinstance(rule_definitions[key], bootstrap.Union): # Filter out terminals when not a union. E.g no # reason to retain TYPE, END_TYPE, but operators @@ -331,7 +342,7 @@ def to_tree(x, key=None): vs = list(di.values()) return {k: v for k, v in di.items() if k in subrules or (k == key and len(vs) == 1 and vs[0] not in all_rules)} - + def simplify(di): if isinstance(di, list): if set(map(type, di)) == {str} and set(map(len, di)) == {1}: @@ -343,11 +354,11 @@ def to_tree(x, key=None): return {k: simplify(v) for k, v in di.items()} else: return di - + if isinstance(x, ListNode): d = to_tree(x.dict_tokens, key=get_rule_id(x) or key) - if key == 'if_stmt': + if key == "if_stmt": # The definition of if statement if (roughy): # 'if' expr 'then' stmt+ 'else' stmt+ # this causes stmt to be joined under the same @@ -355,39 +366,41 @@ def to_tree(x, key=None): # `else_stmt` that collects the second group # of stmts. - statements = x.dict_tokens['stmt'] - + statements = x.dict_tokens["stmt"] + else_index = None if_nesting = 0 - for i, tk in enumerate(x.flat): - if tk == 'if': if_nesting += 1 - if tk == 'end_if': if_nesting -= 1 - if tk == 'else' and if_nesting == 1: + for i, tk in enumerate(x.flat): + if tk == "if": + if_nesting += 1 + if tk == "end_if": + if_nesting -= 1 + if tk == "else" and if_nesting == 1: else_index = i if else_index: indices = [] for s in statements: for i in range(max(indices, default=0), len(x.flat)): - if x.flat[i:i+len(s.flat)] == s.flat: + if x.flat[i : i + len(s.flat)] == s.flat: indices.append(i) break assert len(indices) == len(statements) before_else = [i < else_index for i in indices] - else_stmt = [st for b, st in zip(before_else, d['stmt']) if not b] - d['stmt'] = [st for b, st in zip(before_else, d['stmt']) if b] + else_stmt = [st for b, st in zip(before_else, d["stmt"]) if not b] + d["stmt"] = [st for b, st in zip(before_else, d["stmt"]) if b] if else_stmt: - d['else_stmt'] = else_stmt - - if key == 'formal_parameter': + d["else_stmt"] = else_stmt + + if key == "formal_parameter": # Not so pretty hack to fix the overwriting of simple_id-like # ast nodes. The full solution would probably to register parse # actions. And directly reassign. - pid = d['parameter_id'][0][0] - d['parameter_id'][0] = x.flat[:x.flat.index(pid)+1:2] + pid = d["parameter_id"][0][0] + d["parameter_id"][0] = x.flat[: x.flat.index(pid) + 1 : 2] if key is None: return {get_rule_id(x): d} @@ -400,7 +413,10 @@ def to_tree(x, key=None): elif isinstance(x, dict): # d = {k: to_tree(v, key=k) for k, v in x.items()} # not fully understood, but when finding specific node Types and production rules, prioritize the former - d = {get_rule_id(k) or k: to_tree(v, key=k) for k, v in sorted(x.items(), key=lambda p: get_rule_id(p[0]) is not None)} + d = { + get_rule_id(k) or k: to_tree(v, key=k) + for k, v in sorted(x.items(), key=lambda p: get_rule_id(p[0]) is not None) + } return simplify(prune(d)) elif isinstance(x, list): return [to_tree(v, key=key) for v in x] @@ -459,7 +475,8 @@ class SuperTypeExpression(Node): else: constraint = self.supertype_rule[0] return [ - list(list(s)[0])[0].simple_id for s in list(list(list(constraint.subtype_constraint[0].supertype_expression[0])[0])[0].one_of[0])[2::2] + list(list(s)[0])[0].simple_id + for s in list(list(list(constraint.subtype_constraint[0].supertype_expression[0])[0])[0].one_of[0])[2::2] ] sub_types = property(get_sub_types) @@ -576,10 +593,11 @@ class ProcedureDeclaration(ListNode): @property def name(self): return self.flat[1] - - + + class FunctionDeclaration(ProcedureDeclaration): pass - + + class RuleDeclaration(ProcedureDeclaration): pass diff --git a/src/ifcopenshell-python/ifcopenshell/express/rule_compiler.py b/src/ifcopenshell-python/ifcopenshell/express/rule_compiler.py index 0fdc01f86c..737c699ae5 100644 --- a/src/ifcopenshell-python/ifcopenshell/express/rule_compiler.py +++ b/src/ifcopenshell-python/ifcopenshell/express/rule_compiler.py @@ -695,6 +695,7 @@ codegen_rule("MOD", lambda context: "%") codegen_rule("TRUE", lambda context: "True") codegen_rule("FALSE", lambda context: "False") + def _dotted_name(node: ast.AST): """Return dotted name for Name/Attribute chains, else None.""" if isinstance(node, ast.Name): @@ -704,6 +705,7 @@ def _dotted_name(node: ast.AST): return f"{base}.{node.attr}" if base else node.attr return None + class AttributeGetattrTransformer(ast.NodeTransformer): def visit_Attribute(self, node): parents = [] @@ -720,7 +722,7 @@ class AttributeGetattrTransformer(ast.NodeTransformer): if isinstance(node.ctx, ast.Store): return node - if _dotted_name(node) in ('ifcopenshell.create_entity', 'str.lower'): + if _dotted_name(node) in ("ifcopenshell.create_entity", "str.lower"): return node if node.attr.startswith("__"): diff --git a/src/ifcopenshell-python/ifcopenshell/express/schema.py b/src/ifcopenshell-python/ifcopenshell/express/schema.py index 1f0a175d80..bd2e12d95f 100644 --- a/src/ifcopenshell-python/ifcopenshell/express/schema.py +++ b/src/ifcopenshell-python/ifcopenshell/express/schema.py @@ -87,14 +87,8 @@ class Schema: sort = lambda d: OrderedCaseInsensitiveDict(sorted(d)) - declarations = [ - d.any()[0] - for d in schema_declarations - if d.rule == "declaration" - ] + [ - d - for d in schema_declarations - if d.rule == "RuleDeclaration" + declarations = [d.any()[0] for d in schema_declarations if d.rule == "declaration"] + [ + d for d in schema_declarations if d.rule == "RuleDeclaration" ] self.types = sort([(t.name, t) for t in declarations if isinstance(t, nodes.TypeDeclaration)]) @@ -102,8 +96,12 @@ class Schema: self.rules = sort([(t.name, t) for t in declarations if isinstance(t, nodes.RuleDeclaration)]) self.functions = sort([(t.name, t) for t in declarations if isinstance(t, nodes.FunctionDeclaration)]) - self.keys = list(self.types.keys()) + list(self.entities.keys()) + list(self.rules.keys()) + list(self.functions.keys()) - self.all_declarations = {k: v for d in (self.types, self.entities, self.rules, self.functions) for k, v in d.items()} + self.keys = ( + list(self.types.keys()) + list(self.entities.keys()) + list(self.rules.keys()) + list(self.functions.keys()) + ) + self.all_declarations = { + k: v for d in (self.types, self.entities, self.rules, self.functions) for k, v in d.items() + } of_type = lambda *types: sort( [(a, b.type) for a, b in self.types.items() if any(isinstance(b.type, ty) for ty in types)] diff --git a/src/ifcopenshell-python/ifcopenshell/express/schema_class.py b/src/ifcopenshell-python/ifcopenshell/express/schema_class.py index a1376a07c3..023abbdaa3 100644 --- a/src/ifcopenshell-python/ifcopenshell/express/schema_class.py +++ b/src/ifcopenshell-python/ifcopenshell/express/schema_class.py @@ -110,9 +110,7 @@ class LateBoundSchemaInstantiator: self.declarations[str(name)].set_subtypes([self.declarations[str(v)] for v in tys]) def finalize(self, can_be_instantiated_set, override_schema_name=None): - self.schema = w.schema_definition( - override_schema_name or self.schema_name, list(self.declarations.values()) - ) + self.schema = w.schema_definition(override_schema_name or self.schema_name, list(self.declarations.values())) def disown(self): for elem in self.cache + list(self.declarations.values()): @@ -123,6 +121,7 @@ class string_pool: def __init__(self, fn): self.di = {} self.fn = fn + def append(self, v): def _(): if i := self.di.get(v): @@ -131,7 +130,9 @@ class string_pool: i = len(self.di) self.di[v] = i return i + return self.fn(_()) + def __iter__(self): return iter(self.di.keys()) @@ -146,9 +147,9 @@ class EarlyBoundCodeWriter: "", '#include "../../ifcparse/schema.h"', '#include "../../ifcparse/schemas/%(schema_name_title)s.h"' % self.__dict__, - '#include ', + "#include ", "", - 'using namespace std::string_literals;', + "using namespace std::string_literals;", "using namespace ifcopenshell;", "", ] @@ -180,18 +181,18 @@ class EarlyBoundCodeWriter: # self.statements.append("{factory_placeholder}") -# self.statements.append( -# """ -# #if defined(__clang__) -# __attribute__((optnone)) -# #elif defined(__GNUC__) || defined(__GNUG__) -# #pragma GCC push_options -# #pragma GCC optimize ("O0") -# #elif defined(_MSC_VER) -# #pragma optimize("", off) -# #endif -# """ -# ) + # self.statements.append( + # """ + # #if defined(__clang__) + # __attribute__((optnone)) + # #elif defined(__GNUC__) || defined(__GNUG__) + # #pragma GCC push_options + # #pragma GCC optimize ("O0") + # #elif defined(_MSC_VER) + # #pragma optimize("", off) + # #endif + # """ + # ) self.statements.append("ifcopenshell::schema_definition* %s_populate_schema() {" % self.schema_name.upper()) self.statements.append("{string_pool_placeholder}") @@ -200,7 +201,7 @@ class EarlyBoundCodeWriter: index_in_schema = self.names.index(name) ref = self.strings.append(name) self.statements.append( - ' %(schema_name)s_types[%(index_in_schema)d] = new type_declaration(%(ref)s, %(index_in_schema)d, %(declared_type)s);' + " %(schema_name)s_types[%(index_in_schema)d] = new type_declaration(%(ref)s, %(index_in_schema)d, %(declared_type)s);" % locals() ) @@ -210,7 +211,7 @@ class EarlyBoundCodeWriter: ref = self.strings.append(name) items = ",".join(self.strings.append(v) for v in enum.values) self.statements.append( - ' %(schema_name)s_types[%(index_in_schema)d] = new enumeration_type(%(ref)s, %(index_in_schema)d, {%(items)s});' + " %(schema_name)s_types[%(index_in_schema)d] = new enumeration_type(%(ref)s, %(index_in_schema)d, {%(items)s});" % locals() ) @@ -218,10 +219,14 @@ class EarlyBoundCodeWriter: schema_name = self.schema_name.upper() index_in_schema = self.names.index(name) ref = self.strings.append(name) - supertype = "0" if len(type.supertypes) == 0 else "%s_types[%d]" % (self.schema_name, self.names.index(type.supertypes[0])) + supertype = ( + "0" + if len(type.supertypes) == 0 + else "%s_types[%d]" % (self.schema_name, self.names.index(type.supertypes[0])) + ) is_abstract = "true" if type.abstract else "false" self.statements.append( - ' %(schema_name)s_types[%(index_in_schema)d] = new entity(%(ref)s, %(is_abstract)s, %(index_in_schema)d, (entity*) %(supertype)s);' + " %(schema_name)s_types[%(index_in_schema)d] = new entity(%(ref)s, %(is_abstract)s, %(index_in_schema)d, (entity*) %(supertype)s);" % locals() ) @@ -233,73 +238,86 @@ class EarlyBoundCodeWriter: map(lambda v: "%s_types[%d]" % (self.schema_name, self.names.index(v)), sorted(map(str, type.values))) ) self.statements.append( - ' %(schema_name)s_types[%(index_in_schema)d] = new select_type(%(ref)s, %(index_in_schema)d, {%(items)s});' + " %(schema_name)s_types[%(index_in_schema)d] = new select_type(%(ref)s, %(index_in_schema)d, {%(items)s});" % locals() ) def entity_attributes(self, name, attribute_definitions, is_derived): schema_name = self.schema_name.upper() index_in_schema = self.names.index(name) + def _(): index_in_schema = self.names.index(name) schema_name = self.schema_name for attr_name, decl_type, optional in attribute_definitions: attr_name_ref = self.strings.append(attr_name) optional_cpp = str(optional).lower() - yield 'new attribute(%(attr_name_ref)s, %(decl_type)s, %(optional_cpp)s)' % locals() + yield "new attribute(%(attr_name_ref)s, %(decl_type)s, %(optional_cpp)s)" % locals() + attributes = ",".join(_()) derived = ",".join(map(lambda b: str(b).lower(), is_derived)) - self.statements.append(" ((entity*)%(schema_name)s_types[%(index_in_schema)d])->set_attributes({%(attributes)s}, {%(derived)s});" % locals()) + self.statements.append( + " ((entity*)%(schema_name)s_types[%(index_in_schema)d])->set_attributes({%(attributes)s}, {%(derived)s});" + % locals() + ) def inverse_attributes(self, name, inv_attrs): schema_name = self.schema_name.upper() index_in_schema = self.names.index(name) + def _(): schema_name = self.schema_name index_in_schema = self.names.index(name) for attr_name, aggr_type, bound1, bound2, entity_ref, attribute_entity, attribute_entity_index in inv_attrs: attr_name_ref = self.strings.append(attr_name) opposite_index_in_schema = self.names.index(entity_ref) - opposite1 = '%(schema_name)s_types[%(opposite_index_in_schema)d]' % locals() + opposite1 = "%(schema_name)s_types[%(opposite_index_in_schema)d]" % locals() opposite_index_in_schema = self.names.index(attribute_entity) - opposite2 = '%(schema_name)s_types[%(opposite_index_in_schema)d]' % locals() - yield 'new inverse_attribute(%(attr_name_ref)s, inverse_attribute::%(aggr_type)s_type, %(bound1)d, %(bound2)d, ((entity*) %(opposite1)s), ((entity*) %(opposite2)s)->attributes()[%(attribute_entity_index)d])' % locals() + opposite2 = "%(schema_name)s_types[%(opposite_index_in_schema)d]" % locals() + yield "new inverse_attribute(%(attr_name_ref)s, inverse_attribute::%(aggr_type)s_type, %(bound1)d, %(bound2)d, ((entity*) %(opposite1)s), ((entity*) %(opposite2)s)->attributes()[%(attribute_entity_index)d])" % locals() + attributes = ",".join(_()) - self.statements.append(" ((entity*) %(schema_name)s_types[%(index_in_schema)d])->set_inverse_attributes({%(attributes)s});" % locals()) + self.statements.append( + " ((entity*) %(schema_name)s_types[%(index_in_schema)d])->set_inverse_attributes({%(attributes)s});" + % locals() + ) def entity_subtypes(self, name, tys): schema_name = self.schema_name.upper() index_in_schema = self.names.index(name) - subtypes = ",".join(map(lambda t: ("((entity*) %%(schema_name)s_types[%d])" % self.names.index(t)), tys)) % locals() - self.statements.append(" ((entity*) %(schema_name)s_types[%(index_in_schema)d])->set_subtypes({%(subtypes)s});" % locals()) + subtypes = ( + ",".join(map(lambda t: ("((entity*) %%(schema_name)s_types[%d])" % self.names.index(t)), tys)) % locals() + ) + self.statements.append( + " ((entity*) %(schema_name)s_types[%(index_in_schema)d])->set_subtypes({%(subtypes)s});" % locals() + ) def finalize(self, can_be_instantiated_set): schema_name = self.schema_name.upper() schema_name_title = self.schema_name.capitalize() + def _(): schema_name = self.schema_name.upper() schema_name_title = self.schema_name.capitalize() for type_name in self.names: index_in_schema = self.names.index(type_name) yield "%(schema_name)s_types[%(index_in_schema)d]" % locals() + declarations = ",".join(_()) schema_name_ref = self.strings.append(schema_name) - self.statements.append( - ' return new schema_definition(%(schema_name_ref)s, {%(declarations)s});' - % locals() - ) - self.statements.append("}"); + self.statements.append(" return new schema_definition(%(schema_name_ref)s, {%(declarations)s});" % locals()) + self.statements.append("}") -# self.statements.append( -# """ -# #if defined(__clang__) -# #elif defined(__GNUC__) || defined(__GNUG__) -# #pragma GCC pop_options -# #elif defined(_MSC_VER) -# #pragma optimize("", on) -# #endif -# """ -# ) + # self.statements.append( + # """ + # #if defined(__clang__) + # #elif defined(__GNUC__) || defined(__GNUG__) + # #pragma GCC pop_options + # #elif defined(_MSC_VER) + # #pragma optimize("", on) + # #endif + # """ + # ) self.statements.extend( ( @@ -353,12 +371,9 @@ class EarlyBoundCodeWriter: # ) "" - self.statements[self.statements.index("{string_pool_placeholder}")] = ( - """ + self.statements[self.statements.index("{string_pool_placeholder}")] = """ const std::string strings[] = {%s}; -""" - % ",".join(map(lambda s: '"%s"s' % s, self.strings)) - ) +""" % ",".join(map(lambda s: '"%s"s' % s, self.strings)) def __str__(self): return "\n".join(self.statements) @@ -380,16 +395,19 @@ class SchemaClass(codegen.Base): def wrapper(*args, **kwargs): schema_name_upper = mapping.schema.name.upper() declared_type = fn(*args, **kwargs) - if 'simple_type' in declared_type: + if "simple_type" in declared_type: pass else: - match = re.search(r'\((\w+?_[\w+]+?_\w+?)\)', declared_type) + match = re.search(r"\((\w+?_[\w+]+?_\w+?)\)", declared_type) if match: old_decl = match.group(1) - name = old_decl.lower().replace(schema_name.lower() + '_', '').replace('_type', '') + name = old_decl.lower().replace(schema_name.lower() + "_", "").replace("_type", "") idx = [n.lower() for n in x.names].index(name) - declared_type = declared_type.replace(old_decl, '%(schema_name_upper)s_types[%(idx)d]' % locals()) + declared_type = declared_type.replace( + old_decl, "%(schema_name_upper)s_types[%(idx)d]" % locals() + ) return declared_type + return wrapper if code == EarlyBoundCodeWriter else fn @transform_to_indexed diff --git a/src/ifcopenshell-python/ifcopenshell/express/templates.py b/src/ifcopenshell-python/ifcopenshell/express/templates.py index 78b69e9e58..737a5db948 100644 --- a/src/ifcopenshell-python/ifcopenshell/express/templates.py +++ b/src/ifcopenshell-python/ifcopenshell/express/templates.py @@ -129,14 +129,16 @@ simpletype_impl_is_without_supertype = "return v == %(class_name)s_type;" simpletype_impl_type = "return *((ifcopenshell::type_declaration*)%(schema_name_upper)s_types[%(index_in_schema)d]);" simpletype_impl_class = "return *((ifcopenshell::type_declaration*)%(schema_name_upper)s_types[%(index_in_schema)d]);" simpletype_impl_explicit_constructor = "data_ = e;" -simpletype_impl_constructor = ( - "data_ = new const std::weak_ptr&(%(schema_name_upper)s_types[%(index_in_schema)d]); set_attribute_value(0, v);" -) +simpletype_impl_constructor = "data_ = new const std::weak_ptr&(%(schema_name_upper)s_types[%(index_in_schema)d]); set_attribute_value(0, v);" simpletype_impl_constructor_templated = "data_ = new const std::weak_ptr&(%(schema_name_upper)s_types[%(index_in_schema)d]); set_attribute_value(0, cast_vector(v));" simpletype_impl_cast = "return get_attribute_value(0);" -simpletype_impl_cast_templated = "std::vector es = get_attribute_value(0); return cast_vector<%(underlying_type)s>(es);" +simpletype_impl_cast_templated = ( + "std::vector es = get_attribute_value(0); return cast_vector<%(underlying_type)s>(es);" +) -simpletype_impl_declaration = "return *((ifcopenshell::type_declaration*)%(schema_name_upper)s_types[%(index_in_schema)d]);" +simpletype_impl_declaration = ( + "return *((ifcopenshell::type_declaration*)%(schema_name_upper)s_types[%(index_in_schema)d]);" +) select = """%(documentation)s class IFC_SCHEMA_API %(name)s : public express::Select { @@ -226,7 +228,7 @@ const ifcopenshell::entity& %(schema_name)s::%(name)s::Class() { return *((ifcop %(schema_name)s::%(name)s %(schema_name)s::%(name)s::initialize(%(constructor_arguments)s) { %(constructor_implementation)s; return *this; } """ -# data_ = e; +# data_ = e; # data_ = new const std::weak_ptr&(%(schema_name_upper)s_types[%(index_in_schema)d]); optional_attribute_description = "/// Whether the optional attribute %s is defined for this %s" @@ -234,9 +236,7 @@ optional_attribute_description = "/// Whether the optional attribute %s is defin function = "%(return_type)s %(schema_name)s::%(class_name)s::%(name)s(%(arguments)s) { %(body)s }" const_function = "%(return_type)s %(schema_name)s::%(class_name)s::%(name)s(%(arguments)s) const { %(body)s }" constructor = "%(schema_name)s::%(class_name)s::%(class_name)s(%(arguments)s) { %(body)s }" -initialize_single_initlist = ( - "%(schema_name)s::%(class_name)s %(schema_name)s::%(class_name)s::initialize(%(arguments)s) { %(body)s; return *this; }" -) +initialize_single_initlist = "%(schema_name)s::%(class_name)s %(schema_name)s::%(class_name)s::initialize(%(arguments)s) { %(body)s; return *this; }" cast_function = "%(schema_name)s::%(class_name)s::operator %(return_type)s() const { %(body)s }" array_type = "std::vector< %(instance_type)s > /*[%(lower)s:%(upper)s]*/" @@ -258,41 +258,25 @@ optional_attr_stmt = "return !get_attribute_value(%(index)d).isNull();" get_attr_stmt = "%(null_check)s %(non_optional_type)s v = get_attribute_value(%(index)d); return v;" get_attr_stmt_enum = "%(null_check)s return %(non_optional_type)s::FromString(get_attribute_value(%(index)d));" -get_attr_stmt_entity = "%(null_check)s return ((express::Base)(get_attribute_value(%(index)d))).as<%(non_optional_type_no_pointer)s>();" +get_attr_stmt_entity = ( + "%(null_check)s return ((express::Base)(get_attribute_value(%(index)d))).as<%(non_optional_type_no_pointer)s>();" +) get_attr_stmt_array = "%(null_check)s std::vector es = get_attribute_value(%(index)d); return cast_vector<%(list_instance_type)s>(es);" get_attr_stmt_nested_array = "%(null_check)s std::vector> es = get_attribute_value(%(index)d); return cast_vector<%(list_instance_type)s>(es);" get_inverse = "return cast_vector<%(type)s>(file()->get_inverse(data()->id(), %(schema_name_upper)s_types[%(type_index)d], %(index)d));" -set_attr_stmt = ( - "%(check_optional_set_begin)sset_attribute_value(%(index)d, %(star_if_optional)sv);%(check_optional_set_else)sunset_attribute_value(%(index)d);%(check_optional_set_end)s" -) -set_attr_instance = ( - "%(check_optional_set_begin)sset_attribute_value(%(index)d, v);%(check_optional_set_else)sunset_attribute_value(%(index)d);%(check_optional_set_end)s" -) -set_attr_stmt_enum = "%(check_optional_set_begin)sset_attribute_value(%(index)d, enumeration_reference(&%(non_optional_type)s::Class(), (size_t) %(star_if_optional)sv));%(check_optional_set_else)sunset_attribute_value(%(index)d);%(check_optional_set_end)s" -set_attr_stmt_array = ( - "%(check_optional_set_begin)sset_attribute_value(%(index)d, cast_vector(%(star_if_optional)sv));%(check_optional_set_else)sunset_attribute_value(%(index)d);%(check_optional_set_end)s" -) -set_attr_stmt_nested_array = ( - "%(check_optional_set_begin)sset_attribute_value(%(index)d, cast_vector(%(star_if_optional)sv));%(check_optional_set_else)sunset_attribute_value(%(index)d);%(check_optional_set_end)s" -) +set_attr_stmt = "%(check_optional_set_begin)sset_attribute_value(%(index)d, %(star_if_optional)sv);%(check_optional_set_else)sunset_attribute_value(%(index)d);%(check_optional_set_end)s" +set_attr_instance = "%(check_optional_set_begin)sset_attribute_value(%(index)d, v);%(check_optional_set_else)sunset_attribute_value(%(index)d);%(check_optional_set_end)s" +set_attr_stmt_enum = "%(check_optional_set_begin)sset_attribute_value(%(index)d, enumeration_reference(&%(non_optional_type)s::Class(), (size_t) %(star_if_optional)sv));%(check_optional_set_else)sunset_attribute_value(%(index)d);%(check_optional_set_end)s" +set_attr_stmt_array = "%(check_optional_set_begin)sset_attribute_value(%(index)d, cast_vector(%(star_if_optional)sv));%(check_optional_set_else)sunset_attribute_value(%(index)d);%(check_optional_set_end)s" +set_attr_stmt_nested_array = "%(check_optional_set_begin)sset_attribute_value(%(index)d, cast_vector(%(star_if_optional)sv));%(check_optional_set_else)sunset_attribute_value(%(index)d);%(check_optional_set_end)s" -constructor_stmt = ( - "set_attribute_value(%(index)d, (%(name)s));" -) -constructor_stmt_enum = ( - "set_attribute_value(%(index)d, (enumeration_reference(&%(type)s::Class(),(size_t)%(name)s)));" -) -constructor_stmt_array = ( - "set_attribute_value(%(index)d, cast_vector(%(name)s));" -) -constructor_stmt_derived = ( - "" -) -constructor_stmt_instance = ( - "set_attribute_value(%(index)d, %(name)s);" -) +constructor_stmt = "set_attribute_value(%(index)d, (%(name)s));" +constructor_stmt_enum = "set_attribute_value(%(index)d, (enumeration_reference(&%(type)s::Class(),(size_t)%(name)s)));" +constructor_stmt_array = "set_attribute_value(%(index)d, cast_vector(%(name)s));" +constructor_stmt_derived = "" +constructor_stmt_instance = "set_attribute_value(%(index)d, %(name)s);" constructor_stmt_optional = " if (%(name)s) {%(stmt)s }" @@ -301,5 +285,3 @@ inverse_implementation = ' inverse_map[Type::%(type)s].insert(std::make_pair( def multi_line_comment(li): return ("/// %s" % ("\n/// ".join(li))) if len(li) else "" - - diff --git a/src/ifcopenshell-python/ifcopenshell/geom/app.py b/src/ifcopenshell-python/ifcopenshell/geom/app.py index c14886abdc..03d7ac477a 100644 --- a/src/ifcopenshell-python/ifcopenshell/geom/app.py +++ b/src/ifcopenshell-python/ifcopenshell/geom/app.py @@ -145,8 +145,7 @@ class configuration: config.set( "snippets", "print all wall ids", - self.config_encode( - """ + self.config_encode(""" ########################################################################### # A simple script that iterates over all walls in the current model # # and prints their Globally unique IDs (GUIDS) to the console window # @@ -154,15 +153,13 @@ class configuration: for wall in model.by_type("IfcWall"): print ("wall with global id: "+str(wall.GlobalId)) -""".lstrip() - ), +""".lstrip()), ) config.set( "snippets", "print properties of current selection", - self.config_encode( - """ + self.config_encode(""" ########################################################################### # A simple script that iterates over all IfcPropertySets of the currently # # selected object and prints them to the console # @@ -180,8 +177,7 @@ if selection: for prop in relDefinesByProperties.RelatingPropertyDefinition.HasProperties: print ("{:<20} :{}".format(prop.Name,prop.NominalValue.wrappedValue)) print ("\\n") -""".lstrip() - ), +""".lstrip()), ) with open(conf_file, "w") as configfile: config.write(configfile) diff --git a/src/ifcopenshell-python/ifcopenshell/geom/main.py b/src/ifcopenshell-python/ifcopenshell/geom/main.py index f1ef0d2a74..62c18b2648 100644 --- a/src/ifcopenshell-python/ifcopenshell/geom/main.py +++ b/src/ifcopenshell-python/ifcopenshell/geom/main.py @@ -547,9 +547,20 @@ def create_shape( return wrap_shape_creation( settings, ( - ifcopenshell_wrapper.create_shape(settings, inst, repr, geometry_library, *ifcopenshell.optional_logger_args(logger),) + ifcopenshell_wrapper.create_shape( + settings, + inst, + repr, + geometry_library, + *ifcopenshell.optional_logger_args(logger), + ) if repr - else ifcopenshell_wrapper.create_shape(settings, inst, geometry_library, *ifcopenshell.optional_logger_args(logger),) + else ifcopenshell_wrapper.create_shape( + settings, + inst, + geometry_library, + *ifcopenshell.optional_logger_args(logger), + ) ), ) diff --git a/src/ifcopenshell-python/ifcopenshell/ifcopenshell_wrapper.pyi b/src/ifcopenshell-python/ifcopenshell/ifcopenshell_wrapper.pyi index 5371628539..982ec2e47e 100644 --- a/src/ifcopenshell-python/ifcopenshell/ifcopenshell_wrapper.pyi +++ b/src/ifcopenshell-python/ifcopenshell/ifcopenshell_wrapper.pyi @@ -330,7 +330,6 @@ class Iterator: def unit_magnitude(self): ... def unit_name(self): ... - class OpaqueCoordinate_3: def __init__(self, *args): ... def get(self, i): ... @@ -755,13 +754,10 @@ class entity_instance(entity_instance_mixin): def declaration(self) -> declaration: ... @property def file(self) -> file: ... - def get_argument(self, *args: int | str) -> Any: ... def get_argument_index(self, a: str) -> int: ... def attribute_name(self, i: int) -> str: ... - def attribute_type( - self, *args: int | str - ) -> Literal[ + def attribute_type(self, *args: int | str) -> Literal[ "NULL", "DERIVED", "INT", @@ -915,7 +911,6 @@ class file(file_mixin): def good(self): ... @property def header(self) -> spf_header: ... - def ifcroot_type(self) -> entity: ... def initialize(self, *args): ... def key_value_store_iter(self, prefix): ... @@ -1619,9 +1614,15 @@ def set_plugin_search_paths(paths: Sequence[str]) -> None: ... def clear_plugin_search_paths() -> None: ... def clear_schemas(): ... def construct_iterator(geometry_library, settings, file, num_threads, logger=None): ... -def construct_iterator_with_include_exclude(geometry_library, settings, file, elems, include, num_threads, logger=None): ... -def construct_iterator_with_include_exclude_globalid(geometry_library, settings, file, elems, include, num_threads, logger=None): ... -def construct_iterator_with_include_exclude_id(geometry_library, settings, file, elems, include, num_threads, logger=None): ... +def construct_iterator_with_include_exclude( + geometry_library, settings, file, elems, include, num_threads, logger=None +): ... +def construct_iterator_with_include_exclude_globalid( + geometry_library, settings, file, elems, include, num_threads, logger=None +): ... +def construct_iterator_with_include_exclude_id( + geometry_library, settings, file, elems, include, num_threads, logger=None +): ... def convert_loop_to_function_item(loop): ... def create_box(*args): ... def create_epeck(*args): ... diff --git a/src/ifcopenshell-python/ifcopenshell/sql.py b/src/ifcopenshell-python/ifcopenshell/sql.py index 8bfe4d4743..932affabb3 100644 --- a/src/ifcopenshell-python/ifcopenshell/sql.py +++ b/src/ifcopenshell-python/ifcopenshell/sql.py @@ -83,7 +83,7 @@ class sqlite(file): if not Path(filepath).exists(): raise FileNotFoundError(f"File doesn't exist: {filepath}") - + # See ifcopenshell.file.file_mixin.post_init() # history, future and transaction are stored in a list so that they # can easily be shared among file instances that are the same C++ diff --git a/src/ifcopenshell-python/ifcopenshell/util/cost.py b/src/ifcopenshell-python/ifcopenshell/util/cost.py index fc3de44455..4354e49e90 100644 --- a/src/ifcopenshell-python/ifcopenshell/util/cost.py +++ b/src/ifcopenshell-python/ifcopenshell/util/cost.py @@ -355,8 +355,7 @@ def get_cost_rate( class CostValueUnserialiser: def parse(self, formula: str): - l = lark.Lark( - """start: formula + l = lark.Lark("""start: formula formula: operand (operator operand)* operand: value | category "(" formula ")" value: NUMBER? @@ -393,8 +392,7 @@ class CostValueUnserialiser: NEWLINE: (CR? LF)+ %ignore WS // Disregard spaces in text - """ - ) + """) start = l.parse(formula) return self.get_formula(start.children[0]) diff --git a/src/ifcopenshell-python/ifcopenshell/util/selector.py b/src/ifcopenshell-python/ifcopenshell/util/selector.py index 4136cb97c0..7b0f628df5 100644 --- a/src/ifcopenshell-python/ifcopenshell/util/selector.py +++ b/src/ifcopenshell-python/ifcopenshell/util/selector.py @@ -40,8 +40,7 @@ import ifcopenshell.util.shape_builder import ifcopenshell.util.system import ifcopenshell.util.unit -filter_elements_grammar = lark.Lark( - """start: filter_group +filter_elements_grammar = lark.Lark("""start: filter_group filter_group: facet_list ("+" facet_list)* "+"? facet_list: facet ("," facet)* @@ -114,11 +113,9 @@ filter_elements_grammar = lark.Lark( %ignore WS // Disregard spaces in text %ignore COMMENT // Allow /* ... */ block comments to toggle parts of a query -""" -) +""") -get_element_grammar = lark.Lark( - """start: keys +get_element_grammar = lark.Lark("""start: keys keys: key ("." key)* key: quoted_string | regex_string | unquoted_string @@ -133,11 +130,9 @@ get_element_grammar = lark.Lark( WS: /[ \\t\\f\\r\\n]/+ %ignore WS // Disregard spaces in text - """ -) + """) -format_grammar = lark.Lark( - """start: expression +format_grammar = lark.Lark("""start: expression ?expression: add_sub ?add_sub: mul_div @@ -196,8 +191,7 @@ format_grammar = lark.Lark( NEWLINE: (CR? LF)+ %ignore WS // Disregard spaces in text -""" -) +""") class FormatTransformer(lark.Transformer): diff --git a/src/ifcopenshell-python/test/api/alignment/test_add_segment_to_layout.py b/src/ifcopenshell-python/test/api/alignment/test_add_segment_to_layout.py index bb607e8605..ab33ced8b9 100644 --- a/src/ifcopenshell-python/test/api/alignment/test_add_segment_to_layout.py +++ b/src/ifcopenshell-python/test/api/alignment/test_add_segment_to_layout.py @@ -24,7 +24,6 @@ import ifcopenshell.api.context import ifcopenshell.api.unit from ifcopenshell.api.alignment._add_segment_to_layout import _add_segment_to_layout - try: ifcopenshell.file(schema="IFC4X3") IFC4X3_AVAILABLE = True diff --git a/src/ifcopenshell-python/test/api/alignment/test_add_stationing_to_alignment.py b/src/ifcopenshell-python/test/api/alignment/test_add_stationing_to_alignment.py index a0b5db0065..4a35f4379d 100644 --- a/src/ifcopenshell-python/test/api/alignment/test_add_stationing_to_alignment.py +++ b/src/ifcopenshell-python/test/api/alignment/test_add_stationing_to_alignment.py @@ -24,7 +24,6 @@ import ifcopenshell.api.context import ifcopenshell.api.unit import ifcopenshell.util.element - try: ifcopenshell.file(schema="IFC4X3") IFC4X3_AVAILABLE = True diff --git a/src/ifcopenshell-python/test/api/alignment/test_add_vertical_alignment.py b/src/ifcopenshell-python/test/api/alignment/test_add_vertical_alignment.py index e4b544b361..3ab0ca2e31 100644 --- a/src/ifcopenshell-python/test/api/alignment/test_add_vertical_alignment.py +++ b/src/ifcopenshell-python/test/api/alignment/test_add_vertical_alignment.py @@ -23,7 +23,6 @@ import ifcopenshell.api.alignment import ifcopenshell.api.context import ifcopenshell.api.unit - try: ifcopenshell.file(schema="IFC4X3") IFC4X3_AVAILABLE = True diff --git a/src/ifcopenshell-python/test/api/alignment/test_create.py b/src/ifcopenshell-python/test/api/alignment/test_create.py index 569daa4474..c3c9ab0f41 100644 --- a/src/ifcopenshell-python/test/api/alignment/test_create.py +++ b/src/ifcopenshell-python/test/api/alignment/test_create.py @@ -23,7 +23,6 @@ import ifcopenshell.api.alignment import ifcopenshell.api.context import ifcopenshell.api.unit - try: ifcopenshell.file(schema="IFC4X3_ADD2") IFC4X3_AVAILABLE = True diff --git a/src/ifcopenshell-python/test/api/alignment/test_create_as_offset_curve.py b/src/ifcopenshell-python/test/api/alignment/test_create_as_offset_curve.py index 925061ae75..bda225d52c 100644 --- a/src/ifcopenshell-python/test/api/alignment/test_create_as_offset_curve.py +++ b/src/ifcopenshell-python/test/api/alignment/test_create_as_offset_curve.py @@ -25,7 +25,6 @@ import ifcopenshell.api.unit import ifcopenshell.util import ifcopenshell.util.unit - try: ifcopenshell.file(schema="IFC4X3_ADD2") IFC4X3_AVAILABLE = True diff --git a/src/ifcopenshell-python/test/api/alignment/test_create_as_polyline.py b/src/ifcopenshell-python/test/api/alignment/test_create_as_polyline.py index 24bfaf2a0f..4dc6668a23 100644 --- a/src/ifcopenshell-python/test/api/alignment/test_create_as_polyline.py +++ b/src/ifcopenshell-python/test/api/alignment/test_create_as_polyline.py @@ -22,7 +22,6 @@ import pytest import ifcopenshell.api.alignment import ifcopenshell.api.unit - try: ifcopenshell.file(schema="IFC4X3_ADD2") IFC4X3_AVAILABLE = True diff --git a/src/ifcopenshell-python/test/api/alignment/test_create_by_pi_method.py b/src/ifcopenshell-python/test/api/alignment/test_create_by_pi_method.py index d2783a97eb..8d94506bf0 100644 --- a/src/ifcopenshell-python/test/api/alignment/test_create_by_pi_method.py +++ b/src/ifcopenshell-python/test/api/alignment/test_create_by_pi_method.py @@ -23,7 +23,6 @@ import ifcopenshell.api.alignment import ifcopenshell.api.context import ifcopenshell.api.unit - try: ifcopenshell.file(schema="IFC4X3") IFC4X3_AVAILABLE = True diff --git a/src/ifcopenshell-python/test/api/alignment/test_create_layout_segment.py b/src/ifcopenshell-python/test/api/alignment/test_create_layout_segment.py index 0bd2ac12cc..cdfcf6bfe1 100644 --- a/src/ifcopenshell-python/test/api/alignment/test_create_layout_segment.py +++ b/src/ifcopenshell-python/test/api/alignment/test_create_layout_segment.py @@ -24,7 +24,6 @@ import ifcopenshell.api.alignment import ifcopenshell.api.context import ifcopenshell.api.unit - try: ifcopenshell.file(schema="IFC4X3_ADD2") IFC4X3_AVAILABLE = True diff --git a/src/ifcopenshell-python/test/api/alignment/test_create_no_geometry.py b/src/ifcopenshell-python/test/api/alignment/test_create_no_geometry.py index 21d7023d22..9d4aee5988 100644 --- a/src/ifcopenshell-python/test/api/alignment/test_create_no_geometry.py +++ b/src/ifcopenshell-python/test/api/alignment/test_create_no_geometry.py @@ -22,7 +22,6 @@ import pytest import ifcopenshell.api.alignment import ifcopenshell.api.unit - try: ifcopenshell.file(schema="IFC4X3_ADD2") IFC4X3_AVAILABLE = True diff --git a/src/ifcopenshell-python/test/api/alignment/test_distance_along_from_station.py b/src/ifcopenshell-python/test/api/alignment/test_distance_along_from_station.py index 27757544c6..dea2c0d5c9 100644 --- a/src/ifcopenshell-python/test/api/alignment/test_distance_along_from_station.py +++ b/src/ifcopenshell-python/test/api/alignment/test_distance_along_from_station.py @@ -22,7 +22,6 @@ import ifcopenshell.api.alignment import ifcopenshell.api.context import ifcopenshell.api.unit - try: ifcopenshell.file(schema="IFC4X3") IFC4X3_AVAILABLE = True diff --git a/src/ifcopenshell-python/test/api/alignment/test_get_alignment.py b/src/ifcopenshell-python/test/api/alignment/test_get_alignment.py index 8b0397249e..ff2263fb86 100644 --- a/src/ifcopenshell-python/test/api/alignment/test_get_alignment.py +++ b/src/ifcopenshell-python/test/api/alignment/test_get_alignment.py @@ -23,7 +23,6 @@ import ifcopenshell.api.alignment import ifcopenshell.api.context import ifcopenshell.api.unit - try: ifcopenshell.file(schema="IFC4X3_ADD2") IFC4X3_AVAILABLE = True diff --git a/src/ifcopenshell-python/test/api/alignment/test_get_basis_curve.py b/src/ifcopenshell-python/test/api/alignment/test_get_basis_curve.py index e228e47089..cbb93dc442 100644 --- a/src/ifcopenshell-python/test/api/alignment/test_get_basis_curve.py +++ b/src/ifcopenshell-python/test/api/alignment/test_get_basis_curve.py @@ -23,7 +23,6 @@ import ifcopenshell.api.alignment import ifcopenshell.api.context import ifcopenshell.api.unit - try: ifcopenshell.file(schema="IFC4X3") IFC4X3_AVAILABLE = True diff --git a/src/ifcopenshell-python/test/api/alignment/test_get_curve.py b/src/ifcopenshell-python/test/api/alignment/test_get_curve.py index 5a2f5295d4..96ab986a1b 100644 --- a/src/ifcopenshell-python/test/api/alignment/test_get_curve.py +++ b/src/ifcopenshell-python/test/api/alignment/test_get_curve.py @@ -22,7 +22,6 @@ import ifcopenshell.api.alignment import ifcopenshell.api.context import ifcopenshell.api.unit - try: ifcopenshell.file(schema="IFC4X3") IFC4X3_AVAILABLE = True diff --git a/src/ifcopenshell-python/test/api/alignment/test_get_layout_curve.py b/src/ifcopenshell-python/test/api/alignment/test_get_layout_curve.py index 107729052f..84bbd82ef2 100644 --- a/src/ifcopenshell-python/test/api/alignment/test_get_layout_curve.py +++ b/src/ifcopenshell-python/test/api/alignment/test_get_layout_curve.py @@ -22,7 +22,6 @@ import ifcopenshell.api.alignment import ifcopenshell.api.context import ifcopenshell.api.unit - try: ifcopenshell.file(schema="IFC4X3") IFC4X3_AVAILABLE = True diff --git a/src/ifcopenshell-python/test/api/alignment/test_has_zero_length_segment.py b/src/ifcopenshell-python/test/api/alignment/test_has_zero_length_segment.py index 56bf630ef7..2192747b86 100644 --- a/src/ifcopenshell-python/test/api/alignment/test_has_zero_length_segment.py +++ b/src/ifcopenshell-python/test/api/alignment/test_has_zero_length_segment.py @@ -22,7 +22,6 @@ import ifcopenshell.api.alignment import ifcopenshell.api.context import ifcopenshell.api.unit - try: ifcopenshell.file(schema="IFC4X3") IFC4X3_AVAILABLE = True diff --git a/src/ifcopenshell-python/test/api/alignment/test_horizontal_layout_by_pi_method.py b/src/ifcopenshell-python/test/api/alignment/test_horizontal_layout_by_pi_method.py index 26a70825e1..8adc41124c 100644 --- a/src/ifcopenshell-python/test/api/alignment/test_horizontal_layout_by_pi_method.py +++ b/src/ifcopenshell-python/test/api/alignment/test_horizontal_layout_by_pi_method.py @@ -23,7 +23,6 @@ import ifcopenshell.api.alignment import ifcopenshell.api.context import ifcopenshell.api.unit - try: ifcopenshell.file(schema="IFC4X3") IFC4X3_AVAILABLE = True diff --git a/src/ifcopenshell-python/test/api/alignment/test_map_alignment_cant_segment.py b/src/ifcopenshell-python/test/api/alignment/test_map_alignment_cant_segment.py index 114e3b97f7..8d985eae7e 100644 --- a/src/ifcopenshell-python/test/api/alignment/test_map_alignment_cant_segment.py +++ b/src/ifcopenshell-python/test/api/alignment/test_map_alignment_cant_segment.py @@ -29,6 +29,7 @@ try: except RuntimeError: IFC4X3_AVAILABLE = False + def _BlossCurve_100_0_300_1000_1_Meter(file): design_parameters = file.createIfcAlignmentCantSegment( StartDistAlong=0.0, diff --git a/src/ifcopenshell-python/test/api/alignment/test_map_alignment_horizontal_segment.py b/src/ifcopenshell-python/test/api/alignment/test_map_alignment_horizontal_segment.py index 1321c352f9..317a59ff6e 100644 --- a/src/ifcopenshell-python/test/api/alignment/test_map_alignment_horizontal_segment.py +++ b/src/ifcopenshell-python/test/api/alignment/test_map_alignment_horizontal_segment.py @@ -33,6 +33,7 @@ try: except RuntimeError: IFC4X3_AVAILABLE = False + def _BlossCurve_100_0_300_1000_1_Meter(file): design_parameters = file.createIfcAlignmentHorizontalSegment( StartPoint=file.createIfcCartesianPoint((0.0, 0.0)), diff --git a/src/ifcopenshell-python/test/api/alignment/test_map_alignment_vertical_segment.py b/src/ifcopenshell-python/test/api/alignment/test_map_alignment_vertical_segment.py index 8f334535d1..e6e47a65a0 100644 --- a/src/ifcopenshell-python/test/api/alignment/test_map_alignment_vertical_segment.py +++ b/src/ifcopenshell-python/test/api/alignment/test_map_alignment_vertical_segment.py @@ -32,6 +32,7 @@ try: except RuntimeError: IFC4X3_AVAILABLE = False + def _CircularArc_100_0_10_0_0_0_0_5_1_Meter(file): design_parameters = file.createIfcAlignmentVerticalSegment( StartDistAlong=0.0, diff --git a/src/ifcopenshell-python/test/api/alignment/test_name_segments.py b/src/ifcopenshell-python/test/api/alignment/test_name_segments.py index fc0afd13a5..038be29727 100644 --- a/src/ifcopenshell-python/test/api/alignment/test_name_segments.py +++ b/src/ifcopenshell-python/test/api/alignment/test_name_segments.py @@ -23,7 +23,6 @@ import ifcopenshell.api.alignment import ifcopenshell.api.context import ifcopenshell.api.unit - try: ifcopenshell.file(schema="IFC4X3") IFC4X3_AVAILABLE = True diff --git a/src/ifcopenshell-python/test/api/alignment/test_referent_names.py b/src/ifcopenshell-python/test/api/alignment/test_referent_names.py index 6b83f1f767..37d299b200 100644 --- a/src/ifcopenshell-python/test/api/alignment/test_referent_names.py +++ b/src/ifcopenshell-python/test/api/alignment/test_referent_names.py @@ -22,7 +22,6 @@ import ifcopenshell.api.alignment import ifcopenshell.api.context import ifcopenshell.api.unit - try: ifcopenshell.file(schema="IFC4X3") IFC4X3_AVAILABLE = True diff --git a/src/ifcopenshell-python/test/api/alignment/test_update_curve_segment_transition_code.py b/src/ifcopenshell-python/test/api/alignment/test_update_curve_segment_transition_code.py index 71cb55c0c4..7afd13cac5 100644 --- a/src/ifcopenshell-python/test/api/alignment/test_update_curve_segment_transition_code.py +++ b/src/ifcopenshell-python/test/api/alignment/test_update_curve_segment_transition_code.py @@ -31,6 +31,7 @@ try: except RuntimeError: IFC4X3_AVAILABLE = False + def _test1(): file = ifcopenshell.file(schema="IFC4X3") project = file.createIfcProject(GlobalId=ifcopenshell.guid.new(), Name="Test") diff --git a/src/ifcopenshell-python/test/api/alignment/test_update_fallback_position.py b/src/ifcopenshell-python/test/api/alignment/test_update_fallback_position.py index 429c733899..23359df7eb 100644 --- a/src/ifcopenshell-python/test/api/alignment/test_update_fallback_position.py +++ b/src/ifcopenshell-python/test/api/alignment/test_update_fallback_position.py @@ -22,7 +22,6 @@ import ifcopenshell.api.alignment import ifcopenshell.api.context import ifcopenshell.api.unit - try: ifcopenshell.file(schema="IFC4X3") IFC4X3_AVAILABLE = True diff --git a/src/ifcopenshell-python/test/api/alignment/test_vertical_layout_by_pi_method.py b/src/ifcopenshell-python/test/api/alignment/test_vertical_layout_by_pi_method.py index 1f113729f0..605a939d7b 100644 --- a/src/ifcopenshell-python/test/api/alignment/test_vertical_layout_by_pi_method.py +++ b/src/ifcopenshell-python/test/api/alignment/test_vertical_layout_by_pi_method.py @@ -23,7 +23,6 @@ import ifcopenshell.api.alignment import ifcopenshell.api.context import ifcopenshell.api.unit - try: ifcopenshell.file(schema="IFC4X3") IFC4X3_AVAILABLE = True diff --git a/src/ifcopenshell-python/test/api/cogo/test_add_survey_point.py b/src/ifcopenshell-python/test/api/cogo/test_add_survey_point.py index 2b4e58f3d6..dbc65199f2 100644 --- a/src/ifcopenshell-python/test/api/cogo/test_add_survey_point.py +++ b/src/ifcopenshell-python/test/api/cogo/test_add_survey_point.py @@ -22,7 +22,6 @@ import ifcopenshell.api.aggregate import ifcopenshell.api.cogo import ifcopenshell.api.context - try: ifcopenshell.file(schema="IFC4X3_ADD2") IFC4X3_AVAILABLE = True diff --git a/src/ifcopenshell-python/test/api/cogo/test_assign_survey_point.py b/src/ifcopenshell-python/test/api/cogo/test_assign_survey_point.py index f998a77afb..da86d2ea1a 100644 --- a/src/ifcopenshell-python/test/api/cogo/test_assign_survey_point.py +++ b/src/ifcopenshell-python/test/api/cogo/test_assign_survey_point.py @@ -22,7 +22,6 @@ import ifcopenshell.api.aggregate import ifcopenshell.api.cogo import ifcopenshell.api.context - try: ifcopenshell.file(schema="IFC4X3_ADD2") IFC4X3_AVAILABLE = True diff --git a/src/ifcopenshell-python/test/api/cogo/test_edit_survey_point.py b/src/ifcopenshell-python/test/api/cogo/test_edit_survey_point.py index 458118a82b..f641ae0246 100644 --- a/src/ifcopenshell-python/test/api/cogo/test_edit_survey_point.py +++ b/src/ifcopenshell-python/test/api/cogo/test_edit_survey_point.py @@ -22,7 +22,6 @@ import ifcopenshell.api.aggregate import ifcopenshell.api.cogo import ifcopenshell.api.context - try: ifcopenshell.file(schema="IFC4X3_ADD2") IFC4X3_AVAILABLE = True diff --git a/src/ifcopenshell-python/test/test_entity_instance.py b/src/ifcopenshell-python/test/test_entity_instance.py index afbf300791..33bb23b4e8 100644 --- a/src/ifcopenshell-python/test/test_entity_instance.py +++ b/src/ifcopenshell-python/test/test_entity_instance.py @@ -20,6 +20,7 @@ import ifcopenshell import pytest import test.bootstrap + class TestGetInfo2(test.bootstrap.IFC4): def test_instance_attribute(self): brep = self.file.create_entity("IfcFacetedBrep") @@ -65,25 +66,27 @@ class TestGetInfo2(test.bootstrap.IFC4): "type": "IfcFacetedBrep", } + def test_equality(): f = ifcopenshell.file() g = ifcopenshell.file() - f.createIfcCartesianPoint((0., 0.)) - g.createIfcCartesianPoint((0., 0.)) + f.createIfcCartesianPoint((0.0, 0.0)) + g.createIfcCartesianPoint((0.0, 0.0)) assert f[1] == g[1] - g[1].Coordinates = (1., 0.) + g[1].Coordinates = (1.0, 0.0) assert f[1] != g[1] + def test_setting_logical(): f = ifcopenshell.file() inst = f.createIfcPresentationLayerWithStyle(LayerOn="UNKNOWN") assert inst.LayerOn == "UNKNOWN" - assert '.U.' in str(inst) + assert ".U." in str(inst) with pytest.raises(Exception): inst.LayerOn = "SOME_OTHER_STRING" inst.LayerOn = False assert inst.LayerOn is False - assert '.F.' in str(inst) + assert ".F." in str(inst) inst.LayerOn = True assert inst.LayerOn is True - assert '.T.' in str(inst) \ No newline at end of file + assert ".T." in str(inst) diff --git a/src/ifcopenshell-python/test/test_file.py b/src/ifcopenshell-python/test/test_file.py index 393dec05e9..076cd2e75a 100644 --- a/src/ifcopenshell-python/test/test_file.py +++ b/src/ifcopenshell-python/test/test_file.py @@ -21,13 +21,13 @@ import pytest import ifcopenshell import test.bootstrap - try: ifcopenshell.file(schema="IFC4X3") IFC4X3_AVAILABLE = True except RuntimeError: IFC4X3_AVAILABLE = False + class TestTransaction(test.bootstrap.IFC4): def test_that_nothing_happens_without_a_transaction(self): wall = self.file.createIfcWall() @@ -296,9 +296,10 @@ class TestFile(test.bootstrap.IFC4): g.assign_header_from(f) assert g.header.file_name.name == "test" + @pytest.mark.skipif(not IFC4X3_AVAILABLE, reason="IFC4X3 not available") def test_schema_identifier(): - f = ifcopenshell.file(schema='IFC4X3') - assert f.schema_identifier == 'IFC4X3_ADD2' - assert f.schema == 'IFC4X3' - assert f.schema_version == (4,3,2,0) + f = ifcopenshell.file(schema="IFC4X3") + assert f.schema_identifier == "IFC4X3_ADD2" + assert f.schema == "IFC4X3" + assert f.schema_version == (4, 3, 2, 0) diff --git a/src/ifcopenshell-python/test/test_parse.py b/src/ifcopenshell-python/test/test_parse.py index 4f3617ebca..d40101333e 100644 --- a/src/ifcopenshell-python/test/test_parse.py +++ b/src/ifcopenshell-python/test/test_parse.py @@ -1,5 +1,6 @@ import ifcopenshell + def test_skip_over_non_entity_instance(): data = """ ISO-10303-21; diff --git a/src/ifcopenshell-python/test/test_rules.py b/src/ifcopenshell-python/test/test_rules.py index 8a65f63556..b75271537e 100644 --- a/src/ifcopenshell-python/test/test_rules.py +++ b/src/ifcopenshell-python/test/test_rules.py @@ -8,6 +8,7 @@ import tabulate import ifcopenshell.express.rule_executor import ifcopenshell.validate + @pytest.mark.parametrize( "filename", [ @@ -45,4 +46,4 @@ def test_file(filename): if __name__ == "__main__": - pytest.main(["-sx", __file__, '--import-mode=importlib']) + pytest.main(["-sx", __file__, "--import-mode=importlib"]) diff --git a/src/ifcopenshell-python/test/test_shape_stats.py b/src/ifcopenshell-python/test/test_shape_stats.py index 7072441a9e..3ec65f609e 100644 --- a/src/ifcopenshell-python/test/test_shape_stats.py +++ b/src/ifcopenshell-python/test/test_shape_stats.py @@ -9,19 +9,20 @@ import ifcopenshell.util.shape from pathlib import Path repo_root = Path(__file__).resolve().parent.parent.parent.parent -test_files = repo_root / 'test' / 'input' / 'tests' +test_files = repo_root / "test" / "input" / "tests" settings = ifcopenshell.geom.settings() -testdata = list(csv.reader((test_files / 'data.csv').open(newline='')))[1:] +testdata = list(csv.reader((test_files / "data.csv").open(newline="")))[1:] print(testdata) + @pytest.mark.parametrize("fn,area,volume", testdata) def test_conversion(fn, area, volume): f = ifcopenshell.open(test_files / fn) - elem = next(inst for inst in f.by_type('IfcElement') if not inst.is_a('IfcOpeningElement')) - for kernel in ('manifold', 'opencascade', 'cgal'): + elem = next(inst for inst in f.by_type("IfcElement") if not inst.is_a("IfcOpeningElement")) + for kernel in ("manifold", "opencascade", "cgal"): shp = ifcopenshell.geom.create_shape(settings, elem, geometry_library=kernel) if area: assert pytest.approx(float(area), rel=0.05) == ifcopenshell.util.shape.get_area(shp.geometry) diff --git a/src/ifcopenshell-python/test/util/test_alignment.py b/src/ifcopenshell-python/test/util/test_alignment.py index af401128db..f23a85743c 100644 --- a/src/ifcopenshell-python/test/util/test_alignment.py +++ b/src/ifcopenshell-python/test/util/test_alignment.py @@ -22,7 +22,6 @@ import ifcopenshell import ifcopenshell.api.unit import ifcopenshell.util.alignment as sta - try: ifcopenshell.file(schema="IFC4X3_ADD2") IFC4X3_AVAILABLE = True diff --git a/src/ifcpatch/ifcpatch/recipes/ExtractElements.py b/src/ifcpatch/ifcpatch/recipes/ExtractElements.py index 2645bcc86e..6aba19516b 100644 --- a/src/ifcpatch/ifcpatch/recipes/ExtractElements.py +++ b/src/ifcpatch/ifcpatch/recipes/ExtractElements.py @@ -111,7 +111,7 @@ class Patcher(ifcpatch.BasePatcher): if element.is_a("IfcProject"): proj = self.new.add(element) for ctx in element.RepresentationContexts or (): - for coop in getattr(ctx, 'HasCoordinateOperation', ()): + for coop in getattr(ctx, "HasCoordinateOperation", ()): self.new.add(coop) return proj return ifcopenshell.api.project.append_asset( diff --git a/src/ifcpatch/test/test_DowngradeIndexedPolyCurve.py b/src/ifcpatch/test/test_DowngradeIndexedPolyCurve.py index adeda0b669..1375f4e241 100644 --- a/src/ifcpatch/test/test_DowngradeIndexedPolyCurve.py +++ b/src/ifcpatch/test/test_DowngradeIndexedPolyCurve.py @@ -33,9 +33,7 @@ class TestDowngradeIndexedPolyCurve(test.bootstrap.IFC4): Points=point_list, Segments=segments, ) - self.file.create_entity( - "IfcArbitraryClosedProfileDef", ProfileType="AREA", OuterCurve=curve - ) + self.file.create_entity("IfcArbitraryClosedProfileDef", ProfileType="AREA", OuterCurve=curve) return curve def test_run_without_segments(self): @@ -80,9 +78,7 @@ class TestDowngradeIndexedPolyCurve(test.bootstrap.IFC4): Points=point_list, Segments=[self.file.createIfcLineIndex((1, 2, 3, 4, 1))], ) - self.file.create_entity( - "IfcArbitraryClosedProfileDef", ProfileType="AREA", OuterCurve=curve - ) + self.file.create_entity("IfcArbitraryClosedProfileDef", ProfileType="AREA", OuterCurve=curve) ifcpatch.execute( {"input": "input.ifc", "file": self.file, "recipe": "DowngradeIndexedPolyCurve", "arguments": []} ) @@ -110,9 +106,7 @@ class TestDowngradeIndexedPolyCurve(test.bootstrap.IFC4): self.file.createIfcLineIndex((3, 4)), ], ) - self.file.create_entity( - "IfcArbitraryClosedProfileDef", ProfileType="AREA", OuterCurve=curve - ) + self.file.create_entity("IfcArbitraryClosedProfileDef", ProfileType="AREA", OuterCurve=curve) ifcpatch.execute( {"input": "input.ifc", "file": self.file, "recipe": "DowngradeIndexedPolyCurve", "arguments": []} ) diff --git a/src/ifctester/ifctester/facet.py b/src/ifctester/ifctester/facet.py index 5c05ae3cc4..18d6e56e29 100644 --- a/src/ifctester/ifctester/facet.py +++ b/src/ifctester/ifctester/facet.py @@ -701,9 +701,7 @@ class Property(Facet): if isinstance(self.baseName, str): prop = pset_props.get(self.baseName) if prop == "UNKNOWN" and next( - p - for p in self.get_properties(inst.file.by_id(pset_props["id"])) - if p.Name == self.baseName + p for p in self.get_properties(inst.file.by_id(pset_props["id"])) if p.Name == self.baseName ).NominalValue.is_a("IfcLogical"): pass elif prop is not None and prop != "": diff --git a/src/ifcviewer-web/make_sample.py b/src/ifcviewer-web/make_sample.py index 9aab28ab9d..5442ca3415 100644 --- a/src/ifcviewer-web/make_sample.py +++ b/src/ifcviewer-web/make_sample.py @@ -39,9 +39,9 @@ BAKE = HERE / "../../build-viewer/ifcviewer/sidecar_bake" # (class, name, footprint w x d in m, height in m, placement x/y/z in m) ELEMENTS = [ - ("IfcSlab", "Slab", (6.0, 6.0), 0.2, (-3.0, -3.0, 0.0)), - ("IfcWall", "Wall", (5.0, 0.3), 3.0, (-2.5, -2.5, 0.2)), - ("IfcBeam", "Beam", (0.3, 5.0), 0.3, (2.0, -2.5, 3.2)), + ("IfcSlab", "Slab", (6.0, 6.0), 0.2, (-3.0, -3.0, 0.0)), + ("IfcWall", "Wall", (5.0, 0.3), 3.0, (-2.5, -2.5, 0.2)), + ("IfcBeam", "Beam", (0.3, 5.0), 0.3, (2.0, -2.5, 3.2)), ] @@ -51,8 +51,8 @@ def build_ifc(path: Path) -> None: ifcopenshell.api.unit.assign_unit(f, length={"is_metric": True, "raw": "METERS"}) body = ifcopenshell.api.context.add_context(f, context_type="Model") body = ifcopenshell.api.context.add_context( - f, context_type="Model", context_identifier="Body", - target_view="MODEL_VIEW", parent=body) + f, context_type="Model", context_identifier="Body", target_view="MODEL_VIEW", parent=body + ) site = ifcopenshell.api.root.create_entity(f, ifc_class="IfcSite", name="Site") storey = ifcopenshell.api.root.create_entity(f, ifc_class="IfcBuildingStorey", name="Ground floor") @@ -61,30 +61,39 @@ def build_ifc(path: Path) -> None: for ifc_class, name, (w, d), height, (x, y, z) in ELEMENTS: element = ifcopenshell.api.root.create_entity(f, ifc_class=ifc_class, name=name) - ifcopenshell.api.spatial.assign_container( - f, products=[element], relating_structure=storey) + ifcopenshell.api.spatial.assign_container(f, products=[element], relating_structure=storey) # A rectangular profile extruded up — enough to be a recognisable, # distinctly-placed solid without dragging in a whole modelling stack. profile = f.create_entity( - "IfcRectangleProfileDef", ProfileType="AREA", XDim=w, YDim=d, + "IfcRectangleProfileDef", + ProfileType="AREA", + XDim=w, + YDim=d, Position=f.create_entity( - "IfcAxis2Placement2D", - Location=f.create_entity("IfcCartesianPoint", Coordinates=(w / 2, d / 2)))) + "IfcAxis2Placement2D", Location=f.create_entity("IfcCartesianPoint", Coordinates=(w / 2, d / 2)) + ), + ) solid = f.create_entity( - "IfcExtrudedAreaSolid", SweptArea=profile, Depth=height, + "IfcExtrudedAreaSolid", + SweptArea=profile, + Depth=height, Position=f.create_entity( - "IfcAxis2Placement3D", - Location=f.create_entity("IfcCartesianPoint", Coordinates=(0.0, 0.0, 0.0))), - ExtrudedDirection=f.create_entity("IfcDirection", DirectionRatios=(0.0, 0.0, 1.0))) + "IfcAxis2Placement3D", Location=f.create_entity("IfcCartesianPoint", Coordinates=(0.0, 0.0, 0.0)) + ), + ExtrudedDirection=f.create_entity("IfcDirection", DirectionRatios=(0.0, 0.0, 1.0)), + ) representation = f.create_entity( - "IfcShapeRepresentation", ContextOfItems=body, RepresentationIdentifier="Body", - RepresentationType="SweptSolid", Items=[solid]) - ifcopenshell.api.geometry.assign_representation( - f, product=element, representation=representation) + "IfcShapeRepresentation", + ContextOfItems=body, + RepresentationIdentifier="Body", + RepresentationType="SweptSolid", + Items=[solid], + ) + ifcopenshell.api.geometry.assign_representation(f, product=element, representation=representation) ifcopenshell.api.geometry.edit_object_placement( - f, product=element, - matrix=ifcopenshell.util.placement.a2p((x, y, z), (0.0, 0.0, 1.0), (1.0, 0.0, 0.0))) + f, product=element, matrix=ifcopenshell.util.placement.a2p((x, y, z), (0.0, 0.0, 1.0), (1.0, 0.0, 0.0)) + ) f.write(str(path)) diff --git a/src/wrappergen/clang_frontend.py b/src/wrappergen/clang_frontend.py index 8962e588aa..8324e5f1e7 100644 --- a/src/wrappergen/clang_frontend.py +++ b/src/wrappergen/clang_frontend.py @@ -168,7 +168,9 @@ def _is_in_allowed_headers(cursor, allowed_headers: set[Path]) -> bool: def _is_in_allowed_namespace(cpp_name: str, config: WrapperConfig) -> bool: if not config.allowed_namespaces: return True - return any(cpp_name == namespace or cpp_name.startswith(f"{namespace}::") for namespace in config.allowed_namespaces) + return any( + cpp_name == namespace or cpp_name.startswith(f"{namespace}::") for namespace in config.allowed_namespaces + ) def _matches_ignore(cpp_name: str, ignored: list[str]) -> bool: @@ -328,7 +330,7 @@ def _python_default_value( if adapter == "integer": return cpp_value if cpp_value.lstrip("-").isdigit() else None if adapter == "string": - return cpp_value if cpp_value.startswith(("\"", "'")) else None + return cpp_value if cpp_value.startswith(('"', "'")) else None if is_enum_adapter(adapter): enum_name = enum_py_names.get(adapter.split(":", 1)[1]) if enum_name is None: @@ -393,9 +395,17 @@ def _finalize_overload_names(callables: list[CallableModel]) -> None: for index, callable_model in enumerate(group, start=1): parameter_suffix = "_".join(parameter.name for parameter in callable_model.parameters) if callable_model.kind == "constructor": - callable_model.py_name = f"{callable_model.py_name}_{parameter_suffix}" if parameter_suffix else f"{callable_model.py_name}_overload_{index}" + callable_model.py_name = ( + f"{callable_model.py_name}_{parameter_suffix}" + if parameter_suffix + else f"{callable_model.py_name}_overload_{index}" + ) else: - callable_model.py_name = f"{callable_model.py_name}_with_{parameter_suffix}" if parameter_suffix else f"{callable_model.py_name}_overload_{index}" + callable_model.py_name = ( + f"{callable_model.py_name}_with_{parameter_suffix}" + if parameter_suffix + else f"{callable_model.py_name}_overload_{index}" + ) callable_model.c_name = normalize_identifier(callable_model.py_name) @@ -473,7 +483,9 @@ def _discover_methods( qualified_name = f"{owner.cpp_name}::{child.spelling}" if _matches_ignore(qualified_name, config.ignore.methods): continue - return_adapter = _resolve_return_adapter(child.result_type.spelling, scalar_adapters, enum_cursors, class_models_by_cpp) + return_adapter = _resolve_return_adapter( + child.result_type.spelling, scalar_adapters, enum_cursors, class_models_by_cpp + ) if return_adapter is None: continue parameters = _build_parameter_models(child, config, scalar_adapters, enum_cursors) @@ -535,7 +547,9 @@ def build_module_model(config: WrapperConfig) -> ModuleModel: for normalized_cpp_name, cursor in class_cursors.items(): owner = class_models_by_cpp[normalized_cpp_name] owner.callables.extend(_discover_constructors(cursor, owner, config, scalar_adapters, enum_cursors)) - owner.callables.extend(_discover_methods(cursor, owner, config, scalar_adapters, enum_cursors, class_models_by_cpp)) + owner.callables.extend( + _discover_methods(cursor, owner, config, scalar_adapters, enum_cursors, class_models_by_cpp) + ) owner.callables = _deduplicate_callables(owner.callables) _finalize_overload_names(owner.callables) diff --git a/src/wrappergen/conventions.py b/src/wrappergen/conventions.py index 68fcc24744..836edbc56d 100644 --- a/src/wrappergen/conventions.py +++ b/src/wrappergen/conventions.py @@ -126,11 +126,7 @@ def resolve_cpp_type_key(cpp_type: str, candidates: set[str]) -> str | None: if canonical in candidates: return canonical leaf = strip_pointer(canonical).rsplit("::", 1)[-1] - matches = [ - candidate - for candidate in candidates - if strip_pointer(candidate).rsplit("::", 1)[-1] == leaf - ] + matches = [candidate for candidate in candidates if strip_pointer(candidate).rsplit("::", 1)[-1] == leaf] if len(matches) == 1: return matches[0] return None diff --git a/src/wrappergen/emit.py b/src/wrappergen/emit.py index 1ffbbf8cd3..d7e610e1f8 100644 --- a/src/wrappergen/emit.py +++ b/src/wrappergen/emit.py @@ -173,7 +173,7 @@ def _class_or_enum_cpp_name(adapter: str, model: ModuleModel) -> str: def _cpp_argument(parameter: ParameterModel, model: ModuleModel) -> str: if parameter.adapter == "string": - return f"std::string({parameter.name} ? {parameter.name} : \"\")" + return f'std::string({parameter.name} ? {parameter.name} : "")' if is_enum_adapter(parameter.adapter): return f"static_cast<{_class_or_enum_cpp_name(parameter.adapter, model)}>({parameter.name})" if is_handle_adapter(parameter.adapter): @@ -315,8 +315,7 @@ def emit_c_api_header(model: ModuleModel) -> str: for variant in _all_variants(model): return_type = _return_c_type(variant.callable.return_adapter, model) parameters = ", ".join( - f"{_parameter_c_type(parameter, model)} {parameter.name}" - for parameter in variant.parameters + f"{_parameter_c_type(parameter, model)} {parameter.name}" for parameter in variant.parameters ) if variant.callable.kind == "method": self_type = f"{_class_c_type(variant.owner, model)}* handle" @@ -327,11 +326,15 @@ def emit_c_api_header(model: ModuleModel) -> str: for class_model in sequence_targets: list_prefix = f"{model.c_prefix}_{_class_c_identifier(class_model, model)}_list" lines.append(f"int {list_prefix}_size(const {_list_c_type(class_model, model)}* handle);") - lines.append(f"{_class_c_type(class_model, model)}* {list_prefix}_get(const {_list_c_type(class_model, model)}* handle, int index);") + lines.append( + f"{_class_c_type(class_model, model)}* {list_prefix}_get(const {_list_c_type(class_model, model)}* handle, int index);" + ) lines.append(f"void {list_prefix}_free({_list_c_type(class_model, model)}* handle);") lines.append("") for class_model in model.classes: - lines.append(f"void {model.c_prefix}_{_class_c_identifier(class_model, model)}_free({_class_c_type(class_model, model)}* handle);") + lines.append( + f"void {model.c_prefix}_{_class_c_identifier(class_model, model)}_free({_class_c_type(class_model, model)}* handle);" + ) lines.extend( [ "", @@ -419,8 +422,7 @@ def emit_c_api_implementation(model: ModuleModel) -> str: for variant in _all_variants(model): return_type = _return_c_type(variant.callable.return_adapter, model) parameter_list = ", ".join( - f"{_parameter_c_type(parameter, model)} {parameter.name}" - for parameter in variant.parameters + f"{_parameter_c_type(parameter, model)} {parameter.name}" for parameter in variant.parameters ) if variant.callable.kind == "method": self_type = f"{_class_c_type(variant.owner, model)}* handle" @@ -435,21 +437,31 @@ def emit_c_api_implementation(model: ModuleModel) -> str: for parameter in variant.parameters: if is_handle_adapter(parameter.adapter): lines.append(f" if ({parameter.name} == nullptr) {{") - lines.append(f' throw std::runtime_error("Null handle parameter received for {parameter.name}");') + lines.append( + f' throw std::runtime_error("Null handle parameter received for {parameter.name}");' + ) lines.append(" }") call_expression = _call_expression(variant, model) if variant.callable.kind == "constructor": lines.append(f" auto constructed_value = {call_expression};") if variant.owner.handle_kind == "shared_ptr": - lines.append(f" return new {_class_c_type(variant.owner, model)}{{ std::move(constructed_value) }};") + lines.append( + f" return new {_class_c_type(variant.owner, model)}{{ std::move(constructed_value) }};" + ) elif variant.owner.owner_cpp_name is not None: - lines.append(f" return new {_class_c_type(variant.owner, model)}{{ {{}}, std::move(constructed_value) }};") + lines.append( + f" return new {_class_c_type(variant.owner, model)}{{ {{}}, std::move(constructed_value) }};" + ) else: - lines.append(f" return new {_class_c_type(variant.owner, model)}{{ std::move(constructed_value) }};") + lines.append( + f" return new {_class_c_type(variant.owner, model)}{{ std::move(constructed_value) }};" + ) elif variant.callable.return_adapter == "string": lines.append(f" auto result = {call_expression};") lines.append(" return duplicate_string(result);") - elif variant.callable.return_adapter in {"integer", "bool", "void"} or is_enum_adapter(variant.callable.return_adapter): + elif variant.callable.return_adapter in {"integer", "bool", "void"} or is_enum_adapter( + variant.callable.return_adapter + ): if variant.callable.return_adapter == "void": lines.append(f" {call_expression};") lines.append(" return;") @@ -503,11 +515,15 @@ def emit_c_api_implementation(model: ModuleModel) -> str: ] ) if class_model.handle_kind == "shared_ptr": - lines.append(f" auto item_value = std::make_shared<{class_model.cpp_name}>(handle->value.at(static_cast(index)));") + lines.append( + f" auto item_value = std::make_shared<{class_model.cpp_name}>(handle->value.at(static_cast(index)));" + ) lines.append(f" return new {_class_c_type(class_model, model)}{{ std::move(item_value) }};") elif class_model.owner_cpp_name is not None: lines.append(f" auto item_value = handle->value.at(static_cast(index));") - lines.append(f" return new {_class_c_type(class_model, model)}{{ handle->owner, std::move(item_value) }};") + lines.append( + f" return new {_class_c_type(class_model, model)}{{ handle->owner, std::move(item_value) }};" + ) else: lines.append(f" auto item_value = handle->value.at(static_cast(index));") lines.append(f" return new {_class_c_type(class_model, model)}{{ std::move(item_value) }};") @@ -526,7 +542,9 @@ def emit_c_api_implementation(model: ModuleModel) -> str: ] ) for class_model in model.classes: - lines.append(f"void {model.c_prefix}_{_class_c_identifier(class_model, model)}_free({_class_c_type(class_model, model)}* handle) {{") + lines.append( + f"void {model.c_prefix}_{_class_c_identifier(class_model, model)}_free({_class_c_type(class_model, model)}* handle) {{" + ) lines.append(" delete handle;") lines.append("}") lines.append("") @@ -706,7 +724,9 @@ def emit_python_extension(model: ModuleModel) -> str: lines.append(f" {list_prefix}_free(result);") lines.append(" return values;") else: - raise RuntimeError(f"Unsupported return adapter in Python extension emitter: {variant.callable.return_adapter}") + raise RuntimeError( + f"Unsupported return adapter in Python extension emitter: {variant.callable.return_adapter}" + ) lines.append("}") lines.append("") lines.extend(["static PyMethodDef MODULE_METHODS[] = {"]) @@ -847,7 +867,9 @@ def emit_python_facade(model: ModuleModel) -> str: lines.append(" self._handle = handle") lines.append("") for callable_model in class_model.callables: - parameters = ", ".join(_python_parameter_signature(parameter, model) for parameter in callable_model.parameters) + parameters = ", ".join( + _python_parameter_signature(parameter, model) for parameter in callable_model.parameters + ) full_variant = _full_variant(class_model, callable_model) call_arguments = ", ".join(_python_native_argument(parameter) for parameter in callable_model.parameters) return_annotation = _python_type_for_return(callable_model.return_adapter, model) diff --git a/src/wrappergen/generate.py b/src/wrappergen/generate.py index 46ee6346bb..9ae35334ef 100644 --- a/src/wrappergen/generate.py +++ b/src/wrappergen/generate.py @@ -27,11 +27,7 @@ def _existing_directories(paths: list[Path]) -> list[str]: def _discover_headers(src_ifcparse: Path) -> list[str]: - return [ - str(path.resolve()) - for path in sorted(src_ifcparse.glob("*.h")) - if path.parent.name != "schemas" - ] + return [str(path.resolve()) for path in sorted(src_ifcparse.glob("*.h")) if path.parent.name != "schemas"] def _discover_boost_include_dirs() -> list[Path]: diff --git a/src/wrappergen/generated/ifcopenshell_experimental.py b/src/wrappergen/generated/ifcopenshell_experimental.py index 8d5d76c054..f8d6acbc70 100644 --- a/src/wrappergen/generated/ifcopenshell_experimental.py +++ b/src/wrappergen/generated/ifcopenshell_experimental.py @@ -13,6 +13,7 @@ class FileType(IntEnum): FT_UNKNOWN = _native.FT_UNKNOWN FT_AUTODETECT = _native.FT_AUTODETECT + class exception: __slots__ = ("_handle",) @@ -23,6 +24,7 @@ class exception: def with_message(message: str) -> exception: return exception(_native.exception_new_with_message(message)) + class attribute_out_of_range_exception: __slots__ = ("_handle",) @@ -33,6 +35,7 @@ class attribute_out_of_range_exception: def with_message(message: str) -> attribute_out_of_range_exception: return attribute_out_of_range_exception(_native.attribute_out_of_range_exception_new_with_message(message)) + class invalid_token_exception: __slots__ = ("_handle",) @@ -40,8 +43,15 @@ class invalid_token_exception: self._handle = handle @staticmethod - def with_token_start_token_string_expected_type(token_start: int, token_string: str, expected_type: str) -> invalid_token_exception: - return invalid_token_exception(_native.invalid_token_exception_new_with_token_start_token_string_expected_type(token_start, token_string, expected_type)) + def with_token_start_token_string_expected_type( + token_start: int, token_string: str, expected_type: str + ) -> invalid_token_exception: + return invalid_token_exception( + _native.invalid_token_exception_new_with_token_start_token_string_expected_type( + token_start, token_string, expected_type + ) + ) + class parameter_type: __slots__ = ("_handle",) @@ -61,6 +71,7 @@ class parameter_type: def is_(self, arg0: str) -> bool: return _native.parameter_type_is(self._handle, arg0) + class named_type: __slots__ = ("_handle",) @@ -76,6 +87,7 @@ class named_type: def is_(self, name: str) -> bool: return _native.named_type_is(self._handle, name) + class simple_type: __slots__ = ("_handle",) @@ -85,6 +97,7 @@ class simple_type: def as_simple_type(self) -> simple_type: return simple_type(_native.simple_type_as_simple_type(self._handle)) + class aggregation_type: __slots__ = ("_handle",) @@ -103,6 +116,7 @@ class aggregation_type: def as_aggregation_type(self) -> aggregation_type: return aggregation_type(_native.aggregation_type_as_aggregation_type(self._handle)) + class declaration: __slots__ = ("_handle",) @@ -143,6 +157,7 @@ class declaration: def schema(self) -> schema_definition: return schema_definition(_native.declaration_schema(self._handle)) + class type_declaration: __slots__ = ("_handle",) @@ -155,6 +170,7 @@ class type_declaration: def as_type_declaration(self) -> type_declaration: return type_declaration(_native.type_declaration_as_type_declaration(self._handle)) + class select_type: __slots__ = ("_handle",) @@ -167,6 +183,7 @@ class select_type: def as_select_type(self) -> select_type: return select_type(_native.select_type_as_select_type(self._handle)) + class enumeration_type: __slots__ = ("_handle",) @@ -179,6 +196,7 @@ class enumeration_type: def as_enumeration_type(self) -> enumeration_type: return enumeration_type(_native.enumeration_type_as_enumeration_type(self._handle)) + class attribute: __slots__ = ("_handle",) @@ -194,6 +212,7 @@ class attribute: def optional(self) -> bool: return _native.attribute_optional(self._handle) + class inverse_attribute: __slots__ = ("_handle",) @@ -215,6 +234,7 @@ class inverse_attribute: def attribute_reference(self) -> attribute: return attribute(_native.inverse_attribute_attribute_reference(self._handle)) + class entity: __slots__ = ("_handle",) @@ -248,6 +268,7 @@ class entity: def as_entity(self) -> entity: return entity(_native.entity_as_entity(self._handle)) + class schema_definition: __slots__ = ("_handle",) @@ -258,7 +279,9 @@ class schema_definition: return declaration(_native.schema_definition_declaration_by_name_with_name(self._handle, name)) def declaration_by_name_with_declaration_index(self, declaration_index: int) -> declaration: - return declaration(_native.schema_definition_declaration_by_name_with_declaration_index(self._handle, declaration_index)) + return declaration( + _native.schema_definition_declaration_by_name_with_declaration_index(self._handle, declaration_index) + ) def declarations(self) -> list[declaration]: return [declaration(item) for item in _native.schema_definition_declarations(self._handle)] @@ -278,6 +301,7 @@ class schema_definition: def name(self) -> str: return _native.schema_definition_name(self._handle) + class Base: __slots__ = ("_handle",) @@ -301,6 +325,7 @@ class Base: def id(self) -> int: return _native.base_id(self._handle) + class Entity: __slots__ = ("_handle",) @@ -314,6 +339,7 @@ class Entity: def get_inverse(self, attribute_name: str) -> list[Entity]: return [Entity(item) for item in _native.entity_get_inverse(self._handle, attribute_name)] + class Select: __slots__ = ("_handle",) @@ -327,6 +353,7 @@ class Select: def concrete(self) -> Base: return Base(_native.select_concrete(self._handle)) + class DeclaredType: __slots__ = ("_handle",) @@ -337,6 +364,7 @@ class DeclaredType: def create() -> DeclaredType: return DeclaredType(_native.declared_type_new()) + class full_buffer_impl: __slots__ = ("_handle",) @@ -365,6 +393,7 @@ class full_buffer_impl: _native.full_buffer_impl_drop_pages(self._handle, up_to_position) return None + class paged_file_impl: __slots__ = ("_handle",) @@ -373,7 +402,9 @@ class paged_file_impl: @staticmethod def with_path_page_size_page_capacity(path: str, page_size: int, page_capacity: int) -> paged_file_impl: - return paged_file_impl(_native.paged_file_impl_new_with_path_page_size_page_capacity(path, page_size, page_capacity)) + return paged_file_impl( + _native.paged_file_impl_new_with_path_page_size_page_capacity(path, page_size, page_capacity) + ) def size(self) -> int: return _native.paged_file_impl_size(self._handle) @@ -389,6 +420,7 @@ class paged_file_impl: _native.paged_file_impl_drop_pages(self._handle, up_to_position) return None + class pushed_sequential_impl: __slots__ = ("_handle",) @@ -409,6 +441,7 @@ class pushed_sequential_impl: _native.pushed_sequential_impl_drop_pages(self._handle, up_to_position) return None + class character_encoder: __slots__ = ("_handle",) @@ -419,6 +452,7 @@ class character_encoder: def with_input(input: str) -> character_encoder: return character_encoder(_native.character_encoder_new_with_input(input)) + class file_open_status: __slots__ = ("_handle",) @@ -427,6 +461,7 @@ class file_open_status: pass + class spf_header: __slots__ = ("_handle",) @@ -435,6 +470,7 @@ class spf_header: pass + class file: __slots__ = ("_handle",) @@ -508,6 +544,7 @@ class file: _native.file_reset_identity_cache(self._handle) return None + class global_id: __slots__ = ("_handle",)