Skip to content

Consume schema-author visibility hints + cascade strictness through nested groups#350

Draft
bdraco wants to merge 3 commits intomainfrom
feature/consume-advanced-yaml-only-flags
Draft

Consume schema-author visibility hints + cascade strictness through nested groups#350
bdraco wants to merge 3 commits intomainfrom
feature/consume-advanced-yaml-only-flags

Conversation

@bdraco
Copy link
Copy Markdown
Member

@bdraco bdraco commented May 6, 2026

What does this implement/fix?

Pairs with esphome/esphome#16267, which adds a visibility=
kwarg (cv.Visibility StrEnum) to cv.Optional /
cv.Required so the field author can mark a config_var's UI
treatment in the schema itself. The dumper emits
"visibility": "advanced" | "yaml_only" on the per-field dict
in the schema bundle this script consumes.

This PR teaches script/sync_components.py to honour the
schema's intent and apply a strictness-cascade to nested
structures.

Schema-driven flag mapping

Schema visibility Catalog flag
absent name-based heuristic decides advanced (existing behaviour)
"advanced" advanced=True
"yaml_only" hidden=True (the frontend already filters hidden)

The hand-curated _ADVANCED_BASE_KEYS / _IMPORTANT_KEYS
classifier 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_cascade walks the catalog tree once at
the top of _extract_config_entries and pushes parent strictness
down. The strictness ordering is YAML_ONLY > ADVANCED >
unset; a child can be stricter than its parent, never less
strict. Without the cascade:

  • An advanced parent block would render under a disclosure
    while its inner fields surfaced on the main form (leaky
    disclosure UX).
  • A yaml_only parent would leak controls into the editor with
    no surrounding context.

The cascade also enforces the per-entry strictness ordering: a
field with hidden=True is also forced advanced=True, since
every yaml-only field is at-least advanced by definition.

Tests

tests/test_sync_components_ui_hints.py covers:

  • Schema-driven mapping in both directions ("advanced"
    advanced=True, "yaml_only"hidden=True)
  • Heuristic fallback when visibility is absent
  • Forward-compat: an unrecognised visibility value falls back
    to the heuristic (so a future upstream level like
    "deprecated" doesn't silently disappear from the form)
  • Cascade rule: parent-ADVANCED pushes to unset children;
    parent-YAML_ONLY hides every descendant; inner
    YAML_ONLY under an ADVANCED parent stays hidden
  • Multi-level descent (grandparent forces leaf strictness)
  • Cascade no-op on a tree with no strict markers
  • config_entries: None tolerated without traversal

Forward-prep

https://schema.esphome.io won't carry the new key until the
upstream esphome PR lands and a new schema is published. Until
then, this change is a no-op — the existing heuristic-derived
advanced values stay; the cascade only mutates fields that
already have one of the strict flags from somewhere. Once the
upstream schema starts shipping visibility, the nightly
catalog 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

  • Bugfix (non-breaking change which fixes an issue) — bugfix
  • New feature (non-breaking change which adds functionality) — new-feature
  • Enhancement to an existing feature — enhancement
  • Breaking change (fix or feature that would cause existing functionality to not work as expected) — breaking-change
  • Refactor (no behaviour change) — refactor
  • Documentation only — docs
  • Maintenance / chore — maintenance
  • CI / workflow change — ci
  • Dependencies bump — dependencies

Frontend coordination

Checklist

  • The code change is tested and works locally.
  • Pre-commit hooks pass (ruff, codespell, yaml/json/python checks).
  • Tests have been added or updated under tests/ where applicable.
  • components.json has not been hand-edited (regenerate via script/sync_components.py if a sync is needed).
  • Architecture-level changes are reflected in docs/ARCHITECTURE.md and/or docs/API.md.

…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.
@bdraco bdraco added the enhancement Improvement to an existing feature label May 6, 2026
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented May 6, 2026

Merging this PR will not alter performance

✅ 9 untouched benchmarks


Comparing feature/consume-advanced-yaml-only-flags (867652e) with main (affe06d)

Open in CodSpeed

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented May 6, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.69%. Comparing base (affe06d) to head (867652e).

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##             main     #350   +/-   ##
=======================================
  Coverage   98.69%   98.69%           
=======================================
  Files          50       50           
  Lines        5652     5652           
=======================================
  Hits         5578     5578           
  Misses         74       74           
Flag Coverage Δ
py3.12 98.63% <ø> (ø)
py3.14 98.69% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.py to read advanced from the schema and apply it to the generated catalog entries.
  • Teach script/sync_components.py to read yaml_only from the schema and map it to the existing catalog hidden flag.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread script/sync_components.py Outdated
Comment thread script/sync_components.py Outdated
bdraco added 2 commits May 5, 2026 22:36
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).
@bdraco bdraco changed the title Consume schema-author UI hints (advanced, yaml_only) from upstream esphome Consume schema-author visibility hints + cascade strictness through nested groups May 6, 2026
@bdraco bdraco requested a review from Copilot May 6, 2026 03:58
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement Improvement to an existing feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants