WillTools 2026-09-09 -- clean snapshot of the development repo for review
ci / test (push) Successful in 6m14s
ci / test (push) Successful in 6m14s
History-free snapshot of the private development repository at 77a82eb. Code, docs and the public catalogue only: no plant or job knowledge layers, no client, job or producer names (tools/scrub.py clean against the widened term list; a second word-level grep clean). The intro deck is left out because its slide images cannot be checked for job drawings.
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Panel Analysis: the pure merge rule for the model-measured pre-fill.
|
||||
|
||||
`script.py`'s `_reads_for` reads three separate things off one panel --
|
||||
`pa_supports.read_supports`, `pa_lifters.read_lifters`, `pa_reinf.read_
|
||||
reinforcement_prefill` -- each returning its own small dict of form-field
|
||||
values (or {}, defensively, when it could not measure anything). This module
|
||||
holds the one rule for folding all three into the button's running `reads`
|
||||
dict, kept apart from `script.py` because that file imports the Revit API at
|
||||
module scope and cannot be imported under `pytest` on host CPython (see
|
||||
`tests/conftest.py`'s docstring) -- so the part that is pure logic, and
|
||||
therefore worth a fast host test, lives here instead.
|
||||
|
||||
THE RULE, in one sentence: everywhere else in `_reads_for` a value already
|
||||
read off the piece wins over a model guess (`setdefault` -- fill only what is
|
||||
still blank); `OVERRIDE_KEYS` are the exception, because for those keys the
|
||||
NEW read *is* the measurement and anything already sitting in `reads` is a
|
||||
weaker guess from an earlier, cruder pass -- `mild_as` is the clearest case:
|
||||
`_assembly_reinforcement`'s old marks-list (a bare comma list of piece marks)
|
||||
is worth less than `pa_reinf.rebar_prefill`'s `(bar size, type name)` summary
|
||||
with a real total area, so the new value has to win even though `reads`
|
||||
already carries something under that key.
|
||||
|
||||
`None` never overwrites anything, for any key, override or not -- a module
|
||||
that could not measure something says so by leaving the key out (or handing
|
||||
back `None`), never by asserting a blank.
|
||||
"""
|
||||
|
||||
# The new measurement wins over whatever is already in `reads`, blank or not.
|
||||
# Every other key follows plain `setdefault` -- only a still-empty slot gets
|
||||
# filled. See the module docstring for why `mild_as` is here: the new
|
||||
# `(bar size, type name)` summary from `pa_reinf.rebar_prefill` outranks the
|
||||
# old marks-list `_assembly_reinforcement` may already have written under the
|
||||
# same key.
|
||||
OVERRIDE_KEYS = ('supports_ft', 'face_lifters', 'edge_lifters',
|
||||
'ps_rows', 'mild_as')
|
||||
|
||||
|
||||
def merge_model_reads(reads, parts):
|
||||
"""Fold `parts` into `reads` IN PLACE, per `OVERRIDE_KEYS`, and return it.
|
||||
|
||||
`parts` is either one dict or a list/tuple of dicts (`pa_supports.
|
||||
read_supports`'s, `pa_lifters.read_lifters`'s, `pa_reinf.read_
|
||||
reinforcement_prefill`'s, in whatever order the caller has them handy --
|
||||
order only matters between two dicts that both carry the same key, which
|
||||
none of the three do today). A `None` value in any part is skipped
|
||||
outright; it never counts as "the model answered" and never overwrites
|
||||
an existing value OR fills a blank.
|
||||
|
||||
Returns `reads` (the same object, mutated) so a caller can chain it, but
|
||||
the mutation is the real effect -- this is not written to be used as a
|
||||
pure expression.
|
||||
"""
|
||||
if isinstance(parts, dict):
|
||||
parts = [parts]
|
||||
for part in (parts or []):
|
||||
if not part:
|
||||
continue
|
||||
for key, value in part.items():
|
||||
if value is None:
|
||||
continue
|
||||
if key in OVERRIDE_KEYS or reads.get(key) is None:
|
||||
reads[key] = value
|
||||
return reads
|
||||
Reference in New Issue
Block a user