mirror of
https://github.com/esphome/esphome.git
synced 2025-11-19 08:15:49 +00:00
handle AUTO_LOAD in sensor.py
This commit is contained in:
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
@@ -196,7 +196,7 @@ jobs:
|
|||||||
uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
||||||
with:
|
with:
|
||||||
path: .temp/components_graph.json
|
path: .temp/components_graph.json
|
||||||
key: components-graph-${{ hashFiles('esphome/components/**/__init__.py') }}
|
key: components-graph-${{ hashFiles('esphome/components/**/*.py') }}
|
||||||
- name: Determine which tests to run
|
- name: Determine which tests to run
|
||||||
id: determine
|
id: determine
|
||||||
env:
|
env:
|
||||||
@@ -226,7 +226,7 @@ jobs:
|
|||||||
uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
||||||
with:
|
with:
|
||||||
path: .temp/components_graph.json
|
path: .temp/components_graph.json
|
||||||
key: components-graph-${{ hashFiles('esphome/components/**/__init__.py') }}
|
key: components-graph-${{ hashFiles('esphome/components/**/*.py') }}
|
||||||
|
|
||||||
integration-tests:
|
integration-tests:
|
||||||
name: Run integration tests
|
name: Run integration tests
|
||||||
|
|||||||
@@ -759,7 +759,7 @@ def resolve_auto_load(
|
|||||||
|
|
||||||
@cache
|
@cache
|
||||||
def get_components_graph_cache_key() -> str:
|
def get_components_graph_cache_key() -> str:
|
||||||
"""Generate cache key based on all component __init__.py file hashes.
|
"""Generate cache key based on all component Python file hashes.
|
||||||
|
|
||||||
Uses git ls-files with sha1 hashes to generate a stable cache key that works
|
Uses git ls-files with sha1 hashes to generate a stable cache key that works
|
||||||
across different machines and CI runs. This is faster and more reliable than
|
across different machines and CI runs. This is faster and more reliable than
|
||||||
@@ -769,16 +769,18 @@ def get_components_graph_cache_key() -> str:
|
|||||||
SHA256 hex string uniquely identifying the current component state
|
SHA256 hex string uniquely identifying the current component state
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Use git ls-files -s to get sha1 hashes of all component __init__.py files
|
# Use git ls-files -s to get sha1 hashes of all component Python files
|
||||||
# Format: <mode> <sha1> <stage> <path>
|
# Format: <mode> <sha1> <stage> <path>
|
||||||
# This is fast and works consistently across CI and local dev
|
# This is fast and works consistently across CI and local dev
|
||||||
cmd = ["git", "ls-files", "-s", "esphome/components/**/__init__.py"]
|
# We hash all .py files because AUTO_LOAD, DEPENDENCIES, etc. can be defined
|
||||||
|
# in any Python file, not just __init__.py
|
||||||
|
cmd = ["git", "ls-files", "-s", "esphome/components/**/*.py"]
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
cmd, capture_output=True, text=True, check=True, cwd=root_path, close_fds=False
|
cmd, capture_output=True, text=True, check=True, cwd=root_path, close_fds=False
|
||||||
)
|
)
|
||||||
|
|
||||||
# Hash the git output (includes file paths and their sha1 hashes)
|
# Hash the git output (includes file paths and their sha1 hashes)
|
||||||
# This changes only when component __init__.py files actually change
|
# This changes only when component Python files actually change
|
||||||
hasher = hashlib.sha256()
|
hasher = hashlib.sha256()
|
||||||
hasher.update(result.stdout.encode())
|
hasher.update(result.stdout.encode())
|
||||||
|
|
||||||
|
|||||||
@@ -1109,10 +1109,18 @@ def test_get_component_from_path(
|
|||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def mock_git_output() -> str:
|
def mock_git_output() -> str:
|
||||||
"""Fixture for mock git ls-files output."""
|
"""Fixture for mock git ls-files output with realistic component files.
|
||||||
|
|
||||||
|
Includes examples of AUTO_LOAD in sensor.py and binary_sensor.py files,
|
||||||
|
which is why we need to hash all .py files, not just __init__.py.
|
||||||
|
"""
|
||||||
return (
|
return (
|
||||||
"100644 abc123... 0 esphome/components/wifi/__init__.py\n"
|
"100644 abc123... 0 esphome/components/wifi/__init__.py\n"
|
||||||
"100644 def456... 0 esphome/components/api/__init__.py\n"
|
"100644 def456... 0 esphome/components/api/__init__.py\n"
|
||||||
|
"100644 ghi789... 0 esphome/components/xiaomi_lywsd03mmc/__init__.py\n"
|
||||||
|
"100644 jkl012... 0 esphome/components/xiaomi_lywsd03mmc/sensor.py\n"
|
||||||
|
"100644 mno345... 0 esphome/components/xiaomi_cgpr1/__init__.py\n"
|
||||||
|
"100644 pqr678... 0 esphome/components/xiaomi_cgpr1/binary_sensor.py\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -1163,12 +1171,22 @@ def test_cache_key_consistent_for_same_files(
|
|||||||
|
|
||||||
|
|
||||||
def test_cache_key_different_for_changed_files(mock_subprocess_run: Mock) -> None:
|
def test_cache_key_different_for_changed_files(mock_subprocess_run: Mock) -> None:
|
||||||
"""Test that different git output produces different cache key."""
|
"""Test that different git output produces different cache key.
|
||||||
|
|
||||||
|
This test demonstrates that changes to any .py file (not just __init__.py)
|
||||||
|
will invalidate the cache, which is important because AUTO_LOAD can be
|
||||||
|
defined in sensor.py, binary_sensor.py, etc.
|
||||||
|
"""
|
||||||
mock_result1 = Mock()
|
mock_result1 = Mock()
|
||||||
mock_result1.stdout = "100644 abc123... 0 esphome/components/wifi/__init__.py\n"
|
mock_result1.stdout = (
|
||||||
|
"100644 abc123... 0 esphome/components/xiaomi_lywsd03mmc/sensor.py\n"
|
||||||
|
)
|
||||||
|
|
||||||
mock_result2 = Mock()
|
mock_result2 = Mock()
|
||||||
mock_result2.stdout = "100644 xyz789... 0 esphome/components/wifi/__init__.py\n"
|
# Same file, different hash - simulates a change to AUTO_LOAD
|
||||||
|
mock_result2.stdout = (
|
||||||
|
"100644 xyz789... 0 esphome/components/xiaomi_lywsd03mmc/sensor.py\n"
|
||||||
|
)
|
||||||
|
|
||||||
mock_subprocess_run.return_value = mock_result1
|
mock_subprocess_run.return_value = mock_result1
|
||||||
key1 = helpers.get_components_graph_cache_key()
|
key1 = helpers.get_components_graph_cache_key()
|
||||||
@@ -1197,7 +1215,7 @@ def test_cache_key_uses_git_ls_files(
|
|||||||
"git",
|
"git",
|
||||||
"ls-files",
|
"ls-files",
|
||||||
"-s",
|
"-s",
|
||||||
"esphome/components/**/__init__.py",
|
"esphome/components/**/*.py",
|
||||||
]
|
]
|
||||||
assert call_args[1]["capture_output"] is True
|
assert call_args[1]["capture_output"] is True
|
||||||
assert call_args[1]["text"] is True
|
assert call_args[1]["text"] is True
|
||||||
|
|||||||
Reference in New Issue
Block a user