Apply an API function to each item in a list, substituting {field} placeholders. Opens the model once, applies the mutation for every item, and returns a summary. The caller is responsible for saving the model. Args: model: The open IFC model (mutated in place). module:
(
model: ifcopenshell.file,
module: str,
function: str,
raw_kwargs_template: dict[str, str],
items: list[dict],
)
| 31 | |
| 32 | |
| 33 | def run_foreach( |
| 34 | model: ifcopenshell.file, |
| 35 | module: str, |
| 36 | function: str, |
| 37 | raw_kwargs_template: dict[str, str], |
| 38 | items: list[dict], |
| 39 | ) -> dict: |
| 40 | """Apply an API function to each item in a list, substituting {field} placeholders. |
| 41 | |
| 42 | Opens the model once, applies the mutation for every item, and returns a summary. |
| 43 | The caller is responsible for saving the model. |
| 44 | |
| 45 | Args: |
| 46 | model: The open IFC model (mutated in place). |
| 47 | module: API module name (e.g. "root"). |
| 48 | function: Function name (e.g. "remove_product"). |
| 49 | raw_kwargs_template: Arg templates with {field} placeholders, e.g. {"product": "{id}"}. |
| 50 | items: List of dicts (e.g. from ifcquery select output). |
| 51 | |
| 52 | Returns: |
| 53 | {"ok": True, "count": N, "errors": []} on full success, |
| 54 | {"ok": False, "count": N, "errors": [{...}]} if any item failed. |
| 55 | """ |
| 56 | errors = [] |
| 57 | count = 0 |
| 58 | |
| 59 | for i, item in enumerate(items): |
| 60 | if not isinstance(item, dict): |
| 61 | errors.append({"index": i, "item": item, "error": "item is not a dict"}) |
| 62 | continue |
| 63 | |
| 64 | substituted = {k: _substitute(v, item) for k, v in raw_kwargs_template.items()} |
| 65 | result = run_api(model, module, function, substituted) |
| 66 | |
| 67 | if result["ok"]: |
| 68 | count += 1 |
| 69 | else: |
| 70 | errors.append({"index": i, "item": item, "error": result["error"]}) |
| 71 | |
| 72 | return { |
| 73 | "ok": len(errors) == 0, |
| 74 | "count": count, |
| 75 | "errors": errors, |
| 76 | } |