diff --git a/helpers/sp/context.py b/helpers/sp/context.py index 74a550e..4329a30 100644 --- a/helpers/sp/context.py +++ b/helpers/sp/context.py @@ -42,3 +42,35 @@ def find_bodies(self, pattern, component=None): results = [] _collect_bodies_recursive(comp, pattern, results) return results + + +# ── Standalone body lookups (no DesignContext instance needed) ─────────────── +# These are the ONE site for raw `bRepBodies` iteration / name-based body +# identification. Templates call these instead of rolling their own +# `_all_bodies`/`_find_body` loops, so the fragile bits (name collisions after +# mirror/pattern renames, proxy vs native) live in a single hardenable place. + +def bodies_in(comp, recursive=False): + """All bodies in a component. Shallow by default (the component's own + bodies — matches the old per-template `_all_bodies`); pass recursive=True to + walk descendants.""" + if recursive: + out = [] + _collect_bodies_recursive(comp, "*", out) + return out + return [comp.bRepBodies.item(i) for i in range(comp.bRepBodies.count)] + + +def find_body(name, comp): + """Find a body by exact name within `comp` (checks the component's own + bodies first, then descendants). Canonical replacement for local + `_find_body` helpers.""" + return _find_body_recursive(comp, name) + + +def find_bodies(pattern, comp): + """Bodies whose name matches a glob `pattern` within `comp` (walks + descendants).""" + out = [] + _collect_bodies_recursive(comp, pattern, out) + return out diff --git a/woodworking/templates/bed_rail_fastener.py b/woodworking/templates/bed_rail_fastener.py index d43264a..0de7c86 100644 --- a/woodworking/templates/bed_rail_fastener.py +++ b/woodworking/templates/bed_rail_fastener.py @@ -76,8 +76,8 @@ def _get_or_import(part_id, step_file): return None tmpl_occ = imported[0][0] tmpl_occ.isLightBulbOn = False - for bi in range(tmpl_occ.component.bRepBodies.count): - tmpl_occ.component.bRepBodies.item(bi).isVisible = False + for b in sp.bodies_in(tmpl_occ.component): + b.isVisible = False _plate_cache[part_id] = tmpl_occ hw_mgr._hardware_occurrences.append((tmpl_occ, root)) return hw_mgr._copy_from_template(tmpl_occ, root) diff --git a/woodworking/templates/domino.py b/woodworking/templates/domino.py index 43e38a9..65a91be 100644 --- a/woodworking/templates/domino.py +++ b/woodworking/templates/domino.py @@ -500,10 +500,5 @@ def four_corners(comp, plane, center, long_axis, long_expr, short_expr, def _find_body(comp, name): - """Find body by name in component (non-recursive, fast).""" - for i in range(comp.bRepBodies.count): - b = comp.bRepBodies.item(i) - if b.name == name: - return b - # Fall back to recursive search - return sp.DesignContext().find_body(name, comp) + """Find body by name in component (delegates to sp.find_body).""" + return sp.find_body(name, comp) diff --git a/woodworking/templates/drawbore.py b/woodworking/templates/drawbore.py index cfdf133..db3fe2d 100644 --- a/woodworking/templates/drawbore.py +++ b/woodworking/templates/drawbore.py @@ -281,5 +281,6 @@ def blind(comp, tenon_plane, tenon_plane_offset, tenon_origin, tenon_size, def _all_bodies(comp): - """Get all bodies in a component.""" - return [comp.bRepBodies.item(i) for i in range(comp.bRepBodies.count)] + """All bodies in a component (delegates to sp.bodies_in — the single site + for raw bRepBodies iteration).""" + return sp.bodies_in(comp) diff --git a/woodworking/templates/scarf_joint.py b/woodworking/templates/scarf_joint.py index d178ebf..6882824 100644 --- a/woodworking/templates/scarf_joint.py +++ b/woodworking/templates/scarf_joint.py @@ -241,11 +241,7 @@ def kanawa_tsugi(comp, body_a, body_b, splice_face, features.append(split_feat) # Find the two halves (everything except the two timbers) - halves = [] - for i in range(comp.bRepBodies.count): - b = comp.bRepBodies.item(i) - if b != body_a and b != body_b: - halves.append(b) + halves = [b for b in sp.bodies_in(comp) if b != body_a and b != body_b] # Sort: half closer to body_a = half_a a_center = _body_center(body_a, grain_axis) diff --git a/woodworking/templates/splayed_legs.py b/woodworking/templates/splayed_legs.py index 9654f8a..7f1e7f8 100644 --- a/woodworking/templates/splayed_legs.py +++ b/woodworking/templates/splayed_legs.py @@ -357,9 +357,5 @@ def define_stretcher_params(params, name, height_expr, def _find_body(comp, name): - """Find body by name in component.""" - for i in range(comp.bRepBodies.count): - b = comp.bRepBodies.item(i) - if b.name == name: - return b - return sp.DesignContext().find_body(name, comp) + """Find body by name in component (delegates to sp.find_body).""" + return sp.find_body(name, comp) diff --git a/woodworking/templates/tusk_tenon.py b/woodworking/templates/tusk_tenon.py index 6bae1d1..4a7f376 100644 --- a/woodworking/templates/tusk_tenon.py +++ b/woodworking/templates/tusk_tenon.py @@ -321,4 +321,4 @@ def _s(v): def _all_bodies(comp): - return [comp.bRepBodies.item(i) for i in range(comp.bRepBodies.count)] + return sp.bodies_in(comp) # single site for raw bRepBodies iteration