mirror of
https://github.com/esphome/esphome.git
synced 2026-10-07 11:26:39 +00:00
[core] Warn when running a different source tree than the one you are in (#18288)
Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
co-authored by
J. Nick Koston
parent
9f28638ee7
commit
be5e28ea9e
@@ -18,6 +18,7 @@ import pytest
|
||||
from pytest import CaptureFixture
|
||||
from zeroconf import ServiceStateChange
|
||||
|
||||
from esphome import __main__ as main
|
||||
from esphome.__main__ import (
|
||||
Purpose,
|
||||
_get_configured_xtal_freq,
|
||||
@@ -6760,3 +6761,144 @@ def test_check_permissions_unreadable_port() -> None:
|
||||
pytest.raises(EsphomeError, match="read or write permission"),
|
||||
):
|
||||
check_permissions("/dev/ttyUSB99")
|
||||
|
||||
|
||||
def _make_checkout(root: Path) -> Path:
|
||||
"""Create a directory that looks like an esphome checkout."""
|
||||
(root / "esphome").mkdir(parents=True)
|
||||
(root / "esphome" / "__main__.py").write_text("", encoding="utf-8")
|
||||
return root
|
||||
|
||||
|
||||
def test_warn_source_tree_mismatch_warns_for_other_tree(
|
||||
tmp_path: Path,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
) -> None:
|
||||
"""Standing in a checkout other than the one being run warns."""
|
||||
standing_in = _make_checkout(tmp_path / "worktree")
|
||||
running = _make_checkout(tmp_path / "main")
|
||||
monkeypatch.chdir(standing_in)
|
||||
monkeypatch.setattr(main, "__file__", str(running / "esphome" / "__main__.py"))
|
||||
|
||||
with caplog.at_level(logging.WARNING):
|
||||
main._warn_if_source_tree_mismatch()
|
||||
|
||||
assert "worktree" in caplog.text
|
||||
assert "main" in caplog.text
|
||||
|
||||
|
||||
def test_warn_source_tree_mismatch_silent_in_same_tree(
|
||||
tmp_path: Path,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
) -> None:
|
||||
"""Standing in the tree that is running is the normal case and is silent."""
|
||||
tree = _make_checkout(tmp_path / "main")
|
||||
monkeypatch.chdir(tree)
|
||||
monkeypatch.setattr(main, "__file__", str(tree / "esphome" / "__main__.py"))
|
||||
|
||||
with caplog.at_level(logging.WARNING):
|
||||
main._warn_if_source_tree_mismatch()
|
||||
|
||||
assert not caplog.text
|
||||
|
||||
|
||||
def test_warn_source_tree_mismatch_silent_outside_checkout(
|
||||
tmp_path: Path,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
) -> None:
|
||||
"""An ordinary install run from a config directory never warns."""
|
||||
running = _make_checkout(tmp_path / "main")
|
||||
config_dir = tmp_path / "configs"
|
||||
config_dir.mkdir()
|
||||
monkeypatch.chdir(config_dir)
|
||||
monkeypatch.setattr(main, "__file__", str(running / "esphome" / "__main__.py"))
|
||||
|
||||
with caplog.at_level(logging.WARNING):
|
||||
main._warn_if_source_tree_mismatch()
|
||||
|
||||
assert not caplog.text
|
||||
|
||||
|
||||
def test_warn_source_tree_mismatch_silent_in_subdirectory(
|
||||
tmp_path: Path,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
) -> None:
|
||||
"""A subdirectory of the running tree resolves to that tree, so no warning."""
|
||||
tree = _make_checkout(tmp_path / "main")
|
||||
subdir = tree / "esphome" / "components"
|
||||
subdir.mkdir(parents=True)
|
||||
monkeypatch.chdir(subdir)
|
||||
monkeypatch.setattr(main, "__file__", str(tree / "esphome" / "__main__.py"))
|
||||
|
||||
with caplog.at_level(logging.WARNING):
|
||||
main._warn_if_source_tree_mismatch()
|
||||
|
||||
assert not caplog.text
|
||||
|
||||
|
||||
def test_warn_source_tree_mismatch_warns_when_stat_fails_on_other_tree(
|
||||
tmp_path: Path,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
) -> None:
|
||||
"""The samefile() fallback must still warn when the trees really differ."""
|
||||
standing_in = _make_checkout(tmp_path / "worktree")
|
||||
running = _make_checkout(tmp_path / "main")
|
||||
monkeypatch.chdir(standing_in)
|
||||
monkeypatch.setattr(main, "__file__", str(running / "esphome" / "__main__.py"))
|
||||
|
||||
def raise_oserror(self: Path, other: Path) -> bool:
|
||||
raise OSError("stat failed")
|
||||
|
||||
monkeypatch.setattr(Path, "samefile", raise_oserror)
|
||||
|
||||
with caplog.at_level(logging.WARNING):
|
||||
main._warn_if_source_tree_mismatch()
|
||||
|
||||
assert "worktree" in caplog.text
|
||||
|
||||
|
||||
def test_warn_source_tree_mismatch_silent_when_cwd_is_gone(
|
||||
tmp_path: Path,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
) -> None:
|
||||
"""A deleted working directory must not turn the diagnostic into a traceback."""
|
||||
running = _make_checkout(tmp_path / "main")
|
||||
monkeypatch.setattr(main, "__file__", str(running / "esphome" / "__main__.py"))
|
||||
|
||||
def raise_filenotfound() -> Path:
|
||||
raise FileNotFoundError("cwd is gone")
|
||||
|
||||
monkeypatch.setattr(Path, "cwd", staticmethod(raise_filenotfound))
|
||||
|
||||
with caplog.at_level(logging.WARNING):
|
||||
main._warn_if_source_tree_mismatch()
|
||||
|
||||
assert not caplog.text
|
||||
|
||||
|
||||
def test_warn_source_tree_mismatch_falls_back_when_stat_fails(
|
||||
tmp_path: Path,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
) -> None:
|
||||
"""If samefile() cannot stat, fall back to comparing the paths."""
|
||||
tree = _make_checkout(tmp_path / "main")
|
||||
monkeypatch.chdir(tree)
|
||||
monkeypatch.setattr(main, "__file__", str(tree / "esphome" / "__main__.py"))
|
||||
|
||||
def raise_oserror(self: Path, other: Path) -> bool:
|
||||
raise OSError("stat failed")
|
||||
|
||||
monkeypatch.setattr(Path, "samefile", raise_oserror)
|
||||
|
||||
with caplog.at_level(logging.WARNING):
|
||||
main._warn_if_source_tree_mismatch()
|
||||
|
||||
# Same tree, so the path comparison still finds them equal and stays silent
|
||||
assert not caplog.text
|
||||
|
||||
Reference in New Issue
Block a user