117 lines
3.3 KiB
Python
117 lines
3.3 KiB
Python
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,
|
|
DOCS_MANUAL_CONTROL,
|
|
SET_MANUAL_CONTROL_SCHEMA,
|
|
VALIDATION_TUPLES,
|
|
apply_service_schema,
|
|
)
|
|
|
|
|
|
def _format_voluptuous_instance(instance):
|
|
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.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():
|
|
import pandas as pd
|
|
|
|
rows = []
|
|
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 = {}
|
|
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]],
|
|
alternative_docs: dict[str, str] | None = None,
|
|
):
|
|
schema = _schema_to_dict(schema)
|
|
rows = []
|
|
for k, (default, type_) in schema.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():
|
|
return _generate_service_markdown_table(apply_service_schema(), DOCS_APPLY)
|
|
|
|
|
|
def generate_set_manual_control_markdown_table():
|
|
return _generate_service_markdown_table(
|
|
SET_MANUAL_CONTROL_SCHEMA,
|
|
DOCS_MANUAL_CONTROL,
|
|
)
|