mirror of
https://github.com/esphome/esphome.git
synced 2025-09-03 11:52:20 +01:00
Implement external custom components installing from YAML (#1630)
* Move components import loading to importlib MetaPathFinder and importlib.resources * Add external_components component * Fix * Fix * fix cv.url return * fix validate shorthand git * implement git refresh * Use finders from sys.path_hooks instead of looking for __init__.py * use github:// schema * error handling * add test * fix handling git output * revert file check handling * fix test * allow full component path be specified for local * fix test * fix path handling * lint Co-authored-by: Guillermo Ruffino <glm.net@gmail.com>
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
from pathlib import Path
|
||||
from typing import Dict
|
||||
|
||||
from esphome.config import iter_components
|
||||
from esphome.const import (
|
||||
@@ -24,6 +26,7 @@ from esphome.helpers import (
|
||||
)
|
||||
from esphome.storage_json import StorageJSON, storage_path
|
||||
from esphome.pins import ESP8266_FLASH_SIZES, ESP8266_LD_SCRIPTS
|
||||
from esphome import loader
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@@ -355,7 +358,7 @@ or use the custom_components folder.
|
||||
|
||||
|
||||
def copy_src_tree():
|
||||
source_files = {}
|
||||
source_files: Dict[Path, loader.SourceFile] = {}
|
||||
for _, component, _ in iter_components(CORE.config):
|
||||
source_files.update(component.source_files)
|
||||
|
||||
@@ -365,37 +368,40 @@ def copy_src_tree():
|
||||
|
||||
# Build #include list for esphome.h
|
||||
include_l = []
|
||||
for target, path in source_files_l:
|
||||
if os.path.splitext(path)[1] in HEADER_FILE_EXTENSIONS:
|
||||
for target, _ in source_files_l:
|
||||
if target.suffix in HEADER_FILE_EXTENSIONS:
|
||||
include_l.append(f'#include "{target}"')
|
||||
include_l.append("")
|
||||
include_s = "\n".join(include_l)
|
||||
|
||||
source_files_copy = source_files.copy()
|
||||
source_files_copy.pop(DEFINES_H_TARGET)
|
||||
ignore_targets = [Path(x) for x in (DEFINES_H_TARGET, VERSION_H_TARGET)]
|
||||
for t in ignore_targets:
|
||||
source_files_copy.pop(t)
|
||||
|
||||
for path in walk_files(CORE.relative_src_path("esphome")):
|
||||
if os.path.splitext(path)[1] not in SOURCE_FILE_EXTENSIONS:
|
||||
for fname in walk_files(CORE.relative_src_path("esphome")):
|
||||
p = Path(fname)
|
||||
if p.suffix not in SOURCE_FILE_EXTENSIONS:
|
||||
# Not a source file, ignore
|
||||
continue
|
||||
# Transform path to target path name
|
||||
target = os.path.relpath(path, CORE.relative_src_path()).replace(
|
||||
os.path.sep, "/"
|
||||
)
|
||||
if target in (DEFINES_H_TARGET, VERSION_H_TARGET):
|
||||
target = p.relative_to(CORE.relative_src_path())
|
||||
if target in ignore_targets:
|
||||
# Ignore defines.h, will be dealt with later
|
||||
continue
|
||||
if target not in source_files_copy:
|
||||
# Source file removed, delete target
|
||||
os.remove(path)
|
||||
p.unlink()
|
||||
else:
|
||||
src_path = source_files_copy.pop(target)
|
||||
copy_file_if_changed(src_path, path)
|
||||
src_file = source_files_copy.pop(target)
|
||||
with src_file.path() as src_path:
|
||||
copy_file_if_changed(src_path, p)
|
||||
|
||||
# Now copy new files
|
||||
for target, src_path in source_files_copy.items():
|
||||
dst_path = CORE.relative_src_path(*target.split("/"))
|
||||
copy_file_if_changed(src_path, dst_path)
|
||||
for target, src_file in source_files_copy.items():
|
||||
dst_path = CORE.relative_src_path(*target.parts)
|
||||
with src_file.path() as src_path:
|
||||
copy_file_if_changed(src_path, dst_path)
|
||||
|
||||
# Finally copy defines
|
||||
write_file_if_changed(
|
||||
|
Reference in New Issue
Block a user