diff --git a/esphome/config_validation.py b/esphome/config_validation.py index 7b68681ed2..2e7a4e5677 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -63,7 +63,7 @@ from esphome.jsonschema import ( jschema_registry, jschema_typed, ) - +from esphome.util import parse_esphome_version from esphome.voluptuous_schema import _Schema from esphome.yaml_util import make_data_base @@ -1742,6 +1742,19 @@ def require_framework_version( return validator +def require_esphome_version(year, month, patch): + def validator(value): + esphome_version = parse_esphome_version() + if esphome_version < (year, month, patch): + requires_version = f"{year}.{month}.{patch}" + raise Invalid( + f"This component requires at least ESPHome version {requires_version}" + ) + return value + + return validator + + @contextmanager def suppress_invalid(): try: diff --git a/esphome/util.py b/esphome/util.py index b2ba0c22c3..9975f5fc72 100644 --- a/esphome/util.py +++ b/esphome/util.py @@ -1,3 +1,4 @@ +import typing from typing import Union, List import collections @@ -242,6 +243,13 @@ def is_dev_esphome_version(): return "dev" in const.__version__ +def parse_esphome_version() -> typing.Tuple[int, int, int]: + match = re.match(r"^(\d+).(\d+).(\d+)(-dev\d*|b\d*)?$", const.__version__) + if match is None: + raise ValueError(f"Failed to parse ESPHome version '{const.__version__}'") + return int(match.group(1)), int(match.group(2)), int(match.group(3)) + + # Custom OrderedDict with nicer repr method for debugging class OrderedDict(collections.OrderedDict): def __repr__(self):