Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 89 additions & 5 deletions plugins/pip/venvShellHook.sh
Original file line number Diff line number Diff line change
@@ -1,8 +1,92 @@
#!/bin/sh
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why get rid of the shebang?

set -eu
STATE_FILE="$DEVBOX_PROJECT_ROOT/.devbox/venv_check_completed"
echo $STATE_FILE
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this left in from debugging?


if ! [ -d "$VENV_DIR" ]; then
echo "Creating new venv environment in path: '${VENV_DIR}'"
python3 -m venv "$VENV_DIR"
echo "You can activate the virtual environment by running '. \$VENV_DIR/bin/activate' (for fish shell, replace '.' with 'source')" >&2
is_valid_venv() {
[ -f "$1/bin/activate" ] && [ -f "$1/bin/python" ]
}

# Function to check if Python is a symlink to a Devbox Python
is_devbox_python() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's also the test -ef flag to check if two files are the same. So you could do:

if [ "$1/bin/python" -ef "$DEVBOX_PACKAGES_DIR/bin/python" ]; then

if [ -z "$DEVBOX_PACKAGES_DIR" ]; then
echo "DEVBOX_PACKAGES_DIR is not set. Unable to check for Devbox Python."
return 1
fi
local python_path="$1/bin/python"
local link_target

while true; do
if [ ! -L "$python_path" ]; then
# Not a symlink, we're done
break
fi

link_target=$(readlink "$python_path")
echo "Checking symlink: $link_target"

if [[ "$link_target" == /* ]]; then
# Absolute path, we're done
python_path="$link_target"
break
elif [[ "$link_target" == python* ]] || [[ "$link_target" == ./* ]] || [[ "$link_target" == ../* ]]; then
# Relative path or python symlink, continue resolving
python_path=$(dirname "$python_path")/"$link_target"
else
# Unexpected format, stop here
break
fi
done

[[ $python_path == $DEVBOX_PACKAGES_DIR/* ]]
}

# Function to check Python version
check_python_version() {
python_version=$(python -c 'import sys; print(".".join(map(str, sys.version_info[:2])))')
if [ "$(printf '%s\n' "3.3" "$python_version" | sort -V | head -n1)" = "3.3" ]; then
return 0
else
return 1
fi
}

# Check if we've already run this script
if [ -f "$STATE_FILE" ]; then
# "We've already run this script. Exiting..."
exit 0
fi

# Check Python version
if ! check_python_version; then
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we just checking the version to see if venv is available? If so, it might be easier to just try importing it.

Suggested change
if ! check_python_version; then
if ! python -c "import venv" &>/dev/null; then

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah that's a much nicer approach

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Had to tweak this because for some reason it was failing the automated tests (but not when run locally)

echo "\033[1;33mWARNING: Python version must be > 3.3 to create a virtual environment.\033[0m"
touch "$STATE_FILE"
exit 1
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this work after the user has updated their python version?

i.e. by creating the state-file, will it skip running again to create the venv after upgrading python

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it should, because the python in the venv is a symlink to the python in our Devbox profile, which is a symlink to the nix store. I'll test a few times to make sure

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed, once the .venv is created, updating python automatically updates the python linked in the .venv folder

fi

# Check if the directory exists
if [ -d "$VENV_DIR" ]; then
if is_valid_venv "$VENV_DIR"; then
if ! is_devbox_python "$VENV_DIR"; then
echo "\033[1;33mWARNING: Virtual environment at $VENV_DIR doesn't use Devbox Python.\033[0m"
echo "Virtual environment: $VENV_DIR"
read -p "Do you want to overwrite it? (y/n) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
echo "Overwriting existing virtual environment..."
rm -rf "$VENV_DIR"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can use python3 -m venv --clear to overwrite.

python3 -m venv "$VENV_DIR"
else
echo "Using existing virtual environment. We recommend changing \$VENV_DIR"
touch "$STATE_FILE"
exit 1
fi
fi
else
echo "Directory exists but is not a valid virtual environment. Creating new one..."
rm -rf "$VENV_DIR"
python -m venv "$VENV_DIR"
fi
else
echo "Virtual environment directory doesn't exist. Creating new one..."
python -m venv "$VENV_DIR"
fi
16 changes: 5 additions & 11 deletions plugins/python.json
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
{
"name": "python",
"version": "0.0.3",
"description": "Python in Devbox works best when used with a virtual environment (vent, virtualenv, etc.). Devbox will automatically create a virtual environment using `venv` for python3 projects, so you can install packages with pip as normal.\nTo activate the environment, run `. $VENV_DIR/bin/activate` or add it to the init_hook of your devbox.json\nTo change where your virtual environment is created, modify the $VENV_DIR environment variable in your init_hook",
"version": "0.0.4",
"description": "Python in Devbox works best when used with a virtual environment (venv, virtualenv, etc.). Devbox will automatically create a virtual environment using `venv` for python3 projects, so you can install packages with pip as normal.\nTo activate the environment, run `. $VENV_DIR/bin/activate` or add it to the init_hook of your devbox.json\nTo change where your virtual environment is created, modify the $VENV_DIR environment variable in your init_hook",
"env": {
/*
This is a block comment
*/
"VENV_DIR": "{{ .Virtenv }}/.venv"
"VENV_DIR": "{{ .DevboxProjectDir }}/.venv"
},
"create_files": {
"{{ .Virtenv }}/bin/venvShellHook.sh": "pip/venvShellHook.sh"
"{{ .Virtenv }}/bin/venvShellHook.sh": "pip/venvShellHook.sh"
},
// this is a line comment above shell
"shell": {
"init_hook": [
"{{ .Virtenv }}/bin/venvShellHook.sh"
]
"init_hook": ["{{ .Virtenv }}/bin/venvShellHook.sh"]
}
}
Loading