mirror of
https://github.com/esphome/esphome.git
synced 2025-10-11 22:33:49 +01:00
improve grouping of no bus components, they can go into any group, saves another 20m
This commit is contained in:
4
script/analyze_component_buses.py
Normal file → Executable file
4
script/analyze_component_buses.py
Normal file → Executable file
@@ -52,6 +52,10 @@ PACKAGE_DEPENDENCIES = {
|
|||||||
# Components defining these directly cannot be grouped (they create unique bus IDs)
|
# Components defining these directly cannot be grouped (they create unique bus IDs)
|
||||||
DIRECT_BUS_TYPES = ("i2c", "spi", "uart", "modbus")
|
DIRECT_BUS_TYPES = ("i2c", "spi", "uart", "modbus")
|
||||||
|
|
||||||
|
# Signature for components with no bus requirements
|
||||||
|
# These components can be merged with any other group
|
||||||
|
NO_BUSES_SIGNATURE = "no_buses"
|
||||||
|
|
||||||
# Base bus components - these ARE the bus implementations and should not
|
# Base bus components - these ARE the bus implementations and should not
|
||||||
# be flagged as needing migration since they are the platform/base components
|
# be flagged as needing migration since they are the platform/base components
|
||||||
BASE_BUS_COMPONENTS = {
|
BASE_BUS_COMPONENTS = {
|
||||||
|
@@ -206,11 +206,21 @@ def merge_component_configs(
|
|||||||
# Load the component's test file
|
# Load the component's test file
|
||||||
comp_data = load_yaml_file(test_file)
|
comp_data = load_yaml_file(test_file)
|
||||||
|
|
||||||
# Validate packages are identical
|
# Validate packages are compatible
|
||||||
|
# Components with no packages (no_buses) can merge with any group
|
||||||
comp_packages = extract_packages_from_yaml(comp_data)
|
comp_packages = extract_packages_from_yaml(comp_data)
|
||||||
|
|
||||||
if all_packages is None:
|
if all_packages is None:
|
||||||
|
# First component - set the baseline
|
||||||
|
all_packages = comp_packages
|
||||||
|
elif not comp_packages:
|
||||||
|
# This component has no packages (no_buses) - it can merge with any group
|
||||||
|
pass
|
||||||
|
elif not all_packages:
|
||||||
|
# Previous components had no packages, but this one does - adopt these packages
|
||||||
all_packages = comp_packages
|
all_packages = comp_packages
|
||||||
elif comp_packages != all_packages:
|
elif comp_packages != all_packages:
|
||||||
|
# Both have packages but they differ - this is an error
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"Component {comp_name} has different packages than previous components. "
|
f"Component {comp_name} has different packages than previous components. "
|
||||||
f"Expected: {all_packages}, Got: {comp_packages}. "
|
f"Expected: {all_packages}, Got: {comp_packages}. "
|
||||||
|
@@ -22,6 +22,7 @@ sys.path.insert(0, str(Path(__file__).parent.parent))
|
|||||||
|
|
||||||
from script.analyze_component_buses import (
|
from script.analyze_component_buses import (
|
||||||
ISOLATED_COMPONENTS,
|
ISOLATED_COMPONENTS,
|
||||||
|
NO_BUSES_SIGNATURE,
|
||||||
analyze_all_components,
|
analyze_all_components,
|
||||||
create_grouping_signature,
|
create_grouping_signature,
|
||||||
)
|
)
|
||||||
@@ -105,7 +106,7 @@ def create_intelligent_batches(
|
|||||||
break # Only use first platform for grouping
|
break # Only use first platform for grouping
|
||||||
else:
|
else:
|
||||||
# No buses found for any platform - can be grouped together
|
# No buses found for any platform - can be grouped together
|
||||||
signature_groups["no_buses"].append(component)
|
signature_groups[NO_BUSES_SIGNATURE].append(component)
|
||||||
|
|
||||||
# Create batches by keeping signature groups together
|
# Create batches by keeping signature groups together
|
||||||
# Components with the same signature stay in the same batches
|
# Components with the same signature stay in the same batches
|
||||||
|
@@ -28,6 +28,7 @@ sys.path.insert(0, str(Path(__file__).parent.parent))
|
|||||||
# pylint: disable=wrong-import-position
|
# pylint: disable=wrong-import-position
|
||||||
from script.analyze_component_buses import (
|
from script.analyze_component_buses import (
|
||||||
ISOLATED_COMPONENTS,
|
ISOLATED_COMPONENTS,
|
||||||
|
NO_BUSES_SIGNATURE,
|
||||||
analyze_all_components,
|
analyze_all_components,
|
||||||
create_grouping_signature,
|
create_grouping_signature,
|
||||||
is_platform_component,
|
is_platform_component,
|
||||||
@@ -403,11 +404,11 @@ def run_grouped_component_tests(
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
# Create signature for this component's bus configuration
|
# Create signature for this component's bus configuration
|
||||||
# Components with no buses get a signature of "no_buses" so they can be grouped together
|
# Components with no buses get NO_BUSES_SIGNATURE so they can be grouped together
|
||||||
if buses:
|
if buses:
|
||||||
signature = create_grouping_signature({platform: buses}, platform)
|
signature = create_grouping_signature({platform: buses}, platform)
|
||||||
else:
|
else:
|
||||||
signature = "no_buses"
|
signature = NO_BUSES_SIGNATURE
|
||||||
|
|
||||||
# Add to grouped components (including those with no buses)
|
# Add to grouped components (including those with no buses)
|
||||||
if signature:
|
if signature:
|
||||||
@@ -462,6 +463,33 @@ def run_grouped_component_tests(
|
|||||||
f"\n Other non-groupable components: {len(other_reasons)} components"
|
f"\n Other non-groupable components: {len(other_reasons)} components"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Distribute no_buses components into other groups to maximize efficiency
|
||||||
|
# Components with no buses can merge with any bus group since they have no conflicting requirements
|
||||||
|
no_buses_by_platform: dict[str, list[str]] = {}
|
||||||
|
for (platform, signature), components in list(grouped_components.items()):
|
||||||
|
if signature == NO_BUSES_SIGNATURE:
|
||||||
|
no_buses_by_platform[platform] = components
|
||||||
|
# Remove from grouped_components - we'll distribute them
|
||||||
|
del grouped_components[(platform, signature)]
|
||||||
|
|
||||||
|
# Distribute no_buses components into existing groups for each platform
|
||||||
|
for platform, no_buses_comps in no_buses_by_platform.items():
|
||||||
|
# Find all non-empty groups for this platform (excluding no_buses)
|
||||||
|
platform_groups = [
|
||||||
|
(sig, comps)
|
||||||
|
for (plat, sig), comps in grouped_components.items()
|
||||||
|
if plat == platform and sig != NO_BUSES_SIGNATURE
|
||||||
|
]
|
||||||
|
|
||||||
|
if platform_groups:
|
||||||
|
# Distribute no_buses components round-robin across existing groups
|
||||||
|
for i, comp in enumerate(no_buses_comps):
|
||||||
|
sig, _ = platform_groups[i % len(platform_groups)]
|
||||||
|
grouped_components[(platform, sig)].append(comp)
|
||||||
|
else:
|
||||||
|
# No other groups for this platform - keep no_buses components together
|
||||||
|
grouped_components[(platform, NO_BUSES_SIGNATURE)] = no_buses_comps
|
||||||
|
|
||||||
groups_to_test = []
|
groups_to_test = []
|
||||||
individual_tests = set() # Use set to avoid duplicates
|
individual_tests = set() # Use set to avoid duplicates
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user