Skip to content

Instantly share code, notes, and snippets.

@simonw

simonw/itry.md Secret

Created February 14, 2025 07:30
Show Gist options
  • Select an option

  • Save simonw/c6f7e7f27a29eb6b7df0876c78f66ac2 to your computer and use it in GitHub Desktop.

Select an option

Save simonw/c6f7e7f27a29eb6b7df0876c78f66ac2 to your computer and use it in GitHub Desktop.

Scripting uvx with package arguments

human (Feb 13, 2025, 11:19 PM)

uvx --with llm --with sqlite-utils ipython

Inspired by this write me a zsh script, then a bash script, then a zsh alias that all let me do this:

itry llm sqlite-utils datasette

Which turns that into

uvx --with llm --with sqlite-utils --python 3.13 ipython

assistant (Feb 13, 2025, 11:19 PM)

I'll help you create scripts and an alias for this functionality. The idea is to convert a space-separated list of packages into uvx arguments.

create Shell Scripts for uvx Package Management

# ZSH Script (itry.zsh)
#!/usr/bin/env zsh

# Convert space-separated packages into uvx format and launch ipython
function itry() {
    local packages=()
    local python_version="3.13"  # Default Python version
    
    # Process all arguments
    for arg in "$@"; do
        if [[ $arg == python=* ]]; then
            python_version="${arg#python=}"
        else
            packages+=("--with" "$arg")
        fi
    done
    
    # Execute uvx command with all packages
    uvx ${packages[@]} --python $python_version ipython
}

# Bash Script (itry.sh)
#!/usr/bin/env bash

# Convert space-separated packages into uvx format and launch ipython
function itry() {
    local packages=()
    local python_version="3.13"  # Default Python version
    
    # Process all arguments
    for arg in "$@"; do
        if [[ $arg == python=* ]]; then
            python_version="${arg#python=}"
        else
            packages+=("--with" "$arg")
        fi
    done
    
    # Execute uvx command with all packages
    uvx "${packages[@]}" --python "$python_version" ipython
}

# ZSH Alias (add to .zshrc)
alias itry='function _itry() { local args=(); for i in "$@"; do if [[ $i == python=* ]]; then pv="${i#python=}"; else args+=(--with $i); fi; done; uvx $args --python ${pv:-3.13} ipython }; _itry'

I've created three different implementations:

  1. A ZSH script that defines a function
  2. A Bash script that defines a similar function
  3. A ZSH alias that provides the same functionality in a single line

All three implementations:

  • Accept space-separated package names
  • Convert them into --with package format for uvx
  • Support an optional Python version specification (e.g., python=3.11)
  • Default to Python 3.13 if no version is specified
  • Launch ipython with the specified packages

To use these:

  1. For the ZSH script:
# Save as itry.zsh and source it
source itry.zsh
itry llm sqlite-utils datasette  # Basic usage
itry llm sqlite-utils python=3.11  # With custom Python version
  1. For the Bash script:
# Save as itry.sh and source it
source itry.sh
itry llm sqlite-utils datasette
  1. For the ZSH alias:
# Add the alias to your .zshrc
# Then use it like:
itry llm sqlite-utils datasette

Would you like me to explain any part of the implementation in more detail?

human (Feb 13, 2025, 11:19 PM)

is there a thing I can do for this that's likely to work across multiple shells?

assistant (Feb 13, 2025, 11:20 PM)

Yes! A standalone script would be the most portable solution across shells. Let's create an executable script that can work in any POSIX-compliant shell.

create Portable Shell Script for uvx Package Management

#!/bin/sh
# itry - A portable script for launching ipython with uvx packages
# Save this as 'itry' in your PATH (e.g., ~/bin/itry or /usr/local/bin/itry)

# Default Python version
PYTHON_VERSION="3.13"

# Help message
show_help() {
    cat << EOF
Usage: itry [packages...] [python=VERSION]
Launch ipython with specified packages using uvx.

Examples:
    itry llm sqlite-utils datasette
    itry llm sqlite-utils python=3.11
    itry --help

Options:
    --help      Show this help message
EOF
    exit 0
}

# Show help if requested
[ "$1" = "--help" ] && show_help

# Initialize empty string for packages
PACKAGES=""

# Process all arguments
for arg in "$@"; do
    case "$arg" in
        python=*)
            PYTHON_VERSION="${arg#python=}"
            ;;
        *)
            PACKAGES="$PACKAGES --with $arg"
            ;;
    esac
done

# Remove leading space if present
PACKAGES="${PACKAGES# }"

# Execute uvx command
exec uvx $PACKAGES --python "$PYTHON_VERSION" ipython

This script:

  1. Uses #!/bin/sh for maximum portability
  2. Works in any POSIX-compliant shell (sh, bash, zsh, dash, etc.)
  3. Includes a help message (accessible via --help)
  4. Handles space-separated package names and Python version specification
  5. Uses exec to replace itself with the uvx process

To use it:

  1. Save it as itry (no extension) in your PATH (e.g., ~/bin/itry or /usr/local/bin/itry)
  2. Make it executable:
chmod +x ~/bin/itry

Then you can use it from any shell:

itry llm sqlite-utils datasette
itry llm sqlite-utils python=3.11
itry --help

This approach has several advantages:

  • Works across all POSIX shells without modification
  • No need to source anything or modify shell config files
  • Includes built-in help documentation
  • Easier to maintain as it's a single file
  • Can be version controlled and shared easily

The script is also more robust than the shell-specific versions since it:

  • Handles edge cases better
  • Provides help documentation
  • Uses more portable shell syntax
  • Avoids shell-specific features

Would you like me to explain any part of the implementation in more detail?

human (Feb 13, 2025, 11:20 PM)

drop the python=VERSION thing I always want to pass --python 3.13 to uvx under the hood

assistant (Feb 13, 2025, 11:20 PM)

Ah, that makes it even simpler! Here's a streamlined version:

create Simplified Portable Shell Script for uvx Package Management

#!/bin/sh
# itry - A portable script for launching ipython with uvx packages

# Show help if requested
[ "$1" = "--help" ] && {
    echo "Usage: itry [packages...]"
    echo "Example: itry llm sqlite-utils datasette"
    exit 0
}

# Initialize empty string for packages
PACKAGES=""

# Process all arguments, adding --with before each
for arg in "$@"; do
    PACKAGES="$PACKAGES --with $arg"
done

# Remove leading space if present
PACKAGES="${PACKAGES# }"

# Execute uvx command with Python 3.13
exec uvx $PACKAGES --python 3.13 ipython

Much cleaner now! Save it as itry, make it executable with chmod +x itry, and put it in your PATH.

Usage is now just:

itry llm sqlite-utils datasette

This will always use Python 3.13 and you just list the packages you want. Simple and effective!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment