147 lines
3.5 KiB
Python
147 lines
3.5 KiB
Python
from unittest import mock
|
|
|
|
import pytest
|
|
|
|
from mlflow.utils import PYTHON_VERSION
|
|
from mlflow.utils.environment import _PythonEnv
|
|
|
|
|
|
def test_constructor_argument_validation():
|
|
with pytest.raises(TypeError, match="`python` must be a string"):
|
|
_PythonEnv(python=1)
|
|
|
|
with pytest.raises(TypeError, match="`build_dependencies` must be a list"):
|
|
_PythonEnv(build_dependencies=0)
|
|
|
|
with pytest.raises(TypeError, match="`dependencies` must be a list"):
|
|
_PythonEnv(dependencies=0)
|
|
|
|
|
|
def test_to_yaml(tmp_path):
|
|
yaml_path = tmp_path / "python_env.yaml"
|
|
_PythonEnv(PYTHON_VERSION, ["a"], ["b"]).to_yaml(yaml_path)
|
|
expected_content = f"""
|
|
python: {PYTHON_VERSION}
|
|
build_dependencies:
|
|
- a
|
|
dependencies:
|
|
- b
|
|
""".lstrip()
|
|
assert yaml_path.read_text() == expected_content
|
|
|
|
|
|
def test_from_yaml(tmp_path):
|
|
content = f"""
|
|
python: {PYTHON_VERSION}
|
|
build_dependencies:
|
|
- a
|
|
- b
|
|
dependencies:
|
|
- c
|
|
- d
|
|
"""
|
|
yaml_path = tmp_path / "test.yaml"
|
|
yaml_path.write_text(content)
|
|
python_env = _PythonEnv.from_yaml(yaml_path)
|
|
assert python_env.python == PYTHON_VERSION
|
|
assert python_env.build_dependencies == ["a", "b"]
|
|
assert python_env.dependencies == ["c", "d"]
|
|
|
|
|
|
def test_from_conda_yaml(tmp_path):
|
|
content = f"""
|
|
name: example
|
|
channels:
|
|
- conda-forge
|
|
dependencies:
|
|
- python={PYTHON_VERSION}
|
|
- pip
|
|
- pip:
|
|
- a
|
|
- b
|
|
"""
|
|
yaml_path = tmp_path / "conda.yaml"
|
|
yaml_path.write_text(content)
|
|
python_env = _PythonEnv.from_conda_yaml(yaml_path)
|
|
assert python_env.python == PYTHON_VERSION
|
|
assert python_env.build_dependencies == ["pip"]
|
|
assert python_env.dependencies == ["a", "b"]
|
|
|
|
|
|
def test_from_conda_yaml_build_dependencies(tmp_path):
|
|
content = f"""
|
|
name: example
|
|
channels:
|
|
- conda-forge
|
|
dependencies:
|
|
- python={PYTHON_VERSION}
|
|
- pip=1.2.3
|
|
- wheel==4.5.6
|
|
- setuptools<=7.8.9
|
|
- pip:
|
|
- a
|
|
- b
|
|
"""
|
|
yaml_path = tmp_path / "conda.yaml"
|
|
yaml_path.write_text(content)
|
|
python_env = _PythonEnv.from_conda_yaml(yaml_path)
|
|
assert python_env.python == PYTHON_VERSION
|
|
assert python_env.build_dependencies == ["pip==1.2.3", "wheel==4.5.6", "setuptools<=7.8.9"]
|
|
assert python_env.dependencies == ["a", "b"]
|
|
|
|
|
|
def test_from_conda_yaml_use_current_python_version_when_no_python_spec_in_conda_yaml(tmp_path):
|
|
content = """
|
|
name: example
|
|
channels:
|
|
- conda-forge
|
|
dependencies:
|
|
- pip
|
|
- pip:
|
|
- a
|
|
- b
|
|
"""
|
|
yaml_path = tmp_path / "conda.yaml"
|
|
yaml_path.write_text(content)
|
|
assert _PythonEnv.from_conda_yaml(yaml_path).python == PYTHON_VERSION
|
|
|
|
|
|
def test_from_conda_yaml_invalid_python_comparator(tmp_path):
|
|
content = f"""
|
|
name: example
|
|
channels:
|
|
- conda-forge
|
|
dependencies:
|
|
- python<{PYTHON_VERSION}
|
|
- pip:
|
|
- a
|
|
- b
|
|
"""
|
|
yaml_path = tmp_path / "conda.yaml"
|
|
yaml_path.write_text(content)
|
|
with pytest.raises(Exception, match="Invalid version comparator for python"):
|
|
_PythonEnv.from_conda_yaml(yaml_path)
|
|
|
|
|
|
def test_from_conda_yaml_conda_dependencies_warning(tmp_path):
|
|
content = f"""
|
|
name: example
|
|
channels:
|
|
- conda-forge
|
|
dependencies:
|
|
- python={PYTHON_VERSION}
|
|
- foo
|
|
- bar
|
|
- pip:
|
|
- a
|
|
"""
|
|
yaml_path = tmp_path / "conda.yaml"
|
|
yaml_path.write_text(content)
|
|
with mock.patch("mlflow.utils.environment._logger.warning") as mock_warning:
|
|
_PythonEnv.from_conda_yaml(yaml_path)
|
|
mock_warning.assert_called_with(
|
|
"The following conda dependencies will not be installed "
|
|
"in the resulting environment: %s",
|
|
["foo", "bar"],
|
|
)
|