1
0
mirror of https://github.com/esphome/esphome.git synced 2025-10-12 23:03:46 +01:00
This commit is contained in:
J. Nick Koston
2025-10-08 16:54:55 -10:00
parent f845243f65
commit a944342ccd
2 changed files with 68 additions and 7 deletions

View File

@@ -51,6 +51,32 @@ VALID_BUS_CONFIGS = {
}
def uses_local_file_references(component_dir: Path) -> bool:
"""Check if a component uses local file references via $component_dir.
Components that reference local files cannot be grouped because each needs
a unique component_dir path pointing to their specific directory.
Args:
component_dir: Path to the component's test directory
Returns:
True if the component uses $component_dir for local file references
"""
common_yaml = component_dir / "common.yaml"
if not common_yaml.exists():
return False
try:
content = common_yaml.read_text()
except Exception:
return False
# Pattern to match $component_dir or ${component_dir} references
# These indicate local file usage that prevents grouping
return bool(re.search(r"\$\{?component_dir\}?", content))
def extract_common_buses(yaml_file: Path) -> set[str]:
"""Extract which common bus configs are included in a YAML test file.
@@ -110,23 +136,28 @@ def analyze_component(component_dir: Path) -> dict[str, list[str]]:
return platform_buses
def analyze_all_components(tests_dir: Path = None) -> dict[str, dict[str, list[str]]]:
def analyze_all_components(
tests_dir: Path = None,
) -> tuple[dict[str, dict[str, list[str]]], set[str]]:
"""Analyze all component test directories.
Args:
tests_dir: Path to tests/components directory (defaults to auto-detect)
Returns:
Dictionary mapping component name to platform->buses mapping
Tuple of:
- Dictionary mapping component name to platform->buses mapping
- Set of component names that use local files (cannot be grouped)
"""
if tests_dir is None:
tests_dir = Path("tests/components")
if not tests_dir.exists():
print(f"Error: {tests_dir} does not exist", file=sys.stderr)
return {}
return {}, set()
components = {}
non_groupable = set()
for component_dir in sorted(tests_dir.iterdir()):
if not component_dir.is_dir():
@@ -138,7 +169,11 @@ def analyze_all_components(tests_dir: Path = None) -> dict[str, dict[str, list[s
if platform_buses:
components[component_name] = platform_buses
return components
# Check if component uses local file references
if uses_local_file_references(component_dir):
non_groupable.add(component_name)
return components, non_groupable
def create_grouping_signature(
@@ -226,14 +261,17 @@ def main() -> None:
if args.components:
# Analyze only specified components
components = {}
non_groupable = set()
for comp in args.components:
comp_dir = tests_dir / comp
platform_buses = analyze_component(comp_dir)
if platform_buses:
components[comp] = platform_buses
if uses_local_file_references(comp_dir):
non_groupable.add(comp)
else:
# Analyze all components
components = analyze_all_components(tests_dir)
components, non_groupable = analyze_all_components(tests_dir)
# Output results
if args.group and args.platform:
@@ -256,12 +294,19 @@ def main() -> None:
else:
# Human-readable output
for component, platform_buses in sorted(components.items()):
print(f"{component}:")
non_groupable_marker = (
" [NON-GROUPABLE]" if component in non_groupable else ""
)
print(f"{component}{non_groupable_marker}:")
for platform, buses in sorted(platform_buses.items()):
bus_str = ", ".join(buses)
print(f" {platform}: {bus_str}")
print()
print(f"Total components analyzed: {len(components)}")
if non_groupable:
print(f"Non-groupable components (use local files): {len(non_groupable)}")
for comp in sorted(non_groupable):
print(f" - {comp}")
if __name__ == "__main__":

View File

@@ -331,13 +331,17 @@ def test_components(
print("\n" + "=" * 80)
print("Analyzing components for intelligent grouping...")
print("=" * 80)
component_buses = analyze_all_components(tests_dir)
component_buses, non_groupable = analyze_all_components(tests_dir)
# Group by (platform, bus_signature)
for component, platforms in component_buses.items():
if component not in all_tests:
continue
# Skip components that use local file references
if component in non_groupable:
continue
for platform, buses in platforms.items():
# Skip if platform doesn't match filter
if platform_filter and not platform.startswith(platform_filter):
@@ -352,6 +356,18 @@ def test_components(
print("\nGrouping Plan:")
print("-" * 80)
# Show excluded components
if non_groupable:
excluded_in_tests = [c for c in non_groupable if c in all_tests]
if excluded_in_tests:
print(
f"\n{len(excluded_in_tests)} components excluded from grouping (use local file references):"
)
for comp in sorted(excluded_in_tests[:5]):
print(f" - {comp}")
if len(excluded_in_tests) > 5:
print(f" ... and {len(excluded_in_tests) - 5} more")
groups_to_test = []
individual_tests = []