|
| 1 | +"""Implementation of the 'default' command to manage default Python version.""" |
| 2 | + |
| 3 | +import json |
| 4 | +from pathlib import Path as PathlibPath |
| 5 | + |
| 6 | +from .exceptions import ArgumentError, NoInstallsError, NoInstallFoundError |
| 7 | +from .installs import get_installs, get_matching_install_tags |
| 8 | +from .logging import LOGGER |
| 9 | +from .pathutils import Path |
| 10 | +from .tagutils import tag_or_range |
| 11 | + |
| 12 | + |
| 13 | +def _get_default_config_file(install_dir): |
| 14 | + """Get the path to the default install marker file.""" |
| 15 | + return Path(install_dir) / ".default" |
| 16 | + |
| 17 | + |
| 18 | +def _load_default_install_id(install_dir): |
| 19 | + """Load the saved default install ID from the marker file.""" |
| 20 | + try: |
| 21 | + default_file = _get_default_config_file(install_dir) |
| 22 | + if default_file.exists(): |
| 23 | + return default_file.read_text(encoding="utf-8").strip() |
| 24 | + except Exception as e: |
| 25 | + LOGGER.debug("Failed to load default install ID: %s", e) |
| 26 | + return None |
| 27 | + |
| 28 | + |
| 29 | +def _save_default_install_id(install_dir, install_id): |
| 30 | + """Save the default install ID to the marker file.""" |
| 31 | + try: |
| 32 | + default_file = _get_default_config_file(install_dir) |
| 33 | + default_file.parent.mkdir(parents=True, exist_ok=True) |
| 34 | + default_file.write_text(install_id, encoding="utf-8") |
| 35 | + LOGGER.info("Default Python version set to: !G!%s!W!", install_id) |
| 36 | + except Exception as e: |
| 37 | + LOGGER.error("Failed to save default install ID: %s", e) |
| 38 | + raise ArgumentError(f"Could not save default version: {e}") from e |
| 39 | + |
| 40 | + |
| 41 | +def _show_current_default(cmd): |
| 42 | + """Show the currently configured default Python version.""" |
| 43 | + try: |
| 44 | + installs = cmd.get_installs(set_default=False) |
| 45 | + except NoInstallsError: |
| 46 | + LOGGER.info("No Python installations found.") |
| 47 | + return |
| 48 | + |
| 49 | + # Check if there's an explicit default marked |
| 50 | + default_install = None |
| 51 | + for install in installs: |
| 52 | + if install.get("default"): |
| 53 | + default_install = install |
| 54 | + break |
| 55 | + |
| 56 | + if default_install: |
| 57 | + LOGGER.print("!G!Current default:!W! %s", default_install["display-name"]) |
| 58 | + LOGGER.print(" ID: %s", default_install["id"]) |
| 59 | + LOGGER.print(" Version: %s", default_install.get("sort-version", "unknown")) |
| 60 | + else: |
| 61 | + LOGGER.print("!Y!No explicit default set.!W!") |
| 62 | + LOGGER.print("Using tag-based default: !B!%s!W!", cmd.default_tag) |
| 63 | + |
| 64 | + |
| 65 | +def _set_default_version(cmd, tag): |
| 66 | + """Set a specific Python version as the default.""" |
| 67 | + try: |
| 68 | + installs = cmd.get_installs(set_default=False) |
| 69 | + except NoInstallsError: |
| 70 | + raise ArgumentError("No Python installations found. Install a version first with 'py install'.") from None |
| 71 | + |
| 72 | + if not installs: |
| 73 | + raise ArgumentError("No Python installations found. Install a version first with 'py install'.") |
| 74 | + |
| 75 | + # Find the install matching the provided tag |
| 76 | + try: |
| 77 | + tag_obj = tag_or_range(tag) |
| 78 | + except Exception as e: |
| 79 | + raise ArgumentError(f"Invalid tag format: {tag}") from e |
| 80 | + |
| 81 | + matching = get_matching_install_tags( |
| 82 | + installs, |
| 83 | + tag_obj, |
| 84 | + default_platform=cmd.default_platform, |
| 85 | + single_tag=False, |
| 86 | + ) |
| 87 | + |
| 88 | + if not matching: |
| 89 | + raise NoInstallFoundError(tag=tag) |
| 90 | + |
| 91 | + selected_install, selected_run_for = matching[0] |
| 92 | + |
| 93 | + # Save the install ID as the default |
| 94 | + _save_default_install_id(cmd.install_dir, selected_install["id"]) |
| 95 | + |
| 96 | + LOGGER.info("Default Python version set to: !G!%s!W! (%s)", |
| 97 | + selected_install["display-name"], |
| 98 | + selected_install["id"]) |
| 99 | + |
| 100 | + |
| 101 | +def execute(cmd): |
| 102 | + """Execute the default command.""" |
| 103 | + cmd.show_welcome() |
| 104 | + |
| 105 | + if cmd.show_help: |
| 106 | + cmd.help() |
| 107 | + return |
| 108 | + |
| 109 | + if not cmd.args: |
| 110 | + # Show current default |
| 111 | + _show_current_default(cmd) |
| 112 | + else: |
| 113 | + # Set new default |
| 114 | + tag = " ".join(cmd.args[0:1]) # Take the first argument as the tag |
| 115 | + _set_default_version(cmd, tag) |
| 116 | + |
0 commit comments