2018-01-30 11:30:47 +00:00
|
|
|
"""Module to handle installing requirements."""
|
|
|
|
import asyncio
|
|
|
|
from functools import partial
|
|
|
|
import logging
|
|
|
|
import os
|
2018-08-09 20:53:12 +00:00
|
|
|
from typing import Any, Dict, List, Optional
|
2018-01-30 11:30:47 +00:00
|
|
|
|
|
|
|
import homeassistant.util.package as pkg_util
|
2018-07-23 08:24:39 +00:00
|
|
|
from homeassistant.core import HomeAssistant
|
2018-01-30 11:30:47 +00:00
|
|
|
|
|
|
|
DATA_PIP_LOCK = 'pip_lock'
|
2018-08-28 10:52:18 +00:00
|
|
|
DATA_PKG_CACHE = 'pkg_cache'
|
2018-01-30 11:30:47 +00:00
|
|
|
CONSTRAINT_FILE = 'package_constraints.txt'
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
2018-07-23 08:24:39 +00:00
|
|
|
async def async_process_requirements(hass: HomeAssistant, name: str,
|
|
|
|
requirements: List[str]) -> bool:
|
2018-01-30 11:30:47 +00:00
|
|
|
"""Install the requirements for a component or platform.
|
|
|
|
|
|
|
|
This method is a coroutine.
|
|
|
|
"""
|
|
|
|
pip_lock = hass.data.get(DATA_PIP_LOCK)
|
|
|
|
if pip_lock is None:
|
2019-05-23 04:09:59 +00:00
|
|
|
pip_lock = hass.data[DATA_PIP_LOCK] = asyncio.Lock()
|
2018-01-30 11:30:47 +00:00
|
|
|
|
|
|
|
pip_install = partial(pkg_util.install_package,
|
|
|
|
**pip_kwargs(hass.config.config_dir))
|
|
|
|
|
2018-02-25 11:38:46 +00:00
|
|
|
async with pip_lock:
|
2018-01-30 11:30:47 +00:00
|
|
|
for req in requirements:
|
2019-05-26 18:58:42 +00:00
|
|
|
if pkg_util.is_installed(req):
|
2018-08-28 10:52:18 +00:00
|
|
|
continue
|
|
|
|
|
2018-07-23 08:24:39 +00:00
|
|
|
ret = await hass.async_add_executor_job(pip_install, req)
|
2018-08-28 10:52:18 +00:00
|
|
|
|
2018-01-30 11:30:47 +00:00
|
|
|
if not ret:
|
|
|
|
_LOGGER.error("Not initializing %s because could not install "
|
|
|
|
"requirement %s", name, req)
|
|
|
|
return False
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
2018-08-09 20:53:12 +00:00
|
|
|
def pip_kwargs(config_dir: Optional[str]) -> Dict[str, Any]:
|
2018-01-30 11:30:47 +00:00
|
|
|
"""Return keyword arguments for PIP install."""
|
2019-06-01 08:04:12 +00:00
|
|
|
is_docker = pkg_util.is_docker_env()
|
2018-01-30 11:30:47 +00:00
|
|
|
kwargs = {
|
2019-06-01 08:04:12 +00:00
|
|
|
'constraints': os.path.join(os.path.dirname(__file__),
|
|
|
|
CONSTRAINT_FILE),
|
|
|
|
'no_cache_dir': is_docker,
|
2018-01-30 11:30:47 +00:00
|
|
|
}
|
2019-05-29 22:30:09 +00:00
|
|
|
if 'WHEELS_LINKS' in os.environ:
|
|
|
|
kwargs['find_links'] = os.environ['WHEELS_LINKS']
|
|
|
|
if not (config_dir is None or pkg_util.is_virtual_env()) and \
|
2019-06-01 08:04:12 +00:00
|
|
|
not is_docker:
|
2018-01-30 11:30:47 +00:00
|
|
|
kwargs['target'] = os.path.join(config_dir, 'deps')
|
|
|
|
return kwargs
|