Compare commits

...
6 changed files with 59 additions and 48 deletions
+9 -17
View File
@@ -1,29 +1,23 @@
import esphome.codegen as cg
from esphome.components import button
import esphome.config_validation as cv
from esphome.const import (
CONF_DEVICE_CLASS,
CONF_ENTITY_CATEGORY,
CONF_ICON,
CONF_ID,
CONF_SETUP_PRIORITY,
CONF_SOURCE_ID,
)
from esphome.core.entity_helpers import inherit_property_from
from esphome.types import ConfigType
from .. import copy_ns
CopyButton = copy_ns.class_("CopyButton", button.Button, cg.Component)
CONFIG_SCHEMA = (
button.button_schema(CopyButton)
.extend(
CONFIG_SCHEMA = cv.All(
# The copy button is no longer a Component
cv.ignored_key(CONF_SETUP_PRIORITY, removed_in="2027.5.0", component="copy"),
button.button_schema(button.ApplyButton).extend(
{
cv.Required(CONF_SOURCE_ID): cv.use_id(button.Button),
}
)
.extend(cv.COMPONENT_SCHEMA)
),
)
FINAL_VALIDATE_SCHEMA = cv.All(
@@ -34,8 +28,6 @@ FINAL_VALIDATE_SCHEMA = cv.All(
async def to_code(config: ConfigType) -> None:
var = cg.new_Pvariable(config[CONF_ID])
await button.register_button(var, config)
await cg.register_component(var, config)
await cg.add_variable(var.set_source, config[CONF_SOURCE_ID])
await button.sub_buttons(config, parent=config[CONF_SOURCE_ID]).create(
config, None, apply="press()"
)
@@ -1,12 +0,0 @@
#include "copy_button.h"
#include "esphome/core/log.h"
namespace esphome::copy {
ESPHOME_LOG_TAG(TAG, "copy.button");
void CopyButton::dump_config() { LOG_BUTTON("", "Copy Button", this); }
void CopyButton::press_action() { source_->press(); }
} // namespace esphome::copy
@@ -1,19 +0,0 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/components/button/button.h"
namespace esphome::copy {
class CopyButton final : public button::Button, public Component {
public:
void set_source(button::Button *source) { source_ = source; }
void dump_config() override;
protected:
void press_action() override;
button::Button *source_;
};
} // namespace esphome::copy
+24
View File
@@ -2927,3 +2927,27 @@ def rename_key(
return config
return validator
def ignored_key(key: str, *, removed_in: str, component: str | None = None):
"""Drop ``key``, which no longer has any effect, with a warning that it will be rejected.
Place it before the schema in ``cv.All`` so existing configs keep validating until
``removed_in``. Input that is not a dictionary is returned unchanged.
"""
def validator(config: dict) -> dict:
if not isinstance(config, dict) or key not in config:
return config
prefix = f"[{component}] " if component else ""
_LOGGER.warning(
"%s'%s' has no effect and can be removed. It will be rejected in %s",
prefix,
key,
removed_in,
)
config = config.copy()
del config[key]
return config
return validator
+8
View File
@@ -24,3 +24,11 @@ select:
- platform: copy
source_id: test_select
name: Test Select Copy
button:
- platform: template
id: copy_source_button
name: Source Button
- platform: copy
source_id: copy_source_button
name: Button Copy
@@ -3153,6 +3153,24 @@ def test_rename_key_absent() -> None:
assert cv.rename_key("old", "new")({"other": 5}) == {"other": 5}
def test_ignored_key_drops_key_with_warning(caplog: pytest.LogCaptureFixture) -> None:
config = {"setup_priority": 600.0, "name": "x"}
result = cv.ignored_key("setup_priority", removed_in="2027.5.0", component="copy")(
config
)
assert result == {"name": "x"}
assert config == {"setup_priority": 600.0, "name": "x"}
assert "[copy] 'setup_priority' has no effect" in caplog.text
assert "2027.5.0" in caplog.text
def test_ignored_key_absent_or_not_a_dict(caplog: pytest.LogCaptureFixture) -> None:
validator = cv.ignored_key("setup_priority", removed_in="2027.5.0")
assert validator({"name": "x"}) == {"name": "x"}
assert validator("text") == "text"
assert caplog.text == ""
@pytest.mark.parametrize("value", ["an_id", 1, None, ["old"]])
def test_rename_key_non_dict_passes_through(value: object) -> None:
assert cv.rename_key("old", "new")(value) == value