Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions catkin_virtualenv/cmake/catkin_generate_virtualenv.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ function(catkin_generate_virtualenv)
add_custom_command(COMMENT "Install requirements to ${CMAKE_BINARY_DIR}/${venv_dir}"
OUTPUT ${CMAKE_BINARY_DIR}/${venv_dir}/bin/activate
COMMAND ${CATKIN_ENV} rosrun catkin_virtualenv venv_install ${venv_dir}
--python ${ARG_PYTHON_INTERPRETER}
--requirements ${requirements_list} --extra-pip-args ${processed_pip_args}
DEPENDS
${CMAKE_BINARY_DIR}/${venv_dir}/bin/python
Expand Down
3 changes: 1 addition & 2 deletions catkin_virtualenv/scripts/venv_init
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,8 @@ if __name__ == '__main__':
extra_pip_args = args.extra_pip_args[1:-1]

print(args.use_system_packages)
venv = Virtualenv(args.venv)
venv = Virtualenv(args.venv, python=args.python)
venv.initialize(
python=args.python,
use_system_packages=args.use_system_packages,
extra_pip_args=[arg for arg in extra_pip_args.split(" ") if arg != ""],
)
5 changes: 3 additions & 2 deletions catkin_virtualenv/scripts/venv_install
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import argparse
from catkin_virtualenv import configure_logging
from catkin_virtualenv.venv import Virtualenv


if __name__ == '__main__':
configure_logging()

Expand All @@ -34,12 +33,14 @@ if __name__ == '__main__':
'--requirements', required=True, nargs='+', help="Requirements to sync to virtualenv.")
parser.add_argument(
'--extra-pip-args', default='""', type=str, help="Extra pip args for install.")
parser.add_argument(
'--python', default="python3", help="Build the virtualenv with which python version.")

args = parser.parse_args()

extra_pip_args = args.extra_pip_args[1:-1]

venv = Virtualenv(args.venv)
venv = Virtualenv(args.venv, args.python)
venv.install(
requirements=args.requirements,
extra_pip_args=[arg for arg in extra_pip_args.split(" ") if arg != ""],
Expand Down
27 changes: 15 additions & 12 deletions catkin_virtualenv/src/catkin_virtualenv/venv.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import re
import shutil
import subprocess
import tempfile

try:
from urllib.request import urlretrieve
Expand All @@ -35,7 +34,7 @@

from distutils.spawn import find_executable

from . import run_command, relocate
from . import relocate, run_command
from .collect_requirements import collect_requirements

_BYTECODE_REGEX = re.compile(r".*\.py[co]")
Expand All @@ -45,18 +44,20 @@


class Virtualenv:
def __init__(self, path):
def __init__(self, path, python="python3"):
"""Manage a virtualenv at the specified path."""
self.path = path
self.python = python # eg. python3.12

def initialize(self, python, use_system_packages, extra_pip_args, clean=True):
def initialize(self, use_system_packages, extra_pip_args, clean=True):
"""Initialize a new virtualenv using the specified python version and extra arguments."""
if clean:
try:
shutil.rmtree(self.path)
except Exception:
pass

python = self.python
system_python = find_executable(python)

if not system_python:
Expand All @@ -66,18 +67,20 @@ def initialize(self, python, use_system_packages, extra_pip_args, clean=True):
raise RuntimeError(error_msg)

preinstall = [
"pip==24.0",
"pip-tools==7.4.1",
"pip==25.3",
"pip-tools==7.5.1",
"setuptools", # No-longer preinstalled with python3.14 venvs.
]

builtin_venv = self._check_module(system_python, "venv")
if builtin_venv:
virtualenv = [system_python, "-m", "venv"]
else:
virtualenv = ["virtualenv", "--no-setuptools", "--verbose", "--python", python]
# TODO: This fix for setuptools breaks python2 support. Do we still care about Python2?
# py2's virtualenv command will try install latest setuptools. setuptools>=45 not compatible with py2,
# but we do require a reasonably up-to-date version (because of pip==20.1), so v44 at least.
preinstall += ["setuptools>=44,<45"]
preinstall += ["setuptools"]

if use_system_packages:
virtualenv.append("--system-site-packages")
Expand All @@ -92,27 +95,27 @@ def initialize(self, python, use_system_packages, extra_pip_args, clean=True):
if without_pip:
# install pip via get-pip.py
version_proc = run_command(
["python", "-cimport sys; print('{}.{}'.format(*sys.version_info))"], capture_output=True
[python, "-cimport sys; print('{}.{}'.format(*sys.version_info))"], capture_output=True
)
version = version_proc.stdout
if isinstance(version, bytes):
version = version.decode("utf-8")
version = version.strip()
# download pip from https://bootstrap.pypa.io/pip/
get_pip_path, _ = urlretrieve("https://bootstrap.pypa.io/pip/get-pip.py")
run_command([self._venv_bin("python"), get_pip_path], check=True)
run_command([self._venv_bin(python), get_pip_path], check=True)

# (gservin): test --no-cache-dir
run_command(
[self._venv_bin("python"), "-m", "pip", "install", "--no-cache-dir", "-vvv"] + extra_pip_args + preinstall,
[self._venv_bin(python), "-m", "pip", "install", "--no-cache-dir", "-vvv"] + extra_pip_args + preinstall,
check=True,
)

def install(self, requirements, extra_pip_args):
"""Purge the cache first before installing.""" # (KLAD) testing to debug an issue on build farm
command = [self._venv_bin("python"), "-m", "pip", "cache", "purge"]
command = [self._venv_bin(self.python), "-m", "pip", "cache", "purge"]
""" Sync a virtualenv with the specified requirements.""" # (KLAD) testing no-cache-dir
command = [self._venv_bin("python"), "-m", "pip", "install", "-vvv", "--no-cache-dir"] + extra_pip_args
command = [self._venv_bin(self.python), "-m", "pip", "install", "-vvv", "--no-cache-dir"] + extra_pip_args
for req in requirements:
run_command(command + ["-r", req], check=True)

Expand Down