Skip to content

Commit d98a82a

Browse files
reckless: add uv python env installation method
uv is a python installation and package manager written in rust. We can use it to quickly install python package dependencies and configure our plugin's python virtual environment. To maintain consistency with our other reckless python installations, the venv is still activated in a wrapper which then imports the original python source. Changelog-added: reckless can now install python plugins using the uv package manager.
1 parent 50bfad6 commit d98a82a

File tree

1 file changed

+37
-1
lines changed

1 file changed

+37
-1
lines changed

tools/reckless

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -986,6 +986,37 @@ def cargo_installation(cloned_plugin: InstInfo):
986986
return cloned_plugin
987987

988988

989+
def install_python_uv(cloned_plugin: InstInfo):
990+
"""This uses the rust-based python plugin manager uv to manage the python
991+
installation and create a virtual environment."""
992+
993+
source = Path(cloned_plugin.source_loc) / 'source' / cloned_plugin.name
994+
# This virtual env path matches the other python installations and allows
995+
# creating the wrapper in the same manner. Otherwise uv would build it in
996+
# the source/{name} subdirectory.
997+
cloned_plugin.venv = Path('.venv')
998+
999+
# We want the virtual env at the head of our directory structure and uv
1000+
# will need a pyproject.toml there in order to get started.
1001+
(Path(cloned_plugin.source_loc) / 'pyproject.toml').\
1002+
symlink_to(source / 'pyproject.toml')
1003+
1004+
call = ['uv', '-v', 'sync']
1005+
uv = run(call, cwd=str(cloned_plugin.source_loc), stdout=PIPE, stderr=PIPE,
1006+
text=True, check=False)
1007+
if uv.returncode != 0:
1008+
for line in uv.stderr.splitlines():
1009+
log.debug(line)
1010+
log.error('Failed to install virtual environment')
1011+
raise InstallationFailure('Failed to create virtual environment!')
1012+
1013+
# Delete entrypoint symlink so that a venv wrapper can take it's place
1014+
(Path(cloned_plugin.source_loc) / cloned_plugin.entry).unlink()
1015+
1016+
create_wrapper(cloned_plugin)
1017+
return cloned_plugin
1018+
1019+
9891020
python3venv = Installer('python3venv', exe='python3',
9901021
manager='pip', entry='{name}.py')
9911022
python3venv.add_entrypoint('{name}')
@@ -997,6 +1028,7 @@ poetryvenv = Installer('poetryvenv', exe='python3',
9971028
manager='poetry', entry='{name}.py')
9981029
poetryvenv.add_entrypoint('{name}')
9991030
poetryvenv.add_entrypoint('__init__.py')
1031+
poetryvenv.add_dependency_file('poetry.lock')
10001032
poetryvenv.add_dependency_file('pyproject.toml')
10011033
poetryvenv.dependency_call = install_to_python_virtual_environment
10021034

@@ -1007,6 +1039,9 @@ pyprojectViaPip.add_entrypoint('__init__.py')
10071039
pyprojectViaPip.add_dependency_file('pyproject.toml')
10081040
pyprojectViaPip.dependency_call = install_to_python_virtual_environment
10091041

1042+
pythonuv = Installer('pythonuv', exe='python3', manager='uv', entry="{name}.py")
1043+
pythonuv.add_dependency_file('uv.lock')
1044+
pythonuv.dependency_call = install_python_uv
10101045

10111046
# Nodejs plugin installer
10121047
nodejs = Installer('nodejs', exe='node',
@@ -1020,7 +1055,8 @@ rust_cargo = Installer('rust', manager='cargo', entry='Cargo.toml')
10201055
rust_cargo.add_dependency_file('Cargo.toml')
10211056
rust_cargo.dependency_call = cargo_installation
10221057

1023-
INSTALLERS = [python3venv, poetryvenv, pyprojectViaPip, nodejs, rust_cargo]
1058+
INSTALLERS = [pythonuv, python3venv, poetryvenv, pyprojectViaPip, nodejs,
1059+
rust_cargo]
10241060

10251061

10261062
def help_alias(targets: list):

0 commit comments

Comments
 (0)