mirror of
https://github.com/esphome/esphome.git
synced 2026-09-30 00:10:22 +00:00
Merge branch 'esp8266-native-ninja-emission' into esp8266-arduino-toolchain
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
from collections.abc import Generator
|
||||
import errno
|
||||
import io
|
||||
import logging
|
||||
import os
|
||||
@@ -178,37 +177,34 @@ def _run_probe_on_pty(
|
||||
output = b""
|
||||
deadline = time.monotonic() + 60
|
||||
try:
|
||||
try:
|
||||
proc = subprocess.Popen(
|
||||
_probe_command(fixture_path),
|
||||
stdout=follower,
|
||||
stderr=follower if stderr_to_pty else subprocess.PIPE,
|
||||
stdin=follower,
|
||||
env=probe_env,
|
||||
)
|
||||
finally:
|
||||
os.close(follower)
|
||||
while True:
|
||||
timeout = deadline - time.monotonic()
|
||||
if timeout <= 0 or not select.select([controller], [], [], timeout)[0]:
|
||||
pytest.fail(f"pty probe produced no EOF in time; got {output!r}")
|
||||
try:
|
||||
chunk = os.read(controller, 1024)
|
||||
except OSError as err:
|
||||
# macOS raises EIO once the child closes its end of the pty;
|
||||
# anything else is a real failure, not end-of-stream.
|
||||
if err.errno != errno.EIO:
|
||||
raise
|
||||
break
|
||||
if not chunk:
|
||||
break
|
||||
proc = subprocess.Popen(
|
||||
_probe_command(fixture_path),
|
||||
stdout=follower,
|
||||
stderr=follower if stderr_to_pty else subprocess.PIPE,
|
||||
stdin=follower,
|
||||
env=probe_env,
|
||||
)
|
||||
# The parent keeps the follower open until the child has exited and
|
||||
# the controller is drained: macOS discards buffered pty output once
|
||||
# the last follower closes, so closing it early loses the probe's
|
||||
# output whenever the child finishes before the first read.
|
||||
while proc.poll() is None:
|
||||
if time.monotonic() > deadline:
|
||||
pytest.fail(f"pty probe did not exit in time; got {output!r}")
|
||||
if select.select([controller], [], [], 0.01)[0]:
|
||||
output += os.read(controller, 4096)
|
||||
# Everything the child wrote is already buffered, so drain without waiting.
|
||||
while select.select([controller], [], [], 0)[0] and (
|
||||
chunk := os.read(controller, 4096)
|
||||
):
|
||||
output += chunk
|
||||
stderr_text = ""
|
||||
if proc.stderr is not None:
|
||||
stderr_text = proc.stderr.read().decode(errors="replace")
|
||||
proc.stderr.close()
|
||||
assert proc.wait(60) == 0, stderr_text
|
||||
assert proc.returncode == 0, stderr_text
|
||||
finally:
|
||||
os.close(follower)
|
||||
os.close(controller)
|
||||
if proc is not None and proc.poll() is None:
|
||||
proc.kill()
|
||||
|
||||
@@ -471,6 +471,32 @@ def test_spaced_linkflag_survives_relexing(tmp_path) -> None:
|
||||
]
|
||||
|
||||
|
||||
def test_env_attribute_access_warns_without_call(caplog) -> None:
|
||||
"""hasattr()/truthiness on an unsupported method is diagnosable; dunder
|
||||
protocol probes stay silent."""
|
||||
env = _FakeSConsEnv(
|
||||
board_mcu="esp8266", pio_env="esphome_esp8266", pio_platform="espressif8266"
|
||||
)
|
||||
assert env.GetProjectOption
|
||||
assert caplog.text.count("env.GetProjectOption is not supported") == 1
|
||||
assert not hasattr(env, "__deepcopy__")
|
||||
assert "__deepcopy__" not in caplog.text
|
||||
|
||||
|
||||
def test_env_unmodelled_subscript_degrades_one_branch(caplog) -> None:
|
||||
"""env[...] on an unmodelled var returns '' instead of KeyError
|
||||
discarding the whole capture."""
|
||||
env = _FakeSConsEnv(
|
||||
board_mcu="esp8266", pio_env="esphome_esp8266", pio_platform="espressif8266"
|
||||
)
|
||||
assert env["PIOFRAMEWORK"] == ""
|
||||
assert env["PIOFRAMEWORK"] == ""
|
||||
assert caplog.text.count("env['PIOFRAMEWORK'] is not modelled") == 1
|
||||
assert env["BOARD_MCU"] == "esp8266"
|
||||
env.Append(LIBS=["still_captured"])
|
||||
assert env.result.libs == ["still_captured"]
|
||||
|
||||
|
||||
def test_uncaptured_append_key_warns_once(caplog) -> None:
|
||||
"""A loop of Appends to the same uncaptured key warns once."""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user