2018-01-30 12:30:47 +01:00
|
|
|
"""Test requirements module."""
|
|
|
|
import os
|
2019-06-04 20:04:20 +02:00
|
|
|
from pathlib import Path
|
2018-08-28 12:52:18 +02:00
|
|
|
from unittest.mock import patch, call
|
2019-08-08 00:35:50 +02:00
|
|
|
from pytest import raises
|
2018-01-30 12:30:47 +01:00
|
|
|
|
2019-04-15 04:07:05 +02:00
|
|
|
from homeassistant import setup
|
2018-08-28 12:52:18 +02:00
|
|
|
from homeassistant.requirements import (
|
2019-07-31 21:25:30 +02:00
|
|
|
CONSTRAINT_FILE,
|
2019-08-08 00:35:50 +02:00
|
|
|
async_get_integration_with_requirements,
|
2019-07-31 21:25:30 +02:00
|
|
|
async_process_requirements,
|
|
|
|
PROGRESS_FILE,
|
|
|
|
_install,
|
2019-08-08 00:35:50 +02:00
|
|
|
RequirementsNotFound,
|
2019-07-31 21:25:30 +02:00
|
|
|
)
|
2018-08-28 12:52:18 +02:00
|
|
|
|
2019-08-01 16:37:37 +02:00
|
|
|
from tests.common import get_test_home_assistant, MockModule, mock_integration
|
2018-08-28 12:52:18 +02:00
|
|
|
|
2018-01-30 12:30:47 +01:00
|
|
|
|
2019-10-04 22:49:51 +02:00
|
|
|
def env_without_wheel_links():
|
|
|
|
"""Return env without wheel links."""
|
|
|
|
env = dict(os.environ)
|
|
|
|
env.pop("WHEEL_LINKS", None)
|
|
|
|
return env
|
|
|
|
|
|
|
|
|
2018-01-30 12:30:47 +01:00
|
|
|
class TestRequirements:
|
|
|
|
"""Test the requirements module."""
|
|
|
|
|
|
|
|
hass = None
|
|
|
|
backup_cache = None
|
|
|
|
|
|
|
|
# pylint: disable=invalid-name, no-self-use
|
|
|
|
def setup_method(self, method):
|
2018-08-19 22:29:08 +02:00
|
|
|
"""Set up the test."""
|
2018-01-30 12:30:47 +01:00
|
|
|
self.hass = get_test_home_assistant()
|
|
|
|
|
|
|
|
def teardown_method(self, method):
|
|
|
|
"""Clean up."""
|
|
|
|
self.hass.stop()
|
|
|
|
|
2019-07-31 21:25:30 +02:00
|
|
|
@patch("os.path.dirname")
|
|
|
|
@patch("homeassistant.util.package.is_virtual_env", return_value=True)
|
|
|
|
@patch("homeassistant.util.package.is_docker_env", return_value=False)
|
|
|
|
@patch("homeassistant.util.package.install_package", return_value=True)
|
2019-10-04 22:49:51 +02:00
|
|
|
@patch.dict(os.environ, env_without_wheel_links(), clear=True)
|
2018-01-30 12:30:47 +01:00
|
|
|
def test_requirement_installed_in_venv(
|
2019-07-31 21:25:30 +02:00
|
|
|
self, mock_install, mock_denv, mock_venv, mock_dirname
|
|
|
|
):
|
2018-01-30 12:30:47 +01:00
|
|
|
"""Test requirement installed in virtual environment."""
|
2019-07-31 21:25:30 +02:00
|
|
|
mock_dirname.return_value = "ha_package_path"
|
2018-01-30 12:30:47 +01:00
|
|
|
self.hass.config.skip_pip = False
|
2019-07-31 21:25:30 +02:00
|
|
|
mock_integration(self.hass, MockModule("comp", requirements=["package==0.0.1"]))
|
|
|
|
assert setup.setup_component(self.hass, "comp", {})
|
|
|
|
assert "comp" in self.hass.config.components
|
2018-08-28 12:52:18 +02:00
|
|
|
assert mock_install.call_args == call(
|
2019-07-31 21:25:30 +02:00
|
|
|
"package==0.0.1",
|
|
|
|
constraints=os.path.join("ha_package_path", CONSTRAINT_FILE),
|
2019-06-01 10:04:12 +02:00
|
|
|
no_cache_dir=False,
|
|
|
|
)
|
2018-01-30 12:30:47 +01:00
|
|
|
|
2019-07-31 21:25:30 +02:00
|
|
|
@patch("os.path.dirname")
|
|
|
|
@patch("homeassistant.util.package.is_virtual_env", return_value=False)
|
|
|
|
@patch("homeassistant.util.package.is_docker_env", return_value=False)
|
|
|
|
@patch("homeassistant.util.package.install_package", return_value=True)
|
2019-10-04 22:49:51 +02:00
|
|
|
@patch.dict(os.environ, env_without_wheel_links(), clear=True)
|
2018-01-30 12:30:47 +01:00
|
|
|
def test_requirement_installed_in_deps(
|
2019-07-31 21:25:30 +02:00
|
|
|
self, mock_install, mock_denv, mock_venv, mock_dirname
|
|
|
|
):
|
2018-01-30 12:30:47 +01:00
|
|
|
"""Test requirement installed in deps directory."""
|
2019-07-31 21:25:30 +02:00
|
|
|
mock_dirname.return_value = "ha_package_path"
|
2018-01-30 12:30:47 +01:00
|
|
|
self.hass.config.skip_pip = False
|
2019-07-31 21:25:30 +02:00
|
|
|
mock_integration(self.hass, MockModule("comp", requirements=["package==0.0.1"]))
|
|
|
|
assert setup.setup_component(self.hass, "comp", {})
|
|
|
|
assert "comp" in self.hass.config.components
|
2018-08-28 12:52:18 +02:00
|
|
|
assert mock_install.call_args == call(
|
2019-07-31 21:25:30 +02:00
|
|
|
"package==0.0.1",
|
|
|
|
target=self.hass.config.path("deps"),
|
|
|
|
constraints=os.path.join("ha_package_path", CONSTRAINT_FILE),
|
2019-06-01 10:04:12 +02:00
|
|
|
no_cache_dir=False,
|
|
|
|
)
|
2018-08-28 12:52:18 +02:00
|
|
|
|
|
|
|
|
|
|
|
async def test_install_existing_package(hass):
|
|
|
|
"""Test an install attempt on an existing package."""
|
2019-07-31 21:25:30 +02:00
|
|
|
with patch(
|
2019-08-01 16:37:37 +02:00
|
|
|
"homeassistant.util.package.install_package", return_value=True
|
2019-07-31 21:25:30 +02:00
|
|
|
) as mock_inst:
|
2019-08-08 00:35:50 +02:00
|
|
|
await async_process_requirements(hass, "test_component", ["hello==1.0.0"])
|
2018-08-28 12:52:18 +02:00
|
|
|
|
|
|
|
assert len(mock_inst.mock_calls) == 1
|
|
|
|
|
2019-07-31 21:25:30 +02:00
|
|
|
with patch("homeassistant.util.package.is_installed", return_value=True), patch(
|
|
|
|
"homeassistant.util.package.install_package"
|
|
|
|
) as mock_inst:
|
2019-08-08 00:35:50 +02:00
|
|
|
await async_process_requirements(hass, "test_component", ["hello==1.0.0"])
|
2018-08-28 12:52:18 +02:00
|
|
|
|
|
|
|
assert len(mock_inst.mock_calls) == 0
|
2019-05-30 00:30:09 +02:00
|
|
|
|
|
|
|
|
2019-08-08 00:35:50 +02:00
|
|
|
async def test_install_missing_package(hass):
|
|
|
|
"""Test an install attempt on an existing package."""
|
|
|
|
with patch(
|
|
|
|
"homeassistant.util.package.install_package", return_value=False
|
|
|
|
) as mock_inst:
|
|
|
|
with raises(RequirementsNotFound):
|
|
|
|
await async_process_requirements(hass, "test_component", ["hello==1.0.0"])
|
|
|
|
|
|
|
|
assert len(mock_inst.mock_calls) == 1
|
|
|
|
|
|
|
|
|
|
|
|
async def test_get_integration_with_requirements(hass):
|
|
|
|
"""Check getting an integration with loaded requirements."""
|
|
|
|
hass.config.skip_pip = False
|
2019-10-31 19:39:26 +01:00
|
|
|
mock_integration(
|
|
|
|
hass, MockModule("test_component_dep", requirements=["test-comp-dep==1.0.0"])
|
|
|
|
)
|
2019-11-02 01:21:50 +01:00
|
|
|
mock_integration(
|
|
|
|
hass,
|
|
|
|
MockModule(
|
|
|
|
"test_component_after_dep", requirements=["test-comp-after-dep==1.0.0"]
|
|
|
|
),
|
|
|
|
)
|
2019-10-31 19:39:26 +01:00
|
|
|
mock_integration(
|
|
|
|
hass,
|
|
|
|
MockModule(
|
|
|
|
"test_component",
|
|
|
|
requirements=["test-comp==1.0.0"],
|
|
|
|
dependencies=["test_component_dep"],
|
2019-11-02 01:21:50 +01:00
|
|
|
partial_manifest={"after_dependencies": ["test_component_after_dep"]},
|
2019-10-31 19:39:26 +01:00
|
|
|
),
|
|
|
|
)
|
2019-08-08 00:35:50 +02:00
|
|
|
|
|
|
|
with patch(
|
|
|
|
"homeassistant.util.package.is_installed", return_value=False
|
|
|
|
) as mock_is_installed, patch(
|
|
|
|
"homeassistant.util.package.install_package", return_value=True
|
|
|
|
) as mock_inst:
|
|
|
|
|
|
|
|
integration = await async_get_integration_with_requirements(
|
|
|
|
hass, "test_component"
|
|
|
|
)
|
|
|
|
assert integration
|
|
|
|
assert integration.domain == "test_component"
|
|
|
|
|
2019-11-02 01:21:50 +01:00
|
|
|
assert len(mock_is_installed.mock_calls) == 3
|
2019-10-31 19:39:26 +01:00
|
|
|
assert mock_is_installed.mock_calls[0][1][0] == "test-comp==1.0.0"
|
|
|
|
assert mock_is_installed.mock_calls[1][1][0] == "test-comp-dep==1.0.0"
|
2019-11-02 01:21:50 +01:00
|
|
|
assert mock_is_installed.mock_calls[2][1][0] == "test-comp-after-dep==1.0.0"
|
2019-10-31 19:39:26 +01:00
|
|
|
|
2019-11-02 01:21:50 +01:00
|
|
|
assert len(mock_inst.mock_calls) == 3
|
2019-10-31 19:39:26 +01:00
|
|
|
assert mock_inst.mock_calls[0][1][0] == "test-comp==1.0.0"
|
|
|
|
assert mock_inst.mock_calls[1][1][0] == "test-comp-dep==1.0.0"
|
2019-11-02 01:21:50 +01:00
|
|
|
assert mock_inst.mock_calls[2][1][0] == "test-comp-after-dep==1.0.0"
|
2019-08-08 00:35:50 +02:00
|
|
|
|
|
|
|
|
2019-05-30 00:30:09 +02:00
|
|
|
async def test_install_with_wheels_index(hass):
|
|
|
|
"""Test an install attempt with wheels index URL."""
|
|
|
|
hass.config.skip_pip = False
|
2019-07-31 21:25:30 +02:00
|
|
|
mock_integration(hass, MockModule("comp", requirements=["hello==1.0.0"]))
|
|
|
|
|
|
|
|
with patch("homeassistant.util.package.is_installed", return_value=False), patch(
|
|
|
|
"homeassistant.util.package.is_docker_env", return_value=True
|
|
|
|
), patch("homeassistant.util.package.install_package") as mock_inst, patch.dict(
|
|
|
|
os.environ, {"WHEELS_LINKS": "https://wheels.hass.io/test"}
|
|
|
|
), patch(
|
|
|
|
"os.path.dirname"
|
|
|
|
) as mock_dir:
|
|
|
|
mock_dir.return_value = "ha_package_path"
|
|
|
|
assert await setup.async_setup_component(hass, "comp", {})
|
|
|
|
assert "comp" in hass.config.components
|
2019-10-04 22:49:51 +02:00
|
|
|
|
2019-05-30 00:30:09 +02:00
|
|
|
assert mock_inst.call_args == call(
|
2019-07-31 21:25:30 +02:00
|
|
|
"hello==1.0.0",
|
|
|
|
find_links="https://wheels.hass.io/test",
|
|
|
|
constraints=os.path.join("ha_package_path", CONSTRAINT_FILE),
|
2019-06-01 10:04:12 +02:00
|
|
|
no_cache_dir=True,
|
|
|
|
)
|
2019-05-30 00:30:09 +02:00
|
|
|
|
|
|
|
|
|
|
|
async def test_install_on_docker(hass):
|
|
|
|
"""Test an install attempt on an docker system env."""
|
|
|
|
hass.config.skip_pip = False
|
2019-07-31 21:25:30 +02:00
|
|
|
mock_integration(hass, MockModule("comp", requirements=["hello==1.0.0"]))
|
|
|
|
|
|
|
|
with patch("homeassistant.util.package.is_installed", return_value=False), patch(
|
|
|
|
"homeassistant.util.package.is_docker_env", return_value=True
|
|
|
|
), patch("homeassistant.util.package.install_package") as mock_inst, patch(
|
|
|
|
"os.path.dirname"
|
2019-10-04 22:49:51 +02:00
|
|
|
) as mock_dir, patch.dict(
|
|
|
|
os.environ, env_without_wheel_links(), clear=True
|
|
|
|
):
|
2019-07-31 21:25:30 +02:00
|
|
|
mock_dir.return_value = "ha_package_path"
|
|
|
|
assert await setup.async_setup_component(hass, "comp", {})
|
|
|
|
assert "comp" in hass.config.components
|
2019-10-04 22:49:51 +02:00
|
|
|
|
2019-05-30 00:30:09 +02:00
|
|
|
assert mock_inst.call_args == call(
|
2019-07-31 21:25:30 +02:00
|
|
|
"hello==1.0.0",
|
|
|
|
constraints=os.path.join("ha_package_path", CONSTRAINT_FILE),
|
2019-06-01 10:04:12 +02:00
|
|
|
no_cache_dir=True,
|
|
|
|
)
|
2019-06-04 20:04:20 +02:00
|
|
|
|
|
|
|
|
|
|
|
async def test_progress_lock(hass):
|
|
|
|
"""Test an install attempt on an existing package."""
|
|
|
|
progress_path = Path(hass.config.path(PROGRESS_FILE))
|
2019-07-31 21:25:30 +02:00
|
|
|
kwargs = {"hello": "world"}
|
2019-06-04 20:04:20 +02:00
|
|
|
|
|
|
|
def assert_env(req, **passed_kwargs):
|
|
|
|
"""Assert the env."""
|
|
|
|
assert progress_path.exists()
|
2019-07-31 21:25:30 +02:00
|
|
|
assert req == "hello"
|
2019-06-04 20:04:20 +02:00
|
|
|
assert passed_kwargs == kwargs
|
|
|
|
return True
|
|
|
|
|
2019-07-31 21:25:30 +02:00
|
|
|
with patch("homeassistant.util.package.install_package", side_effect=assert_env):
|
|
|
|
_install(hass, "hello", kwargs)
|
2019-06-04 20:04:20 +02:00
|
|
|
|
|
|
|
assert not progress_path.exists()
|