71 lines
2.1 KiB
Python
71 lines
2.1 KiB
Python
"""Module to handle installing requirements."""
|
|
import asyncio
|
|
from pathlib import Path
|
|
import logging
|
|
import os
|
|
from typing import Any, Dict, List, Optional
|
|
|
|
import homeassistant.util.package as pkg_util
|
|
from homeassistant.core import HomeAssistant
|
|
|
|
DATA_PIP_LOCK = "pip_lock"
|
|
DATA_PKG_CACHE = "pkg_cache"
|
|
CONSTRAINT_FILE = "package_constraints.txt"
|
|
PROGRESS_FILE = ".pip_progress"
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
|
|
async def async_process_requirements(
|
|
hass: HomeAssistant, name: str, requirements: List[str]
|
|
) -> bool:
|
|
"""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:
|
|
pip_lock = hass.data[DATA_PIP_LOCK] = asyncio.Lock()
|
|
|
|
kwargs = pip_kwargs(hass.config.config_dir)
|
|
|
|
async with pip_lock:
|
|
for req in requirements:
|
|
if pkg_util.is_installed(req):
|
|
continue
|
|
|
|
ret = await hass.async_add_executor_job(_install, hass, req, kwargs)
|
|
|
|
if not ret:
|
|
_LOGGER.error(
|
|
"Not initializing %s because could not install " "requirement %s",
|
|
name,
|
|
req,
|
|
)
|
|
return False
|
|
|
|
return True
|
|
|
|
|
|
def _install(hass: HomeAssistant, req: str, kwargs: Dict) -> bool:
|
|
"""Install requirement."""
|
|
progress_path = Path(hass.config.path(PROGRESS_FILE))
|
|
progress_path.touch()
|
|
try:
|
|
return pkg_util.install_package(req, **kwargs)
|
|
finally:
|
|
progress_path.unlink()
|
|
|
|
|
|
def pip_kwargs(config_dir: Optional[str]) -> Dict[str, Any]:
|
|
"""Return keyword arguments for PIP install."""
|
|
is_docker = pkg_util.is_docker_env()
|
|
kwargs = {
|
|
"constraints": os.path.join(os.path.dirname(__file__), CONSTRAINT_FILE),
|
|
"no_cache_dir": is_docker,
|
|
}
|
|
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 not is_docker:
|
|
kwargs["target"] = os.path.join(config_dir, "deps")
|
|
return kwargs
|