Skip to content

Commit 0fbfdc5

Browse files
authored
pyinstaller support added to PipEnv (#19030)
* pyinstaller support added to PipEnv * wip * wip * wip * wip * wip * wip * wip * wip * new test added * _default_python method added * wip * wip * wip * wip
1 parent 97d8643 commit 0fbfdc5

File tree

3 files changed

+68
-2
lines changed

3 files changed

+68
-2
lines changed

conan/internal/model/conf.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@
130130
"tools.system.package_manager:mode": "Mode for package_manager tools: 'check', 'report', 'report-installed' or 'install'",
131131
"tools.system.package_manager:sudo": "Use 'sudo' when invoking the package manager tools in Linux (False by default)",
132132
"tools.system.package_manager:sudo_askpass": "Use the '-A' argument if using sudo in Linux to invoke the system package manager (False by default)",
133+
"tools.system.pipenv:python_interpreter": "Path to the Python interpreter to be used to create the virtualenv",
133134
"tools.apple:sdk_path": "Path to the SDK to be used",
134135
"tools.apple:enable_bitcode": "(boolean) Enable/Disable Bitcode Apple Clang flags",
135136
"tools.apple:enable_arc": "(boolean) Enable/Disable ARC Apple Clang flags",

conan/tools/system/pip_manager.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import venv
21
import platform
32
import os
3+
import shutil
44

55
from conan.tools.build import cmd_args_to_string
66
from conan.tools.env.environment import Environment
7+
from conan.errors import ConanException
78

89

910
class PipEnv:
@@ -23,6 +24,23 @@ def generate(self):
2324
env.prepend_path("PATH", self.bin_dir)
2425
env.vars(self._conanfile).save_script(self.env_name)
2526

27+
@staticmethod
28+
def _default_python():
29+
default_python = shutil.which('python') if platform.system() == "Windows" else shutil.which('python3')
30+
return os.path.realpath(default_python) if default_python else None
31+
32+
def _create_venv(self):
33+
python_interpreter = self._conanfile.conf.get("tools.system.pipenv:python_interpreter") or self._default_python()
34+
if not python_interpreter:
35+
raise ConanException("PipEnv could not find a Python executable path. "
36+
"Please, install Python system-wide or set the 'tools.system.pipenv:python_interpreter' "
37+
"conf to the full path of a Python executable")
38+
39+
try:
40+
self._conanfile.run(cmd_args_to_string([python_interpreter, '-m', 'venv', self._env_dir]))
41+
except ConanException as e:
42+
raise ConanException(f"PipEnv could not create a Python virtual environment using '{python_interpreter}': {e}")
43+
2644
def install(self, packages, pip_args=None):
2745
"""
2846
Will try to install the list of pip packages passed as a parameter.
@@ -34,7 +52,7 @@ def install(self, packages, pip_args=None):
3452
:return: the return code of the executed pip command.
3553
"""
3654

37-
venv.EnvBuilder(clear=True, with_pip=True).create(self._env_dir)
55+
self._create_venv()
3856
args = [self._python_exe, "-m", "pip", "install", "--disable-pip-version-check"]
3957
if pip_args:
4058
args += list(pip_args)
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
from conan.tools.system import PipEnv
2+
from unittest.mock import patch
3+
import pytest
4+
from conan.errors import ConanException
5+
from conan.internal.model.settings import Settings
6+
from conan.test.utils.mocks import ConanFileMock
7+
8+
9+
@patch('shutil.which')
10+
def test_pipenv_conf(mock_shutil_which):
11+
conanfile = ConanFileMock()
12+
conanfile.settings = Settings()
13+
conanfile.conf.define("tools.system.pipenv:python_interpreter", "/python/interpreter/from/config")
14+
result = "/python/interpreter/from/config -m venv"
15+
pipenv = PipEnv(conanfile, "testenv")
16+
17+
def fake_run(command, win_bash=False, subsystem=None, env=None, ignore_errors=False, quiet=False):
18+
assert result in command
19+
return 100
20+
conanfile.run = fake_run
21+
pipenv._create_venv()
22+
mock_shutil_which.assert_not_called()
23+
24+
25+
@patch('shutil.which')
26+
def test_pipenv_error_message(mock_shutil_which):
27+
conanfile = ConanFileMock()
28+
conanfile.settings = Settings()
29+
mock_shutil_which.return_value = None
30+
with pytest.raises(ConanException) as exc_info:
31+
pipenv = PipEnv(conanfile, "testenv")
32+
pipenv._create_venv()
33+
assert "install Python system-wide or set the 'tools.system.pipenv:python_interpreter' conf" in exc_info.value.args[0]
34+
35+
36+
def test_pipenv_creation_error_message():
37+
conanfile = ConanFileMock()
38+
conanfile.settings = Settings()
39+
conanfile.conf.define("tools.system.pipenv:python_interpreter", "/python/interpreter/from/config")
40+
pipenv = PipEnv(conanfile, "testenv")
41+
42+
def fake_run(command, win_bash=False, subsystem=None, env=None, ignore_errors=False, quiet=False):
43+
raise ConanException("fake error message")
44+
conanfile.run = fake_run
45+
with pytest.raises(ConanException) as exc_info:
46+
pipenv._create_venv()
47+
assert "using '/python/interpreter/from/config': fake error message" in exc_info.value.args[0]

0 commit comments

Comments
 (0)