diff --git a/generators/VirtualPythonEnv.py b/generators/VirtualPythonEnv.py index 8d7c998..d797f07 100644 --- a/generators/VirtualPythonEnv.py +++ b/generators/VirtualPythonEnv.py @@ -9,6 +9,8 @@ from jinja2 import Template from conan.tools.env import VirtualRunEnv from conans.model import Generator +from conans.errors import ConanException +from conans import tools class VirtualPythonEnv(Generator): @@ -31,16 +33,42 @@ class VirtualPythonEnv(Generator): @property def content(self): - if hasattr(self.conanfile, "_python_interpreter"): - python_interpreter = self.conanfile._python_interpreter + from platform import python_version + py_version = python_version() + py_version = self.conanfile.options.get_safe("python_version", py_version) + if py_version == python_version(): + python_interpreter = Path(sys.executable) else: - python_interpreter = sys.executable - - self.conanfile.run(f"{python_interpreter} -m venv {self.conanfile.build_folder}", env = "conanrun") - python_interpreter = os.path.join(self.conanfile.build_folder, self._venv_path, "python") + # Need to find the requested Python version + # Assuming they're all installed along-side each other + current_py_base_version = f"{tools.Version(python_version()).major}{tools.Version(python_version()).minor}" + py_base_version = f"{tools.Version(py_version).major}{tools.Version(py_version).minor}" + base_exec_prefix = sys.exec_prefix.split(current_py_base_version) + if len(base_exec_prefix) != 2: + raise ConanException(f"Could not find requested Python version {py_version}") + py_exec_prefix = Path(base_exec_prefix[0] + py_base_version) + py_exec = Path(sys.executable) + python_interpreter = py_exec_prefix.joinpath(py_exec.stem + py_exec.suffix) + if not python_interpreter.exists(): + raise ConanException(f"Could not find requested Python executable at: {python_interpreter}") + + # When on Windows execute as Windows Path + if self.conanfile.settings.os == "Windows": + python_interpreter = Path(*[f"'{p}'" if " " in p else p for p in python_interpreter.parts]) + + # Create the virtual environment + self.conanfile.run(f"""{python_interpreter} -m venv {self.conanfile.folders.build}""", env = "conanrun") + + # + python_venv_interpreter = Path(self.conanfile.build_folder, self._venv_path, + Path(sys.executable).stem + Path(sys.executable).suffix) + if not python_venv_interpreter.exists(): + raise ConanException(f"Virtual environment Python interpreter not found at: {python_venv_interpreter}") + if self.conanfile.settings.os == "Windows": + python_venv_interpreter = Path(*[f"'{p}'" if " " in p else p for p in python_venv_interpreter.parts]) buffer = StringIO() - self.conanfile.run(f"""{python_interpreter} -c 'import sysconfig; print(sysconfig.get_path("purelib"))'""", env = "conanrun", + self.conanfile.run(f"""{python_venv_interpreter} -c "import sysconfig; print(sysconfig.get_path('purelib'))""""", env = "conanrun", output = buffer) pythonpath = buffer.getvalue().splitlines()[-1] @@ -58,17 +86,36 @@ class VirtualPythonEnv(Generator): if hasattr(self.conanfile, "requirements_txts"): if self.conanfile.requirements_txts: if hasattr(self.conanfile.requirements_txts, "__iter__") and not isinstance(self.conanfile.requirements_txts, str): + # conanfile has a list of requirements_txts specified for req_txt in self.conanfile.requirements_txts: with envvars.apply(): - self.conanfile.run( - f"{python_interpreter} -m pip install -r {os.path.join(self.conanfile.source_folder, req_txt)}", - run_environment = True, env = "conanrun") + requirements_txt_path = Path(self.conanfile.source_folder, req_txt) + if requirements_txt_path.exists(): + self.conanfile.run(f"""{python_venv_interpreter} -m pip install -r {requirements_txt_path}""", + run_environment = True, env = "conanrun", + win_bash = self.conanfile.settings.os == "Windows") + else: + self.conanfile.output.warn(f"Failed to find pip requirement file: {requirements_txt_path}") else: + # conanfile has a single requirements_txt specified with envvars.apply(): - self.conanfile.run( - f"{python_interpreter} -m pip install -r {os.path.join(self.conanfile.source_folder, self.conanfile.requirements_txts)}", - run_environment = True, env = "conanrun") + requirements_txt_path = Path(self.conanfile.source_folder, self.conanfile.requirements_txts) + if requirements_txt_path.exists(): + self.conanfile.run(f"""{python_venv_interpreter} -m pip install -r {requirements_txt_path}""", + run_environment = True, env = "conanrun") + else: + self.conanfile.output.warn(f"Failed to find pip requirement file: {requirements_txt_path}") + else: + # No requirements_txts found in the conanfile looking for a requirements.txt in the source_folder + requirements_txt_path = Path(self.conanfile.source_folder, "requirements.txt") + if requirements_txt_path.exists(): + with envvars.apply(): + self.conanfile.run(f"""{python_venv_interpreter} -m pip install -r {requirements_txt_path}""", run_environment = True, + env = "conanrun") + else: + self.conanfile.output.warn(f"Failed to find pip requirement file: {requirements_txt_path}") + # Generate the Python Virtual Environment Script template = Template("""\ deactivate() {