WillTools 2026-09-09 -- clean snapshot of the development repo for review
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:
2026-09-09 08:35:15 -05:00
commit 25592fa6c2
406 changed files with 223435 additions and 0 deletions
@@ -0,0 +1,175 @@
# -*- coding: utf-8 -*-
"""The pyRevit YAML reader, faked HONESTLY -- strings only, like the real one.
`pyrevit/coreutils/yaml.py` is a YamlDotNet wrapper and its ENTIRE scalar
conversion is:
elif isinstance(ynode, libyaml.RepresentationModel.YamlScalarNode):
return ynode.Value
Every scalar therefore comes back as a STRING: `1.5` as `'1.5'`, `true` as
`'true'`, and `null` as the four characters `'null'`. Two modules in this tree
read through it -- `knowledge._merge_file`, which runs `_coerce()` afterwards,
and `ticketpage._read_yaml`, which until 2026-08-31 did not.
WHY THIS FILE EXISTS: THE OLD FAKE WAS KINDER THAN PRODUCTION.
The suite's only pyRevit YAML double was backed by `vibe.yamlkit`, which TYPES
its scalars -- `_parse_scalar` turns 'null' into None. So every guard in this
repository that reads YAML read it through a typing reader while the button
read it through one that types nothing. The master checklist consequently
arrived at the button with `CHECKLIST_FOR_ENGINEER` derived EMPTY (5.3 and 5.5
red on the owner's screen) and the WORD 'null' in 37 of 39 rows' reason slots
-- with the whole suite green, because the corruption is a non-empty string and
so satisfies the very guard that demands a sentence from every row.
A double that is more forgiving than the thing it doubles is not a test double,
it is a blindfold. Everything faking this reader now comes here, so the
kindness cannot creep back one test file at a time.
AND THE SAME LESSON, AGAIN, ON DUPLICATE KEYS (2026-09-01).
YamlDotNet -- what pyRevit's reader is -- REFUSES a mapping key stated twice:
`load_as_dict` raises `Duplicate key`. This fake read through `yamlkit`, which
takes the last one and says nothing, so the production reader and the double
disagreed about whether a file loads AT ALL. A nested duplicate in one plant
file therefore threw away that entire 255KB layer inside Revit -- every
parameter role None, the sweep enumerating 0 assemblies, every report normal --
and nothing on the host could reproduce it. `_UniqueKeyLoader` below closes
that: this reader now raises on a duplicate at any depth, exactly like the one
it doubles. `knowledge._merge_file` is the code that had to learn to say so,
and `tools/knowledgelint.py` is the same strictness as a host-side gate.
WHY NOT conftest.py: `panellift/tests/` has a conftest of its own, so a
whole-repo `python -m pytest` leaves exactly one module named `conftest`
importable and it is whichever pytest reached first. `from conftest import ...`
inside a test file is a coin flip; this name is unique in the tree.
"""
# pylint: disable=import-error,invalid-name
import io
import sys
import types
def stringify_like_yamldotnet(node):
"""Every scalar as text, the way the real pyRevit reader returns it.
Maps and sequences keep their shape; only the leaves change.
"""
if isinstance(node, dict):
return dict([(k, stringify_like_yamldotnet(v))
for k, v in node.items()])
if isinstance(node, (list, tuple)):
return [stringify_like_yamldotnet(v) for v in node]
if node is None:
return u'null'
if node is True:
return u'true'
if node is False:
return u'false'
if isinstance(node, bytes):
return node.decode('utf-8')
if isinstance(node, str):
return node
return u'{0}'.format(node)
def install_pyrevit_yaml(monkeypatch, load_as_dict):
"""Register a fake `pyrevit.coreutils.yaml` exposing `load_as_dict`.
The readers under test import the module chain and swallow every
exception, so a half-registered chain makes the read quietly do nothing
and the test passes for the wrong reason. All three names are set.
"""
yaml_mod = types.ModuleType('pyrevit.coreutils.yaml')
yaml_mod.load_as_dict = load_as_dict
coreutils = types.ModuleType('pyrevit.coreutils')
coreutils.yaml = yaml_mod
pyrevit = types.ModuleType('pyrevit')
pyrevit.coreutils = coreutils
monkeypatch.setitem(sys.modules, 'pyrevit', pyrevit)
monkeypatch.setitem(sys.modules, 'pyrevit.coreutils', coreutils)
monkeypatch.setitem(sys.modules, 'pyrevit.coreutils.yaml', yaml_mod)
return yaml_mod
class DuplicateKeyError(ValueError):
"""A mapping key stated twice, refused the way YamlDotNet refuses it.
A `ValueError` so a caller guarding a parse with `except ValueError` still
catches it, and its own class so a test can name exactly this failure.
The message leads with the same two words the real reader's does --
`Duplicate key` -- because that string is what a person sees in Self Check
and in `config_problems()`, and a double that produces a different one
teaches the wrong thing about what to search for.
"""
def raise_on_duplicate_keys(text, path=None):
"""Refuse `text` if any mapping in it states a key twice, at any depth.
PyYAML with the standard unique-key loader recipe: `construct_mapping` is
called once per mapping node, so nesting is covered without walking the
tree by hand, and `key_node.start_mark` gives the line and column of the
SECOND statement of the key -- the one to delete.
PyYAML is used only as the duplicate DETECTOR; the value still comes back
from `yamlkit`, whose grammar is the one the rest of this fake is built
on. So a document PyYAML cannot parse for some other reason is passed
through here rather than refused: a grammar disagreement between PyYAML
and yamlkit is not evidence about YamlDotNet, and this checker has exactly
one question. The cost is honest and worth writing down -- a duplicate key
inside a document PyYAML rejects for an unrelated reason is not seen here.
`tools/knowledgelint.py` reports that case, because it strict-parses the
real files with PyYAML and nothing else.
"""
import yaml
class _UniqueKeyLoader(yaml.SafeLoader):
pass
def _construct_mapping(loader, node, deep=False):
seen = set()
for key_node, _value_node in node.value:
key = loader.construct_object(key_node, deep=deep)
try:
duplicate = key in seen
except TypeError: # an unhashable key: not our
continue # question, and not our error
if duplicate:
mark = key_node.start_mark
raise DuplicateKeyError(
'Duplicate key: {0!r} at line {1}, column {2}{3} -- a '
'mapping may state a key only once.'.format(
key, mark.line + 1, mark.column + 1,
' of {0}'.format(path) if path else ''))
seen.add(key)
return yaml.SafeLoader.construct_mapping(loader, node, deep=deep)
_UniqueKeyLoader.add_constructor(
yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG, _construct_mapping)
try:
yaml.load(text, Loader=_UniqueKeyLoader)
except DuplicateKeyError:
raise
except Exception: # see the docstring: not this question
return
def strings_only_yaml_reader():
"""`load_as_dict` with yamlkit's grammar and YamlDotNet's (absent) types.
Strict about duplicate keys as well as untyped about scalars, because the
reader it stands in for is both. See the module docstring.
"""
from vibe import yamlkit
def load_as_dict(path):
handle = io.open(str(path), 'r', encoding='utf-8')
try:
text = handle.read()
finally:
handle.close()
raise_on_duplicate_keys(text, path)
return stringify_like_yamldotnet(yamlkit.parse(text))
return load_as_dict