mirror of
https://github.com/esphome/esphome.git
synced 2024-11-26 08:55:22 +01:00
Add custom component mechanism
This commit is contained in:
parent
b7afb8c887
commit
db0dd6af09
1 changed files with 42 additions and 3 deletions
|
@ -7,6 +7,7 @@ import re
|
||||||
import os.path
|
import os.path
|
||||||
|
|
||||||
# pylint: disable=unused-import, wrong-import-order
|
# pylint: disable=unused-import, wrong-import-order
|
||||||
|
import sys
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
@ -17,7 +18,7 @@ from esphome.components.substitutions import CONF_SUBSTITUTIONS
|
||||||
from esphome.const import CONF_ESPHOME, CONF_PLATFORM, ESP_PLATFORMS
|
from esphome.const import CONF_ESPHOME, CONF_PLATFORM, ESP_PLATFORMS
|
||||||
from esphome.core import CORE, EsphomeError # noqa
|
from esphome.core import CORE, EsphomeError # noqa
|
||||||
from esphome.helpers import color, indent
|
from esphome.helpers import color, indent
|
||||||
from esphome.py_compat import text_type
|
from esphome.py_compat import text_type, IS_PY2
|
||||||
from esphome.util import safe_print, OrderedDict
|
from esphome.util import safe_print, OrderedDict
|
||||||
|
|
||||||
from typing import List, Optional, Tuple, Union # noqa
|
from typing import List, Optional, Tuple, Union # noqa
|
||||||
|
@ -106,15 +107,53 @@ class ComponentManifest(object):
|
||||||
|
|
||||||
|
|
||||||
CORE_COMPONENTS_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), 'components'))
|
CORE_COMPONENTS_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), 'components'))
|
||||||
|
_UNDEF = object()
|
||||||
|
CUSTOM_COMPONENTS_PATH = _UNDEF
|
||||||
|
|
||||||
|
|
||||||
|
def _mount_config_dir():
|
||||||
|
global CUSTOM_COMPONENTS_PATH
|
||||||
|
if CUSTOM_COMPONENTS_PATH is not _UNDEF:
|
||||||
|
return
|
||||||
|
custom_path = os.path.abspath(os.path.join(CORE.config_dir, 'custom_components'))
|
||||||
|
if not os.path.isdir(custom_path):
|
||||||
|
CUSTOM_COMPONENTS_PATH = None
|
||||||
|
return
|
||||||
|
init_path = os.path.join(custom_path, '__init__.py')
|
||||||
|
if IS_PY2 and not os.path.isfile(init_path):
|
||||||
|
_LOGGER.warning("Found 'custom_components' folder, but file __init__.py was not found. "
|
||||||
|
"ESPHome will automatically create it now....")
|
||||||
|
with open(init_path, 'w') as f:
|
||||||
|
f.write('\n')
|
||||||
|
if CORE.config_dir not in sys.path:
|
||||||
|
sys.path.insert(0, CORE.config_dir)
|
||||||
|
CUSTOM_COMPONENTS_PATH = custom_path
|
||||||
|
|
||||||
|
|
||||||
def _lookup_module(domain, is_platform):
|
def _lookup_module(domain, is_platform):
|
||||||
if domain in _COMPONENT_CACHE:
|
if domain in _COMPONENT_CACHE:
|
||||||
return _COMPONENT_CACHE[domain]
|
return _COMPONENT_CACHE[domain]
|
||||||
|
|
||||||
path = 'esphome.components.{}'.format(domain)
|
_mount_config_dir()
|
||||||
|
# First look for custom_components
|
||||||
try:
|
try:
|
||||||
module = importlib.import_module(path)
|
module = importlib.import_module('custom_components.{}'.format(domain))
|
||||||
|
except ImportError as e:
|
||||||
|
# ImportError when no such module
|
||||||
|
if 'No module named' not in str(e):
|
||||||
|
_LOGGER.warn("Unable to import custom component %s:", domain, exc_info=True)
|
||||||
|
except Exception: # pylint: disable=broad-except
|
||||||
|
# Other error means component has an issue
|
||||||
|
_LOGGER.error("Unable to load custom component %s:", domain, exc_info=True)
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
# Found in custom components
|
||||||
|
manif = ComponentManifest(module, CUSTOM_COMPONENTS_PATH, is_platform=is_platform)
|
||||||
|
_COMPONENT_CACHE[domain] = manif
|
||||||
|
return manif
|
||||||
|
|
||||||
|
try:
|
||||||
|
module = importlib.import_module('esphome.components.{}'.format(domain))
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
if 'No module named' in str(e):
|
if 'No module named' in str(e):
|
||||||
_LOGGER.error("Unable to import component %s:", domain)
|
_LOGGER.error("Unable to import component %s:", domain)
|
||||||
|
|
Loading…
Reference in a new issue