1
0
mirror of https://github.com/esphome/esphome.git synced 2025-10-30 06:33:51 +00:00

Factor PlatformIO buildgen out of writer.py (#9378)

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
Katherine Whitlock
2025-07-21 04:28:11 -04:00
committed by GitHub
parent e485895d97
commit 16a426c182
6 changed files with 226 additions and 146 deletions

View File

@@ -470,6 +470,52 @@ class Library:
return self.as_tuple == other.as_tuple
return NotImplemented
def reconcile_with(self, other):
"""Merge two libraries, reconciling any conflicts."""
if self.name != other.name:
# Different libraries, no reconciliation possible
raise ValueError(
f"Cannot reconcile libraries with different names: {self.name} and {other.name}"
)
# repository specificity takes precedence over version specificity
if self.repository is None and other.repository is None:
pass # No repositories, no conflict, continue on
elif self.repository is None:
# incoming library has a repository, use it
self.repository = other.repository
self.version = other.version
return self
elif other.repository is None:
return self # use the repository/version already present
elif self.repository != other.repository:
raise ValueError(
f"Reconciliation failed! Libraries {self} and {other} requested with conflicting repositories!"
)
if self.version is None and other.version is None:
return self # Arduino library reconciled against another Arduino library, current is acceptable
if self.version is None:
# incoming library has a version, use it
self.version = other.version
return self
if other.version is None:
return self # incoming library has no version, current is acceptable
# Same versions, current library is acceptable
if self.version != other.version:
raise ValueError(
f"Version pinning failed! Libraries {other} and {self} "
"requested with conflicting versions!"
)
return self
# pylint: disable=too-many-public-methods
class EsphomeCore:
@@ -505,8 +551,8 @@ class EsphomeCore:
self.main_statements: list[Statement] = []
# A list of statements to insert in the global block (includes and global variables)
self.global_statements: list[Statement] = []
# A set of platformio libraries to add to the project
self.libraries: list[Library] = []
# A map of platformio libraries to add to the project (shortname: (name, version, repository))
self.platformio_libraries: dict[str, Library] = {}
# A set of build flags to set in the platformio project
self.build_flags: set[str] = set()
# A set of build unflags to set in the platformio project
@@ -550,7 +596,7 @@ class EsphomeCore:
self.variables = {}
self.main_statements = []
self.global_statements = []
self.libraries = []
self.platformio_libraries = {}
self.build_flags = set()
self.build_unflags = set()
self.defines = set()
@@ -738,54 +784,22 @@ class EsphomeCore:
_LOGGER.debug("Adding global: %s", expression)
return expression
def add_library(self, library):
def add_library(self, library: Library):
if not isinstance(library, Library):
raise ValueError(
raise TypeError(
f"Library {library} must be instance of Library, not {type(library)}"
)
for other in self.libraries[:]:
if other.name is None or library.name is None:
continue
library_name = (
library.name if "/" not in library.name else library.name.split("/")[1]
)
other_name = (
other.name if "/" not in other.name else other.name.split("/")[1]
)
if other_name != library_name:
continue
if other.repository is not None:
if library.repository is None or other.repository == library.repository:
# Other is using a/the same repository, takes precedence
break
raise ValueError(
f"Adding named Library with repository failed! Libraries {library} and {other} "
"requested with conflicting repositories!"
)
short_name = (
library.name if "/" not in library.name else library.name.split("/")[-1]
)
if library.repository is not None:
# This is more specific since its using a repository
self.libraries.remove(other)
continue
if library.version is None:
# Other requirement is more specific
break
if other.version is None:
# Found more specific version requirement
self.libraries.remove(other)
continue
if other.version == library.version:
break
raise ValueError(
f"Version pinning failed! Libraries {library} and {other} "
"requested with conflicting versions!"
)
else:
if short_name not in self.platformio_libraries:
_LOGGER.debug("Adding library: %s", library)
self.libraries.append(library)
return library
self.platformio_libraries[short_name] = library
return library
self.platformio_libraries[short_name].reconcile_with(library)
return self.platformio_libraries[short_name]
def add_build_flag(self, build_flag: str) -> str:
self.build_flags.add(build_flag)