From fc337aef6941840a8da8ff66905999e755dd3abb Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Mon, 14 Jul 2025 09:47:52 +1000 Subject: [PATCH 1/5] [esp_ldo] Component schema; default priority (#9479) --- esphome/components/esp_ldo/__init__.py | 18 ++++++++++-------- esphome/components/esp_ldo/esp_ldo.h | 3 +++ .../components/esp_ldo/test.esp32-p4-idf.yaml | 1 + 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/esphome/components/esp_ldo/__init__.py b/esphome/components/esp_ldo/__init__.py index ce24028083..38e684c537 100644 --- a/esphome/components/esp_ldo/__init__.py +++ b/esphome/components/esp_ldo/__init__.py @@ -20,14 +20,16 @@ adjusted_ids = set() CONFIG_SCHEMA = cv.All( cv.ensure_list( - { - cv.GenerateID(): cv.declare_id(EspLdo), - cv.Required(CONF_VOLTAGE): cv.All( - cv.voltage, cv.float_range(min=0.5, max=2.7) - ), - cv.Required(CONF_CHANNEL): cv.one_of(*CHANNELS, int=True), - cv.Optional(CONF_ADJUSTABLE, default=False): cv.boolean, - } + cv.COMPONENT_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(EspLdo), + cv.Required(CONF_VOLTAGE): cv.All( + cv.voltage, cv.float_range(min=0.5, max=2.7) + ), + cv.Required(CONF_CHANNEL): cv.one_of(*CHANNELS, int=True), + cv.Optional(CONF_ADJUSTABLE, default=False): cv.boolean, + } + ) ), cv.only_with_esp_idf, only_on_variant(supported=[VARIANT_ESP32P4]), diff --git a/esphome/components/esp_ldo/esp_ldo.h b/esphome/components/esp_ldo/esp_ldo.h index fb5abf7a3a..bafa32db6b 100644 --- a/esphome/components/esp_ldo/esp_ldo.h +++ b/esphome/components/esp_ldo/esp_ldo.h @@ -17,6 +17,9 @@ class EspLdo : public Component { void set_adjustable(bool adjustable) { this->adjustable_ = adjustable; } void set_voltage(float voltage) { this->voltage_ = voltage; } void adjust_voltage(float voltage); + float get_setup_priority() const override { + return setup_priority::BUS; // LDO setup should be done early + } protected: int channel_; diff --git a/tests/components/esp_ldo/test.esp32-p4-idf.yaml b/tests/components/esp_ldo/test.esp32-p4-idf.yaml index 0e91aaf082..38bd6ac411 100644 --- a/tests/components/esp_ldo/test.esp32-p4-idf.yaml +++ b/tests/components/esp_ldo/test.esp32-p4-idf.yaml @@ -6,6 +6,7 @@ esp_ldo: - id: ldo_4 channel: 4 voltage: 2.0V + setup_priority: 900 esphome: on_boot: From 02d1894a9feaa955c2121e2b2db20d3481873db5 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 13 Jul 2025 14:32:16 -1000 Subject: [PATCH 2/5] Refactor format_hex_pretty functions to eliminate code duplication (#9480) --- esphome/core/helpers.cpp | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/esphome/core/helpers.cpp b/esphome/core/helpers.cpp index b46077af02..e84f5a7317 100644 --- a/esphome/core/helpers.cpp +++ b/esphome/core/helpers.cpp @@ -258,7 +258,9 @@ std::string format_hex(const uint8_t *data, size_t length) { std::string format_hex(const std::vector &data) { return format_hex(data.data(), data.size()); } static char format_hex_pretty_char(uint8_t v) { return v >= 10 ? 'A' + (v - 10) : '0' + v; } -std::string format_hex_pretty(const uint8_t *data, size_t length, char separator, bool show_length) { + +// Shared implementation for uint8_t and string hex formatting +static std::string format_hex_pretty_uint8(const uint8_t *data, size_t length, char separator, bool show_length) { if (data == nullptr || length == 0) return ""; std::string ret; @@ -274,6 +276,10 @@ std::string format_hex_pretty(const uint8_t *data, size_t length, char separator return ret + " (" + std::to_string(length) + ")"; return ret; } + +std::string format_hex_pretty(const uint8_t *data, size_t length, char separator, bool show_length) { + return format_hex_pretty_uint8(data, length, separator, show_length); +} std::string format_hex_pretty(const std::vector &data, char separator, bool show_length) { return format_hex_pretty(data.data(), data.size(), separator, show_length); } @@ -300,20 +306,7 @@ std::string format_hex_pretty(const std::vector &data, char separator, return format_hex_pretty(data.data(), data.size(), separator, show_length); } std::string format_hex_pretty(const std::string &data, char separator, bool show_length) { - if (data.empty()) - return ""; - std::string ret; - uint8_t multiple = separator ? 3 : 2; // 3 if separator is not \0, 2 otherwise - ret.resize(multiple * data.length() - (separator ? 1 : 0)); - for (size_t i = 0; i < data.length(); i++) { - ret[multiple * i] = format_hex_pretty_char((data[i] & 0xF0) >> 4); - ret[multiple * i + 1] = format_hex_pretty_char(data[i] & 0x0F); - if (separator && i != data.length() - 1) - ret[multiple * i + 2] = separator; - } - if (show_length && data.length() > 4) - return ret + " (" + std::to_string(data.length()) + ")"; - return ret; + return format_hex_pretty_uint8(reinterpret_cast(data.data()), data.length(), separator, show_length); } std::string format_bin(const uint8_t *data, size_t length) { From f5c8595a4633fbcae9fb08321fa659fde429527b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 13 Jul 2025 14:41:49 -1000 Subject: [PATCH 3/5] Follow logging best practices by removing redundant component prefix (#9481) --- esphome/core/component.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index 9d863e56cd..b360e1d20b 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -138,7 +138,7 @@ void Component::call_dump_config() { } } } - ESP_LOGE(TAG, " Component %s is marked FAILED: %s", this->get_component_source(), error_msg); + ESP_LOGE(TAG, " %s is marked FAILED: %s", this->get_component_source(), error_msg); } } @@ -191,7 +191,7 @@ bool Component::should_warn_of_blocking(uint32_t blocking_time) { return false; } void Component::mark_failed() { - ESP_LOGE(TAG, "Component %s was marked as failed", this->get_component_source()); + ESP_LOGE(TAG, "%s was marked as failed", this->get_component_source()); this->component_state_ &= ~COMPONENT_STATE_MASK; this->component_state_ |= COMPONENT_STATE_FAILED; this->status_set_error(); @@ -229,7 +229,7 @@ void IRAM_ATTR HOT Component::enable_loop_soon_any_context() { } void Component::reset_to_construction_state() { if ((this->component_state_ & COMPONENT_STATE_MASK) == COMPONENT_STATE_FAILED) { - ESP_LOGI(TAG, "Component %s is being reset to construction state", this->get_component_source()); + ESP_LOGI(TAG, "%s is being reset to construction state", this->get_component_source()); this->component_state_ &= ~COMPONENT_STATE_MASK; this->component_state_ |= COMPONENT_STATE_CONSTRUCTION; // Clear error status when resetting @@ -275,14 +275,14 @@ void Component::status_set_warning(const char *message) { return; this->component_state_ |= STATUS_LED_WARNING; App.app_state_ |= STATUS_LED_WARNING; - ESP_LOGW(TAG, "Component %s set Warning flag: %s", this->get_component_source(), message); + ESP_LOGW(TAG, "%s set Warning flag: %s", this->get_component_source(), message); } void Component::status_set_error(const char *message) { if ((this->component_state_ & STATUS_LED_ERROR) != 0) return; this->component_state_ |= STATUS_LED_ERROR; App.app_state_ |= STATUS_LED_ERROR; - ESP_LOGE(TAG, "Component %s set Error flag: %s", this->get_component_source(), message); + ESP_LOGE(TAG, "%s set Error flag: %s", this->get_component_source(), message); if (strcmp(message, "unspecified") != 0) { // Lazy allocate the error messages vector if needed if (!component_error_messages) { @@ -303,13 +303,13 @@ void Component::status_clear_warning() { if ((this->component_state_ & STATUS_LED_WARNING) == 0) return; this->component_state_ &= ~STATUS_LED_WARNING; - ESP_LOGW(TAG, "Component %s cleared Warning flag", this->get_component_source()); + ESP_LOGW(TAG, "%s cleared Warning flag", this->get_component_source()); } void Component::status_clear_error() { if ((this->component_state_ & STATUS_LED_ERROR) == 0) return; this->component_state_ &= ~STATUS_LED_ERROR; - ESP_LOGE(TAG, "Component %s cleared Error flag", this->get_component_source()); + ESP_LOGE(TAG, "%s cleared Error flag", this->get_component_source()); } void Component::status_momentary_warning(const std::string &name, uint32_t length) { this->status_set_warning(); @@ -403,7 +403,7 @@ uint32_t WarnIfComponentBlockingGuard::finish() { } if (should_warn) { const char *src = component_ == nullptr ? "" : component_->get_component_source(); - ESP_LOGW(TAG, "Component %s took a long time for an operation (%" PRIu32 " ms)", src, blocking_time); + ESP_LOGW(TAG, "%s took a long time for an operation (%" PRIu32 " ms)", src, blocking_time); ESP_LOGW(TAG, "Components should block for at most 30 ms"); } From d31b8ad2e2cdd63884d4f1a7bc42c3677e1eedc1 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 13 Jul 2025 14:58:07 -1000 Subject: [PATCH 4/5] Fix dormant bug in RAMAllocator::reallocate() manual_size calculation (#9482) --- esphome/core/helpers.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 58f162ff9d..c3b404ae60 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -783,7 +783,7 @@ template class RAMAllocator { T *reallocate(T *p, size_t n) { return this->reallocate(p, n, sizeof(T)); } T *reallocate(T *p, size_t n, size_t manual_size) { - size_t size = n * sizeof(T); + size_t size = n * manual_size; T *ptr = nullptr; #ifdef USE_ESP32 if (this->flags_ & Flags::ALLOC_EXTERNAL) { From 873f4125c57dba83b54e6baca19b0bc284412796 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 13 Jul 2025 17:30:34 -1000 Subject: [PATCH 5/5] Fix pre-commit CI issues by switching to lite mode (#9484) --- .github/workflows/ci.yml | 105 +++++++++------------------------------ .pre-commit-config.yaml | 2 +- 2 files changed, 24 insertions(+), 83 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c043c25936..2e2e114fdb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,7 +39,7 @@ jobs: uses: actions/checkout@v4.2.2 - name: Generate cache-key id: cache-key - run: echo key="${{ hashFiles('requirements.txt', 'requirements_test.txt') }}" >> $GITHUB_OUTPUT + run: echo key="${{ hashFiles('requirements.txt', 'requirements_test.txt', '.pre-commit-config.yaml') }}" >> $GITHUB_OUTPUT - name: Set up Python ${{ env.DEFAULT_PYTHON }} id: python uses: actions/setup-python@v5.6.0 @@ -58,55 +58,9 @@ jobs: python -m venv venv . venv/bin/activate python --version - pip install -r requirements.txt -r requirements_test.txt + pip install -r requirements.txt -r requirements_test.txt pre-commit pip install -e . - ruff: - name: Check ruff - runs-on: ubuntu-24.04 - needs: - - common - - determine-jobs - if: needs.determine-jobs.outputs.python-linters == 'true' - steps: - - name: Check out code from GitHub - uses: actions/checkout@v4.2.2 - - name: Restore Python - uses: ./.github/actions/restore-python - with: - python-version: ${{ env.DEFAULT_PYTHON }} - cache-key: ${{ needs.common.outputs.cache-key }} - - name: Run Ruff - run: | - . venv/bin/activate - ruff format esphome tests - - name: Suggested changes - run: script/ci-suggest-changes - if: always() - - flake8: - name: Check flake8 - runs-on: ubuntu-24.04 - needs: - - common - - determine-jobs - if: needs.determine-jobs.outputs.python-linters == 'true' - steps: - - name: Check out code from GitHub - uses: actions/checkout@v4.2.2 - - name: Restore Python - uses: ./.github/actions/restore-python - with: - python-version: ${{ env.DEFAULT_PYTHON }} - cache-key: ${{ needs.common.outputs.cache-key }} - - name: Run flake8 - run: | - . venv/bin/activate - flake8 esphome - - name: Suggested changes - run: script/ci-suggest-changes - if: always() - pylint: name: Check pylint runs-on: ubuntu-24.04 @@ -248,7 +202,6 @@ jobs: outputs: integration-tests: ${{ steps.determine.outputs.integration-tests }} clang-tidy: ${{ steps.determine.outputs.clang-tidy }} - clang-format: ${{ steps.determine.outputs.clang-format }} python-linters: ${{ steps.determine.outputs.python-linters }} changed-components: ${{ steps.determine.outputs.changed-components }} component-test-count: ${{ steps.determine.outputs.component-test-count }} @@ -276,7 +229,6 @@ jobs: # Extract individual fields echo "integration-tests=$(echo "$output" | jq -r '.integration_tests')" >> $GITHUB_OUTPUT echo "clang-tidy=$(echo "$output" | jq -r '.clang_tidy')" >> $GITHUB_OUTPUT - echo "clang-format=$(echo "$output" | jq -r '.clang_format')" >> $GITHUB_OUTPUT echo "python-linters=$(echo "$output" | jq -r '.python_linters')" >> $GITHUB_OUTPUT echo "changed-components=$(echo "$output" | jq -c '.changed_components')" >> $GITHUB_OUTPUT echo "component-test-count=$(echo "$output" | jq -r '.component_test_count')" >> $GITHUB_OUTPUT @@ -317,41 +269,12 @@ jobs: . venv/bin/activate pytest -vv --no-cov --tb=native -n auto tests/integration/ - clang-format: - name: Check clang-format - runs-on: ubuntu-24.04 - needs: - - common - - determine-jobs - if: needs.determine-jobs.outputs.clang-format == 'true' - steps: - - name: Check out code from GitHub - uses: actions/checkout@v4.2.2 - - name: Restore Python - uses: ./.github/actions/restore-python - with: - python-version: ${{ env.DEFAULT_PYTHON }} - cache-key: ${{ needs.common.outputs.cache-key }} - - name: Install clang-format - run: | - . venv/bin/activate - pip install clang-format -c requirements_dev.txt - - name: Run clang-format - run: | - . venv/bin/activate - script/clang-format -i - git diff-index --quiet HEAD -- - - name: Suggested changes - run: script/ci-suggest-changes - if: always() - clang-tidy-deps: name: Clang-tidy dependencies runs-on: ubuntu-24.04 needs: - common - ci-custom - - clang-format - pytest - determine-jobs if: | @@ -573,15 +496,32 @@ jobs: ./script/test_build_components -e compile -c $component done + pre-commit-ci-lite: + name: pre-commit.ci lite + runs-on: ubuntu-latest + needs: + - common + if: github.event_name == 'pull_request' && github.base_ref != 'beta' && github.base_ref != 'release' + steps: + - name: Check out code from GitHub + uses: actions/checkout@v4.2.2 + - name: Restore Python + uses: ./.github/actions/restore-python + with: + python-version: ${{ env.DEFAULT_PYTHON }} + cache-key: ${{ needs.common.outputs.cache-key }} + - uses: pre-commit/action@v3.0.1 + env: + SKIP: pylint,clang-tidy-hash,yamllint + - uses: pre-commit-ci/lite-action@v1.1.0 + if: always() + ci-status: name: CI Status runs-on: ubuntu-24.04 needs: - common - - ruff - ci-custom - - clang-format - - flake8 - pylint - pytest - integration-tests @@ -592,6 +532,7 @@ jobs: - test-build-components - test-build-components-splitter - test-build-components-split + - pre-commit-ci-lite if: always() steps: - name: Success diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 203808c88b..8db7f21599 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,7 +4,7 @@ ci: autoupdate_commit_msg: 'pre-commit: autoupdate' - autoupdate_schedule: weekly + autoupdate_schedule: off # Disabled until ruff versions are synced between deps and pre-commit # Skip hooks that have issues in pre-commit CI environment skip: [pylint, clang-tidy-hash, yamllint]