The docstring claimed exact registry names for every core above 2.6.2;
2.6.3, 3.0.0 and 3.0.1 ship with non-zero trailing components the
formula cannot produce. Name them, say which callers are safe (the ~
range on the PlatformIO path, the floored check_and_install), and
credit the floor with covering 3.0.0/3.0.1 as well as the absent 3.1.0.
<= 2.6.2 instead of < 2.6.3: a 2.6.2 pre-release sorts above 2.6.2 and
belongs to the package-major-3 encoding, so the helper now describes
the same set as _format_framework_arduino_version and a 2.6.2-b1 pin
formats as it does on dev. The module never logged, so its _LOGGER and
logging import go.
cv.Invalid now carries path=[CONF_VERSION] so the rejection lands on
the framework version line the comment promised, matching the esp32
convention. framework_package_version raises for cores before 2.6.3
instead of encoding them wrongly for a caller that skipped the
PlatformIO path's era guard. get_build_env joins PATH from filtered
parts so an absent PATH cannot leave a trailing separator that the
shell reads as the current directory.
The pre-lexed tokens feed both _flag_defines and _project_flags so a
malformed entry warns once per generation. An unflag that hits nothing
in the user flags or any framework set (a typo, or -DUSE_FOO against
-DUSE_FOO=1) is named instead of silently leaving the flag in force.
A raw MMU_* define alongside a PIO_FRAMEWORK_ARDUINO_MMU_* knob, or a
raw TCP_MSS/LWIP_* alongside the lwIP knobs, would win the compile line
while the linker script or prebuilt library keeps the knob's values;
both now raise like the no-knob case. _MMU_VARIANTS holds tuples and the
resolved config gets a copy, so nothing aliases the module table.
_lexed_build_flags lexes once and both consumers accept the tokens, so
a malformed entry warns once per build. The linker-script stamp covers
the header's size and mtime, an unreadable or non-UTF-8 cache
regenerates instead of aborting, plain-form linker flags warn that they
are not routed to the link line, and a moved rate-table anchor surfaces
as a named build error.
parse_enable_env carries the 1/true/yes/on and 0/false/no/off table for
both knobs, so IDF_CCACHE_ENABLE=off disables instead of reading as
truthy and suppressing the shared opt-out. The ccache module docstring
and the ESP-IDF _ccache_env docstring now describe the precedence this
PR actually ships, and the probe test duplicated by the helper move is
dropped from the PlatformIO toolchain tests.
elf2bin.py and eboot.elf join the existence checks so a half-extracted
package fails by name before the compile instead of at the
second-to-last edge. get_project_cxx_compile_flags() values go through
_shell_token like every other flag source. d1_wroom_02 (2 MB, in
ESP8266_BOARD_BUILD and buildable under PlatformIO) joins BOARDS so the
native board guard stops rejecting it, and the guard comment states
what config validation actually checks.
Unknown or conflicting VTABLES_IN_* defines raise instead of warning
and picking arbitrarily (a typo previously won the sorted pick and died
in the SDK header's #error). Custom MMU sizes without the CUSTOM knob
raise too: PlatformIO warns but its defaults win the compile line,
while here the user's tokens would win and compile against a layout the
linker script does not implement. The cached linker script is re-checked
for its SECTIONS block so a truncated file regenerates, the
testing-mode flash-ld read gets the same OSError guard as the gcc
spawn, the ParseFlags docstring states its actual coverage, and the ld
test mocks are quiet so the clean path asserts no warnings.
check_library_data's platform filter raises IncompatiblePlatform (an
InvalidLibrary subclass) so the arduino backend branches on the type
instead of substring-matching the message. The {"Wire": "*"} dict
shorthand resolves to the bundled library like PIO's
process_dependencies instead of a registry lookup. libArchive parses
booleans and true/false strings and warns on anything else (bool(str)
made "false" archive). A declared-but-falsy srcDir raises instead of
silently probing. The converter-drop warning names the missing requests,
and the bundled-walk comment states what PIO actually does.
The installer's EsphomeError becomes cv.Invalid at the config
validator, and test_ccache_env clears the ambient environment so a
developer's exported CCACHE_DIR cannot fail it.
shell_token now picks the quoting style per platform: single quotes on
POSIX (sh expands nothing inside them, so backslash runs, $VAR, and
backticks reach the compiler exactly as lexed, matching SCons's
no-shell spawn) and the CreateProcess argv rule on Windows. A test
round-trips every case through a real /bin/sh.
The ninja and ccache runnability probes collapse into one
tool_version_runs helper in framework_helpers. The registry names a
non-dict top-level payload like the inner guards, and the expect layout
check also runs on marker hits so a marked install that later lost
files fails by name. The ESP-IDF ccache gate defers to
resolve_ccache_path so ESPHOME_CCACHE_ENABLE=0 disables ccache there
too, with IDF_CCACHE_ENABLE still taking precedence.
Platforms normalize toolchain-sensitive keys differently (the esp32
board name, for one), so a config validated under a mismatching
--toolchain must not overwrite the cache while the sidecar keeps the
compile's toolchain. The guard lives in _refresh_sidecar where the old
sidecar is already loaded; legacy sidecars without the field are
unaffected.