Merge branch 'dev' into hassfest_trigger_target

This commit is contained in:
Abílio Costa 2025-07-16 17:03:34 +01:00 committed by GitHub
commit 0050c4ae89
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 85 additions and 71 deletions

View File

@ -43,104 +43,117 @@ def unique_field_validator(fields: Any) -> Any:
return fields return fields
CORE_INTEGRATION_FIELD_SCHEMA = vol.Schema( CUSTOM_INTEGRATION_EXTRA_SCHEMA_DICT = {
{ vol.Optional("description"): str,
vol.Optional("example"): exists, vol.Optional("name"): str,
vol.Optional("default"): exists, }
vol.Optional("required"): bool,
vol.Optional("advanced"): bool,
vol.Optional(CONF_SELECTOR): selector.validate_selector, CORE_INTEGRATION_NOT_TARGETED_FIELD_SCHEMA_DICT = {
vol.Optional("filter"): { vol.Optional("example"): exists,
vol.Exclusive("attribute", "field_filter"): { vol.Optional("default"): exists,
vol.Required(str): [vol.All(str, service.validate_attribute_option)], vol.Optional("required"): bool,
}, vol.Optional("advanced"): bool,
vol.Exclusive("supported_features", "field_filter"): [ vol.Optional(CONF_SELECTOR): selector.validate_selector,
vol.All(str, service.validate_supported_feature) }
],
FIELD_FILTER_SCHEMA_DICT = {
vol.Optional("filter"): {
vol.Exclusive("attribute", "field_filter"): {
vol.Required(str): [vol.All(str, service.validate_attribute_option)],
}, },
vol.Exclusive("supported_features", "field_filter"): [
vol.All(str, service.validate_supported_feature)
],
} }
) }
CORE_INTEGRATION_SECTION_SCHEMA = vol.Schema(
{ def _field_schema(targeted: bool, custom: bool) -> vol.Schema:
"""Return the field schema."""
schema_dict = CORE_INTEGRATION_NOT_TARGETED_FIELD_SCHEMA_DICT.copy()
# Filters are only allowed for targeted services because they rely on the presence
# of a `target` field to determine the scope of the service call. Non-targeted
# services do not have a `target` field, making filters inapplicable.
if targeted:
schema_dict |= FIELD_FILTER_SCHEMA_DICT
if custom:
schema_dict |= CUSTOM_INTEGRATION_EXTRA_SCHEMA_DICT
return vol.Schema(schema_dict)
def _section_schema(targeted: bool, custom: bool) -> vol.Schema:
"""Return the section schema."""
schema_dict = {
vol.Optional("collapsed"): bool, vol.Optional("collapsed"): bool,
vol.Required("fields"): vol.Schema({str: CORE_INTEGRATION_FIELD_SCHEMA}), vol.Required("fields"): vol.Schema(
{
str: _field_schema(targeted, custom),
}
),
} }
)
CUSTOM_INTEGRATION_FIELD_SCHEMA = CORE_INTEGRATION_FIELD_SCHEMA.extend( if custom:
{ schema_dict |= CUSTOM_INTEGRATION_EXTRA_SCHEMA_DICT
vol.Optional("description"): str,
vol.Optional("name"): str,
}
)
CUSTOM_INTEGRATION_SECTION_SCHEMA = vol.Schema( return vol.Schema(schema_dict)
{
vol.Optional("description"): str,
vol.Optional("name"): str, def _service_schema(targeted: bool, custom: bool) -> vol.Schema:
vol.Optional("collapsed"): bool, """Return the service schema."""
vol.Required("fields"): vol.Schema({str: CUSTOM_INTEGRATION_FIELD_SCHEMA}), schema_dict = {
vol.Optional("fields"): vol.All(
vol.Schema(
{
str: vol.Any(
_field_schema(targeted, custom),
_section_schema(targeted, custom),
),
}
),
unique_field_validator,
)
} }
)
if targeted:
schema_dict[vol.Required("target")] = vol.Any(
selector.TargetSelector.CONFIG_SCHEMA, None
)
if custom:
schema_dict |= CUSTOM_INTEGRATION_EXTRA_SCHEMA_DICT
return vol.Schema(schema_dict)
CORE_INTEGRATION_SERVICE_SCHEMA = vol.Any( CORE_INTEGRATION_SERVICE_SCHEMA = vol.Any(
vol.Schema( _service_schema(targeted=True, custom=False),
{ _service_schema(targeted=False, custom=False),
vol.Optional("target"): vol.Any(
selector.TargetSelector.CONFIG_SCHEMA, None
),
vol.Optional("fields"): vol.All(
vol.Schema(
{
str: vol.Any(
CORE_INTEGRATION_FIELD_SCHEMA,
CORE_INTEGRATION_SECTION_SCHEMA,
)
}
),
unique_field_validator,
),
}
),
None, None,
) )
CUSTOM_INTEGRATION_SERVICE_SCHEMA = vol.Any( CUSTOM_INTEGRATION_SERVICE_SCHEMA = vol.Any(
vol.Schema( _service_schema(targeted=True, custom=True),
{ _service_schema(targeted=False, custom=True),
vol.Optional("description"): str,
vol.Optional("name"): str,
vol.Optional("target"): vol.Any(
selector.TargetSelector.CONFIG_SCHEMA, None
),
vol.Optional("fields"): vol.All(
vol.Schema(
{
str: vol.Any(
CUSTOM_INTEGRATION_FIELD_SCHEMA,
CUSTOM_INTEGRATION_SECTION_SCHEMA,
)
}
),
unique_field_validator,
),
}
),
None, None,
) )
CORE_INTEGRATION_SERVICES_SCHEMA = vol.Schema( CORE_INTEGRATION_SERVICES_SCHEMA = vol.Schema(
{ {
vol.Remove(vol.All(str, service.starts_with_dot)): object, vol.Remove(vol.All(str, service.starts_with_dot)): object,
cv.slug: CORE_INTEGRATION_SERVICE_SCHEMA, cv.slug: CORE_INTEGRATION_SERVICE_SCHEMA,
} }
) )
CUSTOM_INTEGRATION_SERVICES_SCHEMA = vol.Schema( CUSTOM_INTEGRATION_SERVICES_SCHEMA = vol.Schema(
{cv.slug: CUSTOM_INTEGRATION_SERVICE_SCHEMA} {cv.slug: CUSTOM_INTEGRATION_SERVICE_SCHEMA}
) )
VALIDATE_AS_CUSTOM_INTEGRATION = { VALIDATE_AS_CUSTOM_INTEGRATION = {
# Adding translations would be a breaking change # Adding translations would be a breaking change
"foursquare", "foursquare",

View File

@ -199,7 +199,8 @@ async def test_send_message_with_data(hass: HomeAssistant, tmp_path: Path) -> No
}, },
}, },
), ),
] ],
any_order=True,
) )