Last active
May 23, 2025 23:41
-
-
Save pmolodo/9550e0643645caf61e275a8b1298e775 to your computer and use it in GitHub Desktop.
Installs the uv tool in a .uv subdirectory of this folder
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
"""Installs the uv tool in a .uv subdirectory of this folder""" | |
import argparse | |
import enum | |
import inspect | |
import os | |
import shutil | |
import subprocess | |
import sys | |
import traceback | |
import urllib.request | |
############################################################################### | |
# Constants | |
############################################################################### | |
THIS_FILE = os.path.abspath(inspect.getsourcefile(lambda: None) or __file__) | |
THIS_DIR = os.path.dirname(THIS_FILE) | |
DEFAULT_UV_DIR = os.path.join(THIS_DIR, ".uv") | |
# Note that even if you install with the .sh on windows, it will autodetect platform | |
# and download uv.exe | |
UV_FILENAME = "uv.exe" if sys.platform == "win32" else "uv" | |
INSTALL_SH_URL = "https://astral.sh/uv/install.sh" | |
INSTALL_PS1_URL = "https://astral.sh/uv/install.ps1" | |
############################################################################### | |
# Utilities | |
############################################################################### | |
def download_url(url: str, output_path: str): | |
with urllib.request.urlopen(url) as response, open(output_path, "wb") as out_file: | |
shutil.copyfileobj(response, out_file) | |
############################################################################### | |
# Core Functions | |
############################################################################### | |
class ScriptType(enum.Enum): | |
POWERSHELL = 1 | |
SH = 2 | |
@classmethod | |
def by_host(cls): | |
return cls.POWERSHELL if sys.platform == "win32" else cls.SH | |
def install_environ(uv_dir): | |
# $XDG_BIN_HOME will set the install directory | |
env = dict(os.environ) | |
env["XDG_BIN_HOME"] = uv_dir | |
env["UV_NO_MODIFY_PATH"] = "1" | |
return env | |
def uv_install(uv_dir=DEFAULT_UV_DIR, script_type: ScriptType | None = None, add_to_path=True): | |
uv_path = os.path.join(uv_dir, UV_FILENAME) | |
if os.path.isfile(uv_path): | |
return | |
if script_type is None: | |
script_type = ScriptType.by_host() | |
if not os.path.isdir(uv_dir): | |
os.makedirs(uv_dir) | |
match script_type: | |
case ScriptType.POWERSHELL: | |
install_script_filename = "install_uv.ps1" | |
install_url = INSTALL_PS1_URL | |
install_args = ["powershell", "-ExecutionPolicy", "ByPass"] | |
case ScriptType.SH: | |
install_script_filename = "install_uv.sh" | |
install_url = INSTALL_SH_URL | |
install_args = ["sh"] | |
case _: | |
raise ValueError(f"unrecognized script_type: {script_type}") | |
install_script_path = os.path.join(uv_dir, install_script_filename) | |
download_url(install_url, install_script_path) | |
install_args.append(install_script_path) | |
subprocess.run(install_args, env=install_environ(uv_dir=uv_dir)) | |
os.remove(install_script_path) | |
if add_to_path: | |
# only adds to the path for the current python process | |
path = [x for x in os.environ.get("PATH", "").split(os.pathsep) if x] | |
if DEFAULT_UV_DIR not in path: | |
path.append(DEFAULT_UV_DIR) | |
os.environ["PATH"] = os.pathsep.join(path) | |
return uv_path | |
def uv(args, uv_dir=) | |
############################################################################### | |
# CLI | |
############################################################################### | |
def get_parser(): | |
parser = argparse.ArgumentParser( | |
description=__doc__, | |
formatter_class=argparse.ArgumentDefaultsHelpFormatter, | |
) | |
parser.add_argument( | |
"-u", "--uv-dir", help="Path to the folder to install the uv executable in", default=DEFAULT_UV_DIR | |
) | |
osgroup = parser.add_mutually_exclusive_group() | |
osgroup.add_argument( | |
"-s", | |
"--sh", | |
dest="script_type", | |
action="store_const", | |
const=ScriptType.SH, | |
help=f"Force install via {INSTALL_SH_URL}", | |
) | |
osgroup.add_argument( | |
"-p", | |
"--powershell", | |
dest="script_type", | |
action="store_const", | |
const=ScriptType.POWERSHELL, | |
help=f"Force install via {INSTALL_PS1_URL}", | |
) | |
return parser | |
def main(argv=None): | |
if argv is None: | |
argv = sys.argv[1:] | |
parser = get_parser() | |
args = parser.parse_args(argv) | |
try: | |
uv_install(uv_dir=args.uv_dir, script_type=args.script_type) | |
except Exception: # pylint: disable=broad-except | |
traceback.print_exc() | |
return 1 | |
return 0 | |
if __name__ == "__main__": | |
sys.exit(main()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment