|
1 | 1 | # type: ignore |
2 | 2 | import json |
3 | 3 | import os |
| 4 | +import subprocess |
4 | 5 | import uuid |
5 | 6 | import zipfile |
6 | 7 | from string import Template |
@@ -52,6 +53,66 @@ def check_config(directory): |
52 | 53 | } |
53 | 54 |
|
54 | 55 |
|
| 56 | +def is_uv_available(): |
| 57 | + """Check if uv command is available in the system.""" |
| 58 | + try: |
| 59 | + subprocess.run(["uv", "--version"], capture_output=True, check=True, timeout=20) |
| 60 | + return True |
| 61 | + except (subprocess.CalledProcessError, FileNotFoundError): |
| 62 | + return False |
| 63 | + except Exception as e: |
| 64 | + console.warning( |
| 65 | + f"An unexpected error occurred while checking uv availability: {str(e)}" |
| 66 | + ) |
| 67 | + return False |
| 68 | + |
| 69 | + |
| 70 | +def is_uv_project(directory): |
| 71 | + """Check if this is a uv project by looking for the uv.lock file.""" |
| 72 | + uv_lock_path = os.path.join(directory, "uv.lock") |
| 73 | + |
| 74 | + # If uv.lock exists, it's definitely a uv project |
| 75 | + if os.path.exists(uv_lock_path): |
| 76 | + return True |
| 77 | + |
| 78 | + return False |
| 79 | + |
| 80 | + |
| 81 | +def run_uv_lock(directory): |
| 82 | + """Run uv lock to update the lock file.""" |
| 83 | + try: |
| 84 | + subprocess.run( |
| 85 | + ["uv", "lock"], |
| 86 | + cwd=directory, |
| 87 | + capture_output=True, |
| 88 | + text=True, |
| 89 | + check=True, |
| 90 | + timeout=60, |
| 91 | + ) |
| 92 | + return True |
| 93 | + except subprocess.CalledProcessError as e: |
| 94 | + console.warning(f"uv lock failed: {e.stderr}") |
| 95 | + return False |
| 96 | + except FileNotFoundError: |
| 97 | + console.warning("uv command not found. Skipping lock file update.") |
| 98 | + return False |
| 99 | + except Exception as e: |
| 100 | + console.warning(f"An unexpected error occurred while running uv lock: {str(e)}") |
| 101 | + return False |
| 102 | + |
| 103 | + |
| 104 | +def handle_uv_operations(directory): |
| 105 | + """Handle uv operations if uv is detected and available.""" |
| 106 | + if not is_uv_available(): |
| 107 | + return |
| 108 | + |
| 109 | + if not is_uv_project(directory): |
| 110 | + return |
| 111 | + |
| 112 | + # Always run uv lock to ensure lock file is up to date |
| 113 | + run_uv_lock(directory) |
| 114 | + |
| 115 | + |
55 | 116 | def generate_operate_file(entryPoints): |
56 | 117 | project_id = str(uuid.uuid4()) |
57 | 118 |
|
@@ -210,7 +271,15 @@ def is_venv_dir(d): |
210 | 271 | ) |
211 | 272 |
|
212 | 273 |
|
213 | | -def pack_fn(projectName, description, entryPoints, version, authors, directory): |
| 274 | +def pack_fn( |
| 275 | + projectName, |
| 276 | + description, |
| 277 | + entryPoints, |
| 278 | + version, |
| 279 | + authors, |
| 280 | + directory, |
| 281 | + include_uv_lock=True, |
| 282 | +): |
214 | 283 | operate_file = generate_operate_file(entryPoints) |
215 | 284 | entrypoints_file = generate_entrypoints_file(entryPoints) |
216 | 285 |
|
@@ -304,7 +373,11 @@ def pack_fn(projectName, description, entryPoints, version, authors, directory): |
304 | 373 | with open(file_path, "r", encoding="latin-1") as f: |
305 | 374 | z.writestr(f"content/{rel_path}", f.read()) |
306 | 375 |
|
307 | | - optional_files = ["pyproject.toml", "README.md", "uv.lock"] |
| 376 | + # Handle optional files, conditionally including uv.lock |
| 377 | + optional_files = ["pyproject.toml", "README.md"] |
| 378 | + if include_uv_lock: |
| 379 | + optional_files.append("uv.lock") |
| 380 | + |
308 | 381 | for file in optional_files: |
309 | 382 | file_path = os.path.join(directory, file) |
310 | 383 | if os.path.exists(file_path): |
@@ -367,8 +440,13 @@ def display_project_info(config): |
367 | 440 |
|
368 | 441 | @click.command() |
369 | 442 | @click.argument("root", type=str, default="./") |
| 443 | +@click.option( |
| 444 | + "--nolock", |
| 445 | + is_flag=True, |
| 446 | + help="Skip running uv lock and exclude uv.lock from the package", |
| 447 | +) |
370 | 448 | @track |
371 | | -def pack(root): |
| 449 | +def pack(root, nolock): |
372 | 450 | """Pack the project.""" |
373 | 451 | version = get_project_version(root) |
374 | 452 |
|
@@ -403,13 +481,18 @@ def pack(root): |
403 | 481 |
|
404 | 482 | with console.spinner("Packaging project ..."): |
405 | 483 | try: |
| 484 | + # Handle uv operations before packaging, unless nolock is specified |
| 485 | + if not nolock: |
| 486 | + handle_uv_operations(root) |
| 487 | + |
406 | 488 | pack_fn( |
407 | 489 | config["project_name"], |
408 | 490 | config["description"], |
409 | 491 | config["entryPoints"], |
410 | 492 | version or config["version"], |
411 | 493 | config["authors"], |
412 | 494 | root, |
| 495 | + include_uv_lock=not nolock, |
413 | 496 | ) |
414 | 497 | display_project_info(config) |
415 | 498 | console.success("Project successfully packaged.") |
|
0 commit comments