mirror of
https://github.com/basnijholt/adaptive-lighting.git
synced 2026-09-28 12:54:22 +02:00
Delete upstream docs apparatus; rewrite README for the fork
The CDiT fork is single-household and was carrying an entire upstream docs/ mkdocs site documenting features the fork has removed (sleep mode, take-over-control, brightness_mode selector, YAML config). The README mostly auto-generated from those pages via markdown-code-runner. What's gone: - docs/ — all 11 pages + assets + run_markdown_code_runner.py - .github/workflows/docs.yml — zensical+shinylive GitHub Pages build - .github/workflows/markdown-code-runner.yml — auto-edit of README from docs/ - .github/update-services.py / update-strings.py — would clobber the hand-edited services.yaml / strings.json - scripts/update-generated-content — orchestrator for the above - custom_components/adaptive_lighting/_docs_helpers.py + docs_gen.py — only used by the deleted markdown-code-runner - zensical.toml — docs-site config - "docs" dependency group in pyproject.toml (markdown-code-runner, shinylive, zensical, etc.) + lock regenerated What's new: - README.md rewritten to describe the fork's actual surface — 3 switches, 4 number entities, 3 sensor entities per profile, 2 services (apply + change_switch_settings), entry-only setup, UI tuning, sun source. Preserves the existing "What's new in 2.1" / "2.2" block quotes. - webapp/README.md annotated to flag the Shiny simulator models the upstream curve (with brightness_mode, sleep mode, etc.) and does not reflect the fork. - CLAUDE.md command table no longer references update-generated-content. Sensor.py + test_sensor_platform.py: incidental black reformat from the lint pass (multi-arg function calls split per line). Tests still pass (123/123). Lint clean. Sensors implementation unchanged.
This commit is contained in:
parent
1b21228b30
commit
bba0ef31d8
31 changed files with 165 additions and 2999 deletions
|
|
@ -1,122 +0,0 @@
|
|||
from typing import Any
|
||||
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
import pandas as pd
|
||||
import voluptuous as vol
|
||||
from homeassistant.helpers import selector
|
||||
|
||||
from .const import (
|
||||
DOCS,
|
||||
DOCS_APPLY,
|
||||
VALIDATION_TUPLES,
|
||||
apply_service_schema,
|
||||
)
|
||||
|
||||
# Stubs for upstream docs sections that no longer exist in the CDiT fork.
|
||||
# The docs generator script reads these by name; provide empty placeholders
|
||||
# so the script does not crash. The section in the rendered README will be
|
||||
# empty and can be deleted from the template separately.
|
||||
DOCS_MANUAL_CONTROL: dict[str, str] = {}
|
||||
SET_MANUAL_CONTROL_SCHEMA = None
|
||||
|
||||
|
||||
def _format_voluptuous_instance(instance: vol.All) -> str:
|
||||
coerce_type = None
|
||||
min_val = None
|
||||
max_val = None
|
||||
|
||||
for validator in instance.validators:
|
||||
if isinstance(validator, vol.Coerce):
|
||||
coerce_type = validator.type.__name__
|
||||
elif isinstance(validator, vol.Clamp | vol.Range):
|
||||
min_val = validator.min
|
||||
max_val = validator.max
|
||||
|
||||
if min_val is not None and max_val is not None:
|
||||
return f"`{coerce_type}` {min_val}-{max_val}"
|
||||
if min_val is not None:
|
||||
return f"`{coerce_type} > {min_val}`"
|
||||
if max_val is not None:
|
||||
return f"`{coerce_type} < {max_val}`"
|
||||
return f"`{coerce_type}`"
|
||||
|
||||
|
||||
def _type_to_str(type_: Any) -> str: # noqa: PLR0911
|
||||
"""Convert a (voluptuous) type to a string."""
|
||||
if type_ == cv.entity_ids:
|
||||
return "list of `entity_id`s"
|
||||
if type_ in (bool, int, float, str):
|
||||
return f"`{type_.__name__}`"
|
||||
if type_ == cv.boolean:
|
||||
return "bool"
|
||||
if isinstance(type_, vol.All):
|
||||
return _format_voluptuous_instance(type_)
|
||||
if isinstance(type_, vol.Any):
|
||||
return " or ".join(_type_to_str(t) for t in type_.validators)
|
||||
if isinstance(type_, vol.In):
|
||||
return f"one of `{type_.container}`"
|
||||
if isinstance(type_, selector.SelectSelector):
|
||||
return f"one of `{type_.config['options']}`"
|
||||
if isinstance(type_, selector.ColorRGBSelector):
|
||||
return "RGB color"
|
||||
msg = f"Unknown type: {type_}"
|
||||
raise ValueError(msg)
|
||||
|
||||
|
||||
def generate_config_markdown_table() -> str:
|
||||
rows: list[dict[str, str]] = []
|
||||
for k, default, type_ in VALIDATION_TUPLES:
|
||||
description = DOCS[k]
|
||||
row = {
|
||||
"Variable name": f"`{k}`",
|
||||
"Description": description,
|
||||
"Default": f"`{default}`",
|
||||
"Type": _type_to_str(type_),
|
||||
}
|
||||
rows.append(row)
|
||||
|
||||
df = pd.DataFrame(rows)
|
||||
return df.to_markdown(index=False)
|
||||
|
||||
|
||||
def _schema_to_dict(schema: vol.Schema) -> dict[str, tuple[Any, Any]]:
|
||||
result: dict[str, tuple[Any, Any]] = {}
|
||||
for key, value in schema.schema.items():
|
||||
if isinstance(key, vol.Optional):
|
||||
default_value = key.default
|
||||
result[key.schema] = (default_value, value)
|
||||
return result
|
||||
|
||||
|
||||
def _generate_service_markdown_table(
|
||||
schema: dict[str, tuple[Any, Any]] | vol.Schema,
|
||||
alternative_docs: dict[str, str] | None = None,
|
||||
) -> str:
|
||||
schema_dict = _schema_to_dict(schema) if isinstance(schema, vol.Schema) else schema
|
||||
rows: list[dict[str, str]] = []
|
||||
for k, (default, type_) in schema_dict.items():
|
||||
if alternative_docs is not None and k in alternative_docs:
|
||||
description = alternative_docs[k]
|
||||
else:
|
||||
description = DOCS[k]
|
||||
row = {
|
||||
"Service data attribute": f"`{k}`",
|
||||
"Description": description,
|
||||
"Required": "✅" if default == vol.UNDEFINED else "❌",
|
||||
"Type": _type_to_str(type_),
|
||||
}
|
||||
rows.append(row)
|
||||
|
||||
df = pd.DataFrame(rows)
|
||||
return df.to_markdown(index=False)
|
||||
|
||||
|
||||
def generate_apply_markdown_table() -> str:
|
||||
return _generate_service_markdown_table(apply_service_schema(), DOCS_APPLY)
|
||||
|
||||
|
||||
def generate_set_manual_control_markdown_table() -> str:
|
||||
return _generate_service_markdown_table(
|
||||
SET_MANUAL_CONTROL_SCHEMA,
|
||||
DOCS_MANUAL_CONTROL,
|
||||
)
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
"""Documentation generation utilities for Adaptive Lighting.
|
||||
|
||||
Provides functions to transform content for the documentation site.
|
||||
Used by markdown-code-runner to generate documentation pages from README content.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
|
||||
|
||||
def _transform_readme_links(content: str) -> str:
|
||||
"""Transform README internal links to docs site links."""
|
||||
# Map README anchors to doc pages
|
||||
link_map = {
|
||||
"#gear-configuration": "configuration.md",
|
||||
"#memo-options": "configuration.md#all-options",
|
||||
"#hammer_and_wrench-services": "services.md",
|
||||
"#adaptive_lightingapply": "services.md#adaptive_lightingapply",
|
||||
"#adaptive_lightingset_manual_control": "services.md#adaptive_lightingset_manual_control",
|
||||
"#adaptive_lightingchange_switch_settings": "services.md#adaptive_lightingchange_switch_settings",
|
||||
"#robot-automation-examples": "automation-examples.md",
|
||||
"#sos-troubleshooting": "troubleshooting.md",
|
||||
"#exclamation-common-problems--solutions": "troubleshooting.md#common-problems-solutions",
|
||||
"#bar_chart-graphs": "advanced/brightness-modes.md#graphs",
|
||||
"#bulb-features": "index.md#features",
|
||||
"#control_knobs-regain-manual-control": "advanced/manual-control.md",
|
||||
"#eyes-see-also": "see-also.md",
|
||||
}
|
||||
|
||||
for old_link, new_link in link_map.items():
|
||||
content = content.replace(f"]({old_link})", f"]({new_link})")
|
||||
|
||||
# Remove ToC link pattern [[ToC](#...)]
|
||||
return re.sub(r"\[\[ToC\]\([^)]+\)\]", "", content)
|
||||
|
|
@ -112,9 +112,7 @@ class AdaptiveOutputSensor(SensorEntity):
|
|||
def _handle_outputs_updated(self) -> None:
|
||||
"""Read this sensor's value from the cache and write state."""
|
||||
outputs = (
|
||||
self._hass.data.get(DOMAIN, {})
|
||||
.get(self._entry.entry_id, {})
|
||||
.get("outputs")
|
||||
self._hass.data.get(DOMAIN, {}).get(self._entry.entry_id, {}).get("outputs")
|
||||
)
|
||||
if not outputs:
|
||||
# Early signal (e.g., setup race) — leave state as unknown.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue