mirror of
https://github.com/esphome/esphome.git
synced 2026-07-10 08:55:36 +00:00
Merge remote-tracking branch 'origin/ci/lazy-import-offenders' into integration
This commit is contained in:
@@ -39,7 +39,7 @@ jobs:
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- name: Generate cache-key
|
||||
id: cache-key
|
||||
run: echo key="${{ hashFiles('requirements.txt', 'requirements_test.txt', '.pre-commit-config.yaml') }}" >> $GITHUB_OUTPUT
|
||||
run: echo key="${{ hashFiles('requirements.txt', 'requirements_dev.txt', 'requirements_test.txt', '.pre-commit-config.yaml') }}" >> $GITHUB_OUTPUT
|
||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||
id: python
|
||||
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||||
@@ -58,7 +58,7 @@ jobs:
|
||||
python -m venv venv
|
||||
. venv/bin/activate
|
||||
python --version
|
||||
pip install -r requirements.txt -r requirements_test.txt pre-commit
|
||||
pip install -r requirements.txt -r requirements_dev.txt -r requirements_test.txt pre-commit
|
||||
pip install -e .
|
||||
|
||||
pylint:
|
||||
@@ -369,7 +369,7 @@ jobs:
|
||||
echo "binary=$BINARY" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Run CodSpeed benchmarks
|
||||
uses: CodSpeedHQ/action@658a901452bb54c799643e060733b7afe9121b8d # v4.14.0
|
||||
uses: CodSpeedHQ/action@c381be0bfd20e844fb45594f6aa182ffcd94545c # v4.15.0
|
||||
with:
|
||||
run: ${{ steps.build.outputs.binary }}
|
||||
mode: simulation
|
||||
|
||||
@@ -146,5 +146,6 @@ sdkconfig.*
|
||||
|
||||
/components
|
||||
/managed_components
|
||||
/dependencies.lock
|
||||
|
||||
api-docs/
|
||||
|
||||
@@ -78,43 +78,43 @@ void BME680Component::setup() {
|
||||
}
|
||||
|
||||
// Read calibration
|
||||
uint8_t cal1[25];
|
||||
if (!this->read_bytes(BME680_REGISTER_COEFF1, cal1, 25)) {
|
||||
uint8_t coeff1[25];
|
||||
if (!this->read_bytes(BME680_REGISTER_COEFF1, coeff1, 25)) {
|
||||
this->mark_failed();
|
||||
return;
|
||||
}
|
||||
uint8_t cal2[16];
|
||||
if (!this->read_bytes(BME680_REGISTER_COEFF2, cal2, 16)) {
|
||||
uint8_t coeff2[16];
|
||||
if (!this->read_bytes(BME680_REGISTER_COEFF2, coeff2, 16)) {
|
||||
this->mark_failed();
|
||||
return;
|
||||
}
|
||||
|
||||
this->calibration_.t1 = cal2[9] << 8 | cal2[8];
|
||||
this->calibration_.t2 = cal1[2] << 8 | cal1[1];
|
||||
this->calibration_.t3 = cal1[3];
|
||||
this->calibration_.t1 = coeff2[9] << 8 | coeff2[8];
|
||||
this->calibration_.t2 = coeff1[2] << 8 | coeff1[1];
|
||||
this->calibration_.t3 = coeff1[3];
|
||||
|
||||
this->calibration_.h1 = cal2[2] << 4 | (cal2[1] & 0x0F);
|
||||
this->calibration_.h2 = cal2[0] << 4 | cal2[1] >> 4;
|
||||
this->calibration_.h3 = cal2[3];
|
||||
this->calibration_.h4 = cal2[4];
|
||||
this->calibration_.h5 = cal2[5];
|
||||
this->calibration_.h6 = cal2[6];
|
||||
this->calibration_.h7 = cal2[7];
|
||||
this->calibration_.h1 = coeff2[2] << 4 | (coeff2[1] & 0x0F);
|
||||
this->calibration_.h2 = coeff2[0] << 4 | coeff2[1] >> 4;
|
||||
this->calibration_.h3 = coeff2[3];
|
||||
this->calibration_.h4 = coeff2[4];
|
||||
this->calibration_.h5 = coeff2[5];
|
||||
this->calibration_.h6 = coeff2[6];
|
||||
this->calibration_.h7 = coeff2[7];
|
||||
|
||||
this->calibration_.p1 = cal1[6] << 8 | cal1[5];
|
||||
this->calibration_.p2 = cal1[8] << 8 | cal1[7];
|
||||
this->calibration_.p3 = cal1[9];
|
||||
this->calibration_.p4 = cal1[12] << 8 | cal1[11];
|
||||
this->calibration_.p5 = cal1[14] << 8 | cal1[13];
|
||||
this->calibration_.p6 = cal1[16];
|
||||
this->calibration_.p7 = cal1[15];
|
||||
this->calibration_.p8 = cal1[20] << 8 | cal1[19];
|
||||
this->calibration_.p9 = cal1[22] << 8 | cal1[21];
|
||||
this->calibration_.p10 = cal1[23];
|
||||
this->calibration_.p1 = coeff1[6] << 8 | coeff1[5];
|
||||
this->calibration_.p2 = coeff1[8] << 8 | coeff1[7];
|
||||
this->calibration_.p3 = coeff1[9];
|
||||
this->calibration_.p4 = coeff1[12] << 8 | coeff1[11];
|
||||
this->calibration_.p5 = coeff1[14] << 8 | coeff1[13];
|
||||
this->calibration_.p6 = coeff1[16];
|
||||
this->calibration_.p7 = coeff1[15];
|
||||
this->calibration_.p8 = coeff1[20] << 8 | coeff1[19];
|
||||
this->calibration_.p9 = coeff1[22] << 8 | coeff1[21];
|
||||
this->calibration_.p10 = coeff1[23];
|
||||
|
||||
this->calibration_.gh1 = cal2[14];
|
||||
this->calibration_.gh2 = cal2[12] << 8 | cal2[13];
|
||||
this->calibration_.gh3 = cal2[15];
|
||||
this->calibration_.gh1 = coeff2[14];
|
||||
this->calibration_.gh2 = coeff2[12] << 8 | coeff2[13];
|
||||
this->calibration_.gh3 = coeff2[15];
|
||||
|
||||
uint8_t temp_var = 0;
|
||||
if (!this->read_byte(0x02, &temp_var)) {
|
||||
|
||||
@@ -29,7 +29,7 @@ class DemoAlarmControlPanel : public AlarmControlPanel, public Component {
|
||||
protected:
|
||||
void control(const AlarmControlPanelCall &call) override {
|
||||
auto state = call.get_state().value_or(ACP_STATE_DISARMED);
|
||||
auto code = call.get_code();
|
||||
const auto &code = call.get_code();
|
||||
switch (state) {
|
||||
case ACP_STATE_ARMED_AWAY:
|
||||
if (this->get_requires_code_to_arm()) {
|
||||
|
||||
@@ -462,7 +462,7 @@ template<typename... Ts> class HttpRequestSendAction : public Action<Ts...> {
|
||||
this->request_headers_.push_back({key, value});
|
||||
}
|
||||
|
||||
void add_collect_header(const char *value) { this->lower_case_collect_headers_.push_back(value); }
|
||||
void add_collect_header(const char *value) { this->lower_case_collect_headers_.emplace_back(value); }
|
||||
|
||||
void init_json(size_t count) { this->json_.init(count); }
|
||||
void add_json(const char *key, TemplatableValue<std::string, Ts...> value) { this->json_.push_back({key, value}); }
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
from operator import itemgetter
|
||||
|
||||
from esphome import config_validation as cv
|
||||
import esphome.codegen as cg
|
||||
from esphome.const import (
|
||||
@@ -11,6 +13,7 @@ from esphome.core import ID
|
||||
from esphome.cpp_generator import MockObj
|
||||
|
||||
from .defines import CONF_GRADIENTS, CONF_OPA, LV_DITHER, add_define, add_warning
|
||||
from .helpers import add_lv_use
|
||||
from .lv_validation import lv_color, lv_percentage, opacity
|
||||
from .lvcode import lv
|
||||
from .types import lv_color_t, lv_gradient_t, lv_opa_t
|
||||
@@ -50,6 +53,7 @@ GRADIENT_SCHEMA = cv.ensure_list(
|
||||
|
||||
|
||||
async def gradients_to_code(config):
|
||||
add_lv_use("gradient")
|
||||
max_stops = 2
|
||||
if any(CONF_DITHER in x for x in config.get(CONF_GRADIENTS, ())):
|
||||
add_warning(
|
||||
@@ -58,7 +62,7 @@ async def gradients_to_code(config):
|
||||
for gradient in config.get(CONF_GRADIENTS, ()):
|
||||
var = MockObj(cg.new_Pvariable(gradient[CONF_ID]), "->")
|
||||
idbase = gradient[CONF_ID].id
|
||||
stops = gradient[CONF_STOPS]
|
||||
stops = sorted(gradient[CONF_STOPS], key=itemgetter(CONF_POSITION))
|
||||
max_stops = max(max_stops, len(stops))
|
||||
if gradient[CONF_DIRECTION].startswith("VER"):
|
||||
lv.grad_vertical_init(var)
|
||||
|
||||
@@ -864,6 +864,32 @@ void lv_scale_draw_event_cb(lv_event_t *e, int16_t range_start, int16_t range_en
|
||||
}
|
||||
#endif // USE_LVGL_SCALE
|
||||
|
||||
#ifdef USE_LVGL_GRADIENT
|
||||
/**
|
||||
*
|
||||
* @param dsc The gradient descriptor containing the color stops
|
||||
* @param pos The current position to calculate the color for
|
||||
* @return The color for the given position
|
||||
*/
|
||||
|
||||
lv_color_t lv_grad_calculate_color(const lv_grad_dsc_t *dsc, int32_t pos) {
|
||||
if (dsc->stops_count == 0)
|
||||
return lv_color_black();
|
||||
if (dsc->stops_count == 1 || pos <= dsc->stops[0].frac)
|
||||
return dsc->stops[0].color;
|
||||
if (pos >= dsc->stops[dsc->stops_count - 1].frac)
|
||||
return dsc->stops[dsc->stops_count - 1].color;
|
||||
int i = 1;
|
||||
while (i < dsc->stops_count && dsc->stops[i].frac < pos)
|
||||
i++;
|
||||
auto *stop1 = &dsc->stops[i - 1];
|
||||
auto *stop2 = &dsc->stops[i];
|
||||
int32_t range = stop2->frac - stop1->frac;
|
||||
int32_t offset = pos - stop1->frac;
|
||||
return lv_color_mix(stop2->color, stop1->color, range == 0 ? 0 : (offset * 255) / range);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void lv_container_constructor(const lv_obj_class_t *class_p, lv_obj_t *obj) {
|
||||
LV_TRACE_OBJ_CREATE("begin");
|
||||
LV_UNUSED(class_p);
|
||||
|
||||
@@ -115,6 +115,16 @@ inline void lv_animimg_set_src(lv_obj_t *img, std::vector<image::Image *> images
|
||||
int16_t lv_get_needle_angle_for_value(lv_obj_t *obj, int value);
|
||||
#endif
|
||||
|
||||
#ifdef USE_LVGL_GRADIENT
|
||||
/**
|
||||
*
|
||||
* @param dsc The gradient descriptor containing the color stops
|
||||
* @param pos The current position to calculate the color for
|
||||
* @return The color for the given position
|
||||
*/
|
||||
|
||||
lv_color_t lv_grad_calculate_color(const lv_grad_dsc_t *dsc, int32_t pos);
|
||||
#endif
|
||||
// Parent class for things that wrap an LVGL object
|
||||
class LvCompound {
|
||||
public:
|
||||
|
||||
@@ -1,18 +1,27 @@
|
||||
from collections.abc import Callable
|
||||
import difflib
|
||||
|
||||
import esphome.codegen as cg
|
||||
from esphome.components.const import KEY_METADATA
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import CONF_FROM, CONF_ID, CONF_TO
|
||||
from esphome.core import CORE
|
||||
from esphome.cpp_generator import MockObj, VariableDeclarationExpression, add_global
|
||||
from esphome.core import CORE, ID
|
||||
from esphome.cpp_generator import (
|
||||
MockObj,
|
||||
MockObjClass,
|
||||
VariableDeclarationExpression,
|
||||
add_global,
|
||||
)
|
||||
from esphome.loader import get_component
|
||||
|
||||
CODEOWNERS = ["@clydebarrow"]
|
||||
MULTI_CONF = True
|
||||
DOMAIN = "mapping"
|
||||
|
||||
mapping_ns = cg.esphome_ns.namespace("mapping")
|
||||
mapping_class = mapping_ns.class_("Mapping")
|
||||
|
||||
CONF_DEFAULT_VALUE = "default_value"
|
||||
CONF_ENTRIES = "entries"
|
||||
CONF_CLASS = "class"
|
||||
|
||||
@@ -22,11 +31,18 @@ class IndexType:
|
||||
Represents a type of index in a map.
|
||||
"""
|
||||
|
||||
def __init__(self, validator, data_type, conversion):
|
||||
def __init__(
|
||||
self, validator: Callable, data_type: MockObj, conversion: Callable = None
|
||||
) -> None:
|
||||
self.validator = validator
|
||||
self.data_type = data_type
|
||||
self.conversion = conversion
|
||||
|
||||
async def convert_value(self, value):
|
||||
if self.conversion:
|
||||
return self.conversion(value)
|
||||
return await cg.get_variable(value)
|
||||
|
||||
|
||||
INDEX_TYPES = {
|
||||
"int": IndexType(cv.int_, cg.int_, int),
|
||||
@@ -38,6 +54,12 @@ INDEX_TYPES = {
|
||||
}
|
||||
|
||||
|
||||
class MappingMetaData:
|
||||
def __init__(self, from_: IndexType, to_: IndexType) -> None:
|
||||
self.from_ = from_
|
||||
self.to_ = to_
|
||||
|
||||
|
||||
def to_schema(value):
|
||||
"""
|
||||
Generate a schema for the 'to' field of a map. This can be either one of the index types or a class name.
|
||||
@@ -60,7 +82,7 @@ BASE_SCHEMA = cv.Schema(
|
||||
)
|
||||
|
||||
|
||||
def get_object_type(to_):
|
||||
def get_object_type(to_) -> MockObjClass | None:
|
||||
"""
|
||||
Get the object type from a string. Possible formats:
|
||||
xxx The name of a component which defines INSTANCE_TYPE
|
||||
@@ -81,25 +103,60 @@ def get_object_type(to_):
|
||||
return None
|
||||
|
||||
|
||||
def get_all_mapping_metadata() -> dict[str, MappingMetaData]:
|
||||
"""Get all mapping metadata."""
|
||||
return CORE.data.setdefault(DOMAIN, {}).setdefault(KEY_METADATA, {})
|
||||
|
||||
|
||||
def get_mapping_metadata(mapping_id: str) -> MappingMetaData:
|
||||
"""Get mapping metadata by ID for use by other components."""
|
||||
return get_all_mapping_metadata()[mapping_id]
|
||||
|
||||
|
||||
def add_metadata(
|
||||
mapping_id: ID,
|
||||
from_: IndexType,
|
||||
to_: IndexType,
|
||||
) -> None:
|
||||
get_all_mapping_metadata()[mapping_id.id] = MappingMetaData(from_, to_)
|
||||
|
||||
|
||||
def map_schema(config):
|
||||
config = BASE_SCHEMA(config)
|
||||
if CONF_ENTRIES not in config or not isinstance(config[CONF_ENTRIES], dict):
|
||||
raise cv.Invalid("an entries list is required for a map")
|
||||
raise cv.Invalid("an entries dictionary is required for a mapping")
|
||||
entries = config[CONF_ENTRIES]
|
||||
if len(entries) == 0:
|
||||
raise cv.Invalid("Map must have at least one entry")
|
||||
raise cv.Invalid("A mapping must have at least one entry")
|
||||
to_ = config[CONF_TO]
|
||||
if to_ in INDEX_TYPES:
|
||||
value_type = INDEX_TYPES[to_].validator
|
||||
value_type = INDEX_TYPES[to_]
|
||||
else:
|
||||
value_type = get_object_type(to_)
|
||||
if value_type is None:
|
||||
object_type = get_object_type(to_)
|
||||
if object_type is None:
|
||||
matches = difflib.get_close_matches(to_, CORE.id_classes)
|
||||
raise cv.Invalid(
|
||||
f"No known mappable class name matches '{to_}'; did you mean one of {', '.join(matches)}?"
|
||||
)
|
||||
value_type = cv.use_id(value_type)
|
||||
config[CONF_ENTRIES] = {k: value_type(v) for k, v in entries.items()}
|
||||
validator = cv.use_id(object_type)
|
||||
value_type = IndexType(validator, object_type)
|
||||
config[CONF_ENTRIES] = {k: value_type.validator(v) for k, v in entries.items()}
|
||||
if (default_value := config.get(CONF_DEFAULT_VALUE)) is not None:
|
||||
config[CONF_DEFAULT_VALUE] = value_type.validator(default_value)
|
||||
unexpected_keys = config.keys() - {
|
||||
CONF_ENTRIES,
|
||||
CONF_TO,
|
||||
CONF_FROM,
|
||||
CONF_ID,
|
||||
CONF_DEFAULT_VALUE,
|
||||
}
|
||||
if unexpected_keys:
|
||||
errors = [
|
||||
cv.Invalid(f"Unexpected key '{k}'", path=[k]) for k in unexpected_keys
|
||||
]
|
||||
raise cv.MultipleInvalid(errors)
|
||||
|
||||
add_metadata(config[CONF_ID], INDEX_TYPES[config[CONF_FROM]], value_type)
|
||||
return config
|
||||
|
||||
|
||||
@@ -107,29 +164,19 @@ CONFIG_SCHEMA = map_schema
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
entries = config[CONF_ENTRIES]
|
||||
from_ = config[CONF_FROM]
|
||||
to_ = config[CONF_TO]
|
||||
index_conversion = INDEX_TYPES[from_].conversion
|
||||
index_type = INDEX_TYPES[from_].data_type
|
||||
if to_ in INDEX_TYPES:
|
||||
value_conversion = INDEX_TYPES[to_].conversion
|
||||
value_type = INDEX_TYPES[to_].data_type
|
||||
entries = {
|
||||
index_conversion(key): value_conversion(value)
|
||||
for key, value in entries.items()
|
||||
}
|
||||
else:
|
||||
entries = {
|
||||
index_conversion(key): await cg.get_variable(value)
|
||||
for key, value in entries.items()
|
||||
}
|
||||
value_type = get_object_type(to_)
|
||||
if list(entries.values())[0].op != ".":
|
||||
value_type = value_type.operator("ptr")
|
||||
varid = config[CONF_ID]
|
||||
metadata = get_mapping_metadata(varid.id)
|
||||
entries = {
|
||||
metadata.from_.conversion(key): await metadata.to_.convert_value(value)
|
||||
for key, value in config[CONF_ENTRIES].items()
|
||||
}
|
||||
value_type = metadata.to_.data_type
|
||||
# entries guaranteed to be non-empty here.
|
||||
value_0 = list(entries.values())[0]
|
||||
if isinstance(value_0, MockObj) and value_0.op != ".":
|
||||
value_type = value_type.operator("ptr")
|
||||
varid.type = mapping_class.template(
|
||||
index_type,
|
||||
metadata.from_.data_type,
|
||||
value_type,
|
||||
)
|
||||
var = MockObj(varid, ".")
|
||||
@@ -139,4 +186,6 @@ async def to_code(config):
|
||||
|
||||
for key, value in entries.items():
|
||||
cg.add(var.set(key, value))
|
||||
if (default_value := config.get(CONF_DEFAULT_VALUE)) is not None:
|
||||
cg.add(var.set_default_value(await metadata.to_.convert_value(default_value)))
|
||||
return var
|
||||
|
||||
@@ -40,6 +40,9 @@ template<typename K, typename V> class Mapping {
|
||||
if (it != this->map_.end()) {
|
||||
return V{it->second};
|
||||
}
|
||||
if (this->default_value_.has_value()) {
|
||||
return this->default_value_.value();
|
||||
}
|
||||
if constexpr (std::is_pointer_v<K>) {
|
||||
esph_log_e(TAG, "Key '%p' not found in mapping", key);
|
||||
} else if constexpr (std::is_same_v<K, std::string>) {
|
||||
@@ -69,11 +72,17 @@ template<typename K, typename V> class Mapping {
|
||||
if (it != this->map_.end()) {
|
||||
return it->second.c_str(); // safe since value remains in map
|
||||
}
|
||||
if (this->default_value_.has_value()) {
|
||||
return this->default_value_.value();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void set_default_value(const V &default_value) { this->default_value_ = default_value; }
|
||||
|
||||
protected:
|
||||
std::map<key_t, value_t, std::less<key_t>, RAMAllocator<std::pair<key_t, value_t>>> map_;
|
||||
std::optional<V> default_value_{};
|
||||
};
|
||||
|
||||
} // namespace esphome::mapping
|
||||
|
||||
@@ -433,13 +433,17 @@ void Pipsolar::handle_qpigs_(const char *message) {
|
||||
}
|
||||
|
||||
void Pipsolar::handle_qmod_(const char *message) {
|
||||
std::string mode;
|
||||
char device_mode = char(message[1]);
|
||||
if (this->last_qmod_) {
|
||||
this->last_qmod_->publish_state(message);
|
||||
}
|
||||
// QMOD response is "(M" where M is the device-mode character. Bail out if the
|
||||
// message is shorter than 2 chars (e.g. empty error response from
|
||||
// handle_poll_error_) — reading message[1] would otherwise be out of bounds.
|
||||
if (message[0] == '\0' || message[1] == '\0')
|
||||
return;
|
||||
if (this->device_mode_) {
|
||||
mode = device_mode;
|
||||
std::string mode;
|
||||
mode = char(message[1]);
|
||||
this->device_mode_->publish_state(mode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -451,7 +451,7 @@ class SPIDevice : public SPIClient {
|
||||
|
||||
uint8_t read_byte() { return this->delegate_->transfer(0); }
|
||||
|
||||
void read_array(uint8_t *data, size_t length) { return this->delegate_->read_array(data, length); }
|
||||
void read_array(uint8_t *data, size_t length) { this->delegate_->read_array(data, length); }
|
||||
|
||||
/**
|
||||
* Write a single data item, up to 32 bits.
|
||||
|
||||
@@ -68,13 +68,8 @@ void TLC5971::transfer_(uint8_t send) {
|
||||
uint8_t startbit = 0x80;
|
||||
|
||||
bool towrite, lastmosi = !(send & startbit);
|
||||
uint8_t bitdelay_us = (1000000 / 1000000) / 2;
|
||||
|
||||
for (uint8_t b = startbit; b != 0; b = b >> 1) {
|
||||
if (bitdelay_us) {
|
||||
delayMicroseconds(bitdelay_us);
|
||||
}
|
||||
|
||||
towrite = send & b;
|
||||
if ((lastmosi != towrite)) {
|
||||
this->data_pin_->digital_write(towrite);
|
||||
@@ -82,11 +77,6 @@ void TLC5971::transfer_(uint8_t send) {
|
||||
}
|
||||
|
||||
this->clock_pin_->digital_write(true);
|
||||
|
||||
if (bitdelay_us) {
|
||||
delayMicroseconds(bitdelay_us);
|
||||
}
|
||||
|
||||
this->clock_pin_->digital_write(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,6 +96,7 @@
|
||||
#define USE_LVGL_CHECKBOX
|
||||
#define USE_LVGL_DROPDOWN
|
||||
#define USE_LVGL_FONT
|
||||
#define USE_LVGL_GRADIENT
|
||||
#define USE_LVGL_IMAGE
|
||||
#define USE_LVGL_IMAGEBUTTON
|
||||
#define USE_LVGL_KEY_LISTENER
|
||||
|
||||
+8
-2
@@ -9,16 +9,22 @@ import logging
|
||||
from pathlib import Path
|
||||
import sys
|
||||
from types import ModuleType
|
||||
from typing import Any
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from esphome.const import SOURCE_FILE_EXTENSIONS
|
||||
from esphome.core import CORE
|
||||
from esphome.types import ConfigType
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from esphome.cpp_generator import MockObjClass
|
||||
|
||||
# `esphome.core.config` is imported lazily in `_lookup_module` when the
|
||||
# "esphome" pseudo-component is first resolved. It pulls in
|
||||
# `esphome.automation` and `esphome.config_validation`, which together
|
||||
# dominate `esphome.__main__` startup cost when loaded eagerly.
|
||||
# `esphome.cpp_generator` is similarly avoided at module scope; it pulls
|
||||
# in `esphome.yaml_util` and is only needed for the `MockObjClass` type
|
||||
# annotation, which is resolved lazily via `TYPE_CHECKING`.
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@@ -97,7 +103,7 @@ class ComponentManifest:
|
||||
return getattr(self.module, "CODEOWNERS", [])
|
||||
|
||||
@property
|
||||
def instance_type(self) -> list[str]:
|
||||
def instance_type(self) -> "MockObjClass | None":
|
||||
return getattr(self.module, "INSTANCE_TYPE", None)
|
||||
|
||||
@property
|
||||
|
||||
@@ -21,6 +21,7 @@ mapping:
|
||||
entries:
|
||||
clear-night: image_1
|
||||
sunny: image_2
|
||||
default_value: image_1
|
||||
- id: weather_map_2
|
||||
from: string
|
||||
to: image
|
||||
@@ -35,6 +36,7 @@ mapping:
|
||||
2: "two"
|
||||
3: "three"
|
||||
77: "seventy-seven"
|
||||
default_value: unknown
|
||||
- id: string_map
|
||||
from: string
|
||||
to: int
|
||||
|
||||
@@ -4,7 +4,7 @@ packages:
|
||||
|
||||
display:
|
||||
spi_id: spi_bus
|
||||
platform: ili9xxx
|
||||
platform: mipi_spi
|
||||
id: main_lcd
|
||||
model: ili9342
|
||||
cs_pin: 12
|
||||
|
||||
@@ -4,7 +4,7 @@ packages:
|
||||
|
||||
display:
|
||||
spi_id: spi_bus
|
||||
platform: ili9xxx
|
||||
platform: mipi_spi
|
||||
id: main_lcd
|
||||
model: ili9342
|
||||
cs_pin: 5
|
||||
|
||||
@@ -4,7 +4,7 @@ packages:
|
||||
|
||||
display:
|
||||
spi_id: spi_bus
|
||||
platform: ili9xxx
|
||||
platform: mipi_spi
|
||||
id: main_lcd
|
||||
model: ili9342
|
||||
data_rate: 31.25MHz
|
||||
|
||||
Reference in New Issue
Block a user