1
0
mirror of https://github.com/esphome/esphome.git synced 2025-09-24 14:12:24 +01:00

[core] Replace magic coroutine priority numbers with self-documenting CoroPriority enum (#10518)

This commit is contained in:
J. Nick Koston
2025-09-02 16:41:50 -05:00
committed by GitHub
parent f286bc57f3
commit d1276dc6df
57 changed files with 404 additions and 117 deletions

View File

@@ -42,7 +42,10 @@ Here everything is combined in `yield` expressions. You await other coroutines u
the last `yield` expression defines what is returned.
"""
from __future__ import annotations
from collections.abc import Awaitable, Callable, Generator, Iterator
import enum
import functools
import heapq
import inspect
@@ -53,6 +56,79 @@ from typing import Any
_LOGGER = logging.getLogger(__name__)
class CoroPriority(enum.IntEnum):
"""Execution priority stages for ESPHome code generation.
Higher values run first. These stages ensure proper dependency
resolution during code generation.
"""
# Platform initialization - must run first
# Examples: esp32, esp8266, rp2040
PLATFORM = 1000
# Network infrastructure setup
# Examples: network (201)
NETWORK = 201
# Network transport layer
# Examples: async_tcp (200)
NETWORK_TRANSPORT = 200
# Core system components
# Examples: esphome core, most entity base components (cover, update, datetime,
# valve, alarm_control_panel, lock, event, binary_sensor, button, climate, fan,
# light, media_player, number, select, sensor, switch, text_sensor, text),
# microphone, speaker, audio_dac, touchscreen, stepper
CORE = 100
# Diagnostic and debugging systems
# Examples: logger (90)
DIAGNOSTICS = 90
# Status and monitoring systems
# Examples: status_led (80)
STATUS = 80
# Communication protocols and services
# Examples: web_server_base (65), captive_portal (64), wifi (60), ethernet (60),
# mdns (55), ota_updates (54), web_server_ota (52)
COMMUNICATION = 60
# Application-level services
# Examples: safe_mode (50)
APPLICATION = 50
# Web and UI services
# Examples: web_server (40)
WEB = 40
# Automations and user logic
# Examples: esphome core automations (30)
AUTOMATION = 30
# Bus and peripheral setup
# Examples: i2c (1)
BUS = 1
# Standard component priority (default)
# Components without explicit priority run at 0
COMPONENT = 0
# Components that need others to be registered first
# Examples: globals (-100)
LATE = -100
# Platform-specific workarounds and fixes
# Examples: add_arduino_global_workaround (-999), esp8266 pin states (-999)
WORKAROUNDS = -999
# Final setup that requires all components to be registered
# Examples: add_includes, _add_platformio_options, _add_platform_defines (all -1000),
# esp32_ble_tracker feature defines (-1000)
FINAL = -1000
def coroutine(func: Callable[..., Any]) -> Callable[..., Awaitable[Any]]:
"""Decorator to apply to methods to convert them to ESPHome coroutines."""
if getattr(func, "_esphome_coroutine", False):
@@ -95,15 +171,16 @@ def coroutine(func: Callable[..., Any]) -> Callable[..., Awaitable[Any]]:
return coro
def coroutine_with_priority(priority: float):
def coroutine_with_priority(priority: float | CoroPriority):
"""Decorator to apply to functions to convert them to ESPHome coroutines.
:param priority: priority with which to schedule the coroutine, higher priorities run first.
Can be a float or a CoroPriority enum value.
"""
def decorator(func):
coro = coroutine(func)
coro.priority = priority
coro.priority = float(priority)
return coro
return decorator
@@ -173,7 +250,7 @@ class _Task:
self.iterator = iterator
self.original_function = original_function
def with_priority(self, priority: float) -> "_Task":
def with_priority(self, priority: float) -> _Task:
return _Task(priority, self.id_number, self.iterator, self.original_function)
@property