Skip to content

Commit 496169f

Browse files
committed
Use uv venv instead of python venv when available
Adds a huge speed boost in creating virtualenv by taking advantage of uv when it is found as being installed.
1 parent fde5db1 commit 496169f

File tree

6 files changed

+48
-10
lines changed

6 files changed

+48
-10
lines changed

.config/requirements-test.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ ruff
1212
toml-sort
1313
tox
1414
types-PyYAML
15+
uv

.pre-commit-config.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,12 @@ repos:
101101
hooks:
102102
- id: mypy
103103
additional_dependencies:
104-
- pytest
105104
- pip
105+
- pytest
106106
- subprocess_tee
107107
- types-pyyaml
108108
- types-setuptools
109+
- uv
109110
# Override default pre-commit '--ignore-missing-imports'
110111
args: [--strict]
111112

docs/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ For more information about communication, see the [Ansible communication guide](
2222
- Checks for missing system packages
2323
- Symlinks the current collection into the current python interpreter's site-packages
2424
- Install all collection collection dependencies into the current python interpreter's site-packages
25+
- Uses `uv env` instead of python's venv when available to boost performance. Can be disabled with `SKIP_UV=1`
2526

2627
By placing collections into the python site-packages directory they are discoverable by ansible as well as python and pytest.
2728

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ allow-init-docstring = true
7070
arg-type-hints-in-docstring = false
7171
baseline = ".config/pydoclint-baseline.txt"
7272
check-return-types = false
73-
exclude = '\.git|\.tox|build|out|venv'
73+
exclude = '\.git|\.tox|\.venv|build|out|venv'
7474
should-document-private-class-attributes = true
7575
show-filenames-in-every-violation-message = true
7676
skip-checking-short-docstrings = false

src/ansible_dev_environment/config.py

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from __future__ import annotations
44

55
import json
6+
import logging
67
import os
78
import shutil
89
import subprocess
@@ -21,10 +22,40 @@
2122
from .utils import TermFeatures
2223

2324

24-
class Config:
25-
"""The application configuration."""
25+
_logger = logging.getLogger(__name__)
26+
27+
28+
def use_uv() -> bool:
29+
"""Return whether to use uv commands like venv or pip.
30+
31+
Returns:
32+
True if uv is to be used.
33+
"""
34+
if int(os.environ.get("SKIP_UV", "0")):
35+
return False
36+
try:
37+
import uv # noqa: F401
38+
except ImportError:
39+
pass
40+
else:
41+
_logger.info(
42+
"UV was detect and will be used instead of venv/pip. To disable that define SKIP_UP=1 in your environment.",
43+
)
44+
return True
45+
return False
46+
47+
48+
class Config: # pylint: disable=too-many-instance-attributes
49+
"""The application configuration.
50+
51+
Attributes:
52+
pip_cmd: The pip command.
53+
venv_cmd: The venv command.
54+
"""
55+
56+
pip_cmd: str
57+
venv_cmd: str
2658

27-
# pylint: disable=too-many-instance-attributes
2859
def __init__(
2960
self,
3061
args: Namespace,
@@ -144,11 +175,18 @@ def _set_interpreter(
144175
self,
145176
) -> None:
146177
"""Set the interpreter."""
178+
self.pip_cmd = f"{sys.executable} -m pip"
179+
self.venv_cmd = f"{sys.executable} -m venv"
180+
if use_uv():
181+
self.pip_cmd = f"{sys.executable} -m uv pip"
182+
# seed and python-preference make uv venv match python -m venv behavior:
183+
self.venv_cmd = f"{sys.executable} -m uv venv --seed --python-preference=system"
184+
147185
if not self.venv.exists():
148186
if self._create_venv:
149187
msg = f"Creating virtual environment: {self.venv}"
150188
self._output.debug(msg)
151-
command = f"python -m venv {self.venv}"
189+
command = f"{self.venv_cmd} {self.venv}"
152190
msg = f"Creating virtual environment: {self.venv}"
153191
if self.args.system_site_packages:
154192
command = f"{command} --system-site-packages"

src/ansible_dev_environment/subcommands/installer.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -505,10 +505,7 @@ def _pip_install(self) -> None:
505505
msg = "Installing python requirements."
506506
self._output.info(msg)
507507

508-
command = (
509-
f"{self._config.venv_interpreter} -m pip install"
510-
f" -r {self._config.discovered_python_reqs}"
511-
)
508+
command = f"{self._config.pip_cmd} install" f" -r {self._config.discovered_python_reqs}"
512509

513510
msg = f"Installing python requirements from {self._config.discovered_python_reqs}"
514511
self._output.debug(msg)

0 commit comments

Comments
 (0)