Consume schema-author visibility hints + cascade strictness through nested groups#350
Consume schema-author visibility hints + cascade strictness through nested groups#350
Conversation
…phome Pairs with esphome/esphome#16267, which adds ``advanced`` and ``yaml_only`` kwargs to ``cv.Optional`` / ``cv.Required`` so component authors can mark a field's UI treatment at the schema level. The dumper emits the flags onto the per-field dict in the schema bundle this script consumes. When an entry's raw schema dict carries either flag, honour the schema's intent over the existing name-based heuristic: * ``advanced: true`` → entry's ``advanced`` flag set, regardless of what ``_classify_advanced`` would have decided. * ``yaml_only: true`` → entry's ``hidden`` flag set so the frontend's existing ``hidden`` skip applies. Maps the new schema concept onto the catalog's existing field — no consumer-facing surface change. The heuristic stays as the fallback for the long tail of fields the schema doesn't yet annotate; as more fields opt in upstream, the heuristic's hand-curated key sets (``_ADVANCED_BASE_KEYS``, etc.) can shrink toward zero. Forward-prep: the schema bundle on https://schema.esphome.io won't carry the flags until the upstream esphome PR lands and a new schema is published. Until then, this script change is a no-op; the existing heuristic-derived ``advanced`` values stay.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #350 +/- ##
=======================================
Coverage 98.69% 98.69%
=======================================
Files 50 50
Lines 5652 5652
=======================================
Hits 5578 5578
Misses 74 74
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
Updates the component catalog sync script to consume new per-field UI hints emitted by the upstream ESPHome schema bundle, allowing schema authors to control whether a field is treated as “advanced” or only configurable via YAML.
Changes:
- Teach
script/sync_components.pyto readadvancedfrom the schema and apply it to the generated catalog entries. - Teach
script/sync_components.pyto readyaml_onlyfrom the schema and map it to the existing cataloghiddenflag.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Two real concerns flagged by Copilot: 1. The previous shape (``schema_advanced or _classify_advanced(...)``) was additive — when the upstream dumper one day starts emitting ``advanced: false`` to express "schema author opted out of the advanced section", the OR would still let the heuristic flip it on. Switch to keying off ``"advanced" in raw`` so a present-with- value-False on the schema honours the schema instead. Today the dumper only emits the key when True; this change is forward-prep for the polarity-symmetric case. 2. No test coverage for the new flag mapping. Add ``tests/test_sync_components_ui_hints.py`` with seven cases: schema-True wins over heuristic-False, schema-False overrides heuristic-True, no flag falls back to heuristic, yaml_only maps to hidden, hidden defaults to False when absent, both flags are independent, and advanced=False + yaml_only=True is a legal combination (the flags are distinct dimensions).
Pairs with the upstream esphome refactor that replaces the two ``advanced`` / ``yaml_only`` booleans with a single ``visibility`` ``StrEnum`` kwarg. The schema dump now emits ``"visibility": "advanced" | "yaml_only"`` instead of two booleans. Two behaviour changes on the consumer side: 1. Read ``visibility`` (string) instead of two booleans. The schema's value drives ``advanced`` / ``hidden`` directly when present; the name-based heuristic stays as the fallback for the long tail of fields the schema doesn't yet annotate. 2. Apply a cascade pass after leaf conversion. ``YAML_ONLY`` is strictly stronger than ``ADVANCED``, which is strictly stronger than no setting; a stricter parent forces every descendant at-least as strict. Without the cascade, an ``advanced`` parent block could render under a disclosure while its inner fields surfaced on the main form (leaky disclosure UX), and a ``yaml_only`` parent could leak controls with no surrounding context. The cascade walks the tree once at the top of ``_extract_config_entries`` and merges per-entry: each field's own ``hidden`` flag also implies ``advanced`` (per the strictness ordering), and parents push their state down through ``config_entries`` recursion. Test coverage matrix in ``tests/test_sync_components_ui_hints.py`` covers schema-driven + heuristic + cascade interactions across flat fields, nested groups, multi-level descent, and edge cases (unrecognised visibility string, ``config_entries: None``, inner-yaml_only-under-advanced-parent).
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
What does this implement/fix?
Pairs with esphome/esphome#16267, which adds a
visibility=kwarg (
cv.VisibilityStrEnum) tocv.Optional/cv.Requiredso the field author can mark a config_var's UItreatment in the schema itself. The dumper emits
"visibility": "advanced" | "yaml_only"on the per-field dictin the schema bundle this script consumes.
This PR teaches
script/sync_components.pyto honour theschema's intent and apply a strictness-cascade to nested
structures.
Schema-driven flag mapping
visibilityadvanced(existing behaviour)"advanced"advanced=True"yaml_only"hidden=True(the frontend already filtershidden)The hand-curated
_ADVANCED_BASE_KEYS/_IMPORTANT_KEYSclassifier stays as the fallback for the long tail of fields the
schema doesn't yet annotate; as upstream adoption grows, the
heuristic shrinks toward zero.
Cascade pass
A new
_apply_visibility_cascadewalks the catalog tree once atthe top of
_extract_config_entriesand pushes parent strictnessdown. The strictness ordering is
YAML_ONLY>ADVANCED>unset; a child can be stricter than its parent, never less
strict. Without the cascade:
advancedparent block would render under a disclosurewhile its inner fields surfaced on the main form (leaky
disclosure UX).
yaml_onlyparent would leak controls into the editor withno surrounding context.
The cascade also enforces the per-entry strictness ordering: a
field with
hidden=Trueis also forcedadvanced=True, sinceevery yaml-only field is at-least advanced by definition.
Tests
tests/test_sync_components_ui_hints.pycovers:"advanced"→advanced=True,"yaml_only"→hidden=True)visibilityis absentvisibilityvalue falls backto the heuristic (so a future upstream level like
"deprecated"doesn't silently disappear from the form)ADVANCEDpushes to unset children;parent-
YAML_ONLYhides every descendant; innerYAML_ONLYunder anADVANCEDparent stays hiddenconfig_entries: Nonetolerated without traversalForward-prep
https://schema.esphome.iowon't carry the new key until theupstream esphome PR lands and a new schema is published. Until
then, this change is a no-op — the existing heuristic-derived
advancedvalues stay; the cascade only mutates fields thatalready have one of the strict flags from somewhere. Once the
upstream schema starts shipping
visibility, the nightlycatalog sync will naturally pick it up and the catalog diff
will land in the auto-PR.
Related issue or feature (if applicable):
Types of changes
bugfixnew-featureenhancementbreaking-changerefactordocsmaintenancecidependenciesFrontend coordination
Checklist
ruff,codespell, yaml/json/python checks).tests/where applicable.components.jsonhas not been hand-edited (regenerate viascript/sync_components.pyif a sync is needed).docs/ARCHITECTURE.mdand/ordocs/API.md.