Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: [python] Introduce packages option #768

Draft
wants to merge 10 commits into
base: main
Choose a base branch
from
10 changes: 10 additions & 0 deletions src/python/devcontainer-feature.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@
"default": "os-provided",
"description": "Select a Python version to install."
alexander-smolyakov marked this conversation as resolved.
Show resolved Hide resolved
},
"additionalVersions": {
Copy link
Member

Choose a reason for hiding this comment

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

We intentionally did not publicize this option just because it was experimental. Also, it was meant only to be used by universal image.

However, if it works great in different test scenarios then it is worth publicizing 🎉

"type": "string",
"default": "",
"description": "Enter additional Python versions, separated by commas. Use 'X.Y' or 'X.Y.Z' for a specific version"
},
"installTools": {
"type": "boolean",
"default": true,
Expand All @@ -47,6 +52,11 @@
"default": "",
"description": "Configure JupyterLab to accept HTTP requests from the specified origin"
},
"packages": {
"type": "string",
"default": "",
"description": "Optional comma separated list of Python packages to install with pip"
},
"httpProxy": {
"type": "string",
"default": "",
Expand Down
45 changes: 34 additions & 11 deletions src/python/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ CONFIGURE_JUPYTERLAB_ALLOW_ORIGIN="${CONFIGUREJUPYTERLABALLOWORIGIN:-""}"
# alongside PYTHON_VERSION, but not set as default.
ADDITIONAL_VERSIONS="${ADDITIONALVERSIONS:-""}"

# Comma-separated list of packages to be installed
# to Python version specified in PYTHON_VERSION
PYTHON_PACKAGES="${PACKAGES:-""}"

# Import common utils
. ./utils.sh

DEFAULT_UTILS=("pylint" "flake8" "autopep8" "black" "yapf" "mypy" "pydocstyle" "pycodestyle" "bandit" "pipenv" "virtualenv" "pytest")
PYTHON_SOURCE_GPG_KEYS="64E628F8D684696D B26995E310250568 2D347EA6AA65421D FB9921286F5E1540 3A5CA953F73C700D 04C367C218ADD4FF 0EDDC5F26A45C816 6AF053F07D9DC8D2 C9BE28DEE6DF025C 126EB563A74B06BF D9866941EA5BBD71 ED9D77D5 A821E680E5FA6305"
GPG_KEY_SERVERS="keyserver hkp://keyserver.ubuntu.com
Expand Down Expand Up @@ -300,15 +307,6 @@ install_using_oryx() {
add_symlink
}

sudo_if() {
COMMAND="$*"
if [ "$(id -u)" -eq 0 ] && [ "$USERNAME" != "root" ]; then
su - "$USERNAME" -c "$COMMAND"
else
$COMMAND
fi
}

install_user_package() {
alexander-smolyakov marked this conversation as resolved.
Show resolved Hide resolved
INSTALL_UNDER_ROOT="$1"
PACKAGE="$2"
Expand All @@ -317,6 +315,8 @@ install_user_package() {
sudo_if "${PYTHON_SRC}" -m pip install --upgrade --no-cache-dir "$PACKAGE"
else
sudo_if "${PYTHON_SRC}" -m pip install --user --upgrade --no-cache-dir "$PACKAGE"

sudo_if "${PYTHON_SRC}" -m pip show "$PACKAGE"
fi
}

Expand Down Expand Up @@ -473,8 +473,8 @@ if [ "${INSTALL_JUPYTERLAB}" = "true" ]; then
INSTALL_UNDER_ROOT=false
fi

install_user_package $INSTALL_UNDER_ROOT jupyterlab
install_user_package $INSTALL_UNDER_ROOT jupyterlab-git
install_python_package $INSTALL_UNDER_ROOT $PYTHON_SRC jupyterlab
install_python_package $INSTALL_UNDER_ROOT $PYTHON_SRC jupyterlab-git

# Configure JupyterLab if needed
if [ -n "${CONFIGURE_JUPYTERLAB_ALLOW_ORIGIN}" ]; then
Expand All @@ -491,6 +491,29 @@ if [ "${INSTALL_JUPYTERLAB}" = "true" ]; then
fi
fi

# Install pacakages if needed
if [ ! -z "${PYTHON_PACKAGES}" ]; then
if [ -z "${PYTHON_SRC}" ]; then
echo "(!) Could not install packages. Python not found."
exit 1
fi

INSTALL_UNDER_ROOT=true
if [ "$(id -u)" -eq 0 ] && [ "$USERNAME" != "root" ]; then
INSTALL_UNDER_ROOT=false
fi

OLDIFS=$IFS
IFS=","
read -a python_packages <<< "$PYTHON_PACKAGES"
for package in "${python_packages[@]}"; do
name=${test%==*}
version=${test#*==}
install_python_package $INSTALL_UNDER_ROOT $PYTHON_SRC $name $version
done
IFS=$OLDIFS
fi

# Clean up
rm -rf /var/lib/apt/lists/*

Expand Down
33 changes: 33 additions & 0 deletions src/python/utils.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
sudo_if() {
COMMAND="$*"
if [ "$(id -u)" -eq 0 ] && [ "$USERNAME" != "root" ]; then
su - "$USERNAME" -c "$COMMAND"
else
$COMMAND
fi
}

install_python_package() {
INSTALL_UNDER_ROOT="$1"
PYTHON_PATH="$2"
PACKAGE="$3"
VERSION="${4:-""}"

sudo_if "$PYTHON_PATH -m pip uninstall --yes $PACKAGE"

install_command=" -m pip install --upgrade --no-cache-dir "

if [ "$INSTALL_UNDER_ROOT" = false ]; then
install_command+="--user "
fi

install_command+="${PACKAGE}"

if [ ! -z "${VERSION}" ]; then
install_command+="==${VERSION}"
fi

sudo_if "$PYTHON_PATH$install_command"

sudo_if "$PYTHON_PATH -m pip --no-python-version-warning show $PACKAGE"
}
23 changes: 23 additions & 0 deletions test/python/install_packages_mixed.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/bin/bash

set -e

# Optional: Import test library
source dev-container-features-test-lib

# Always run these checks as the non-root user
user="$(whoami)"
check "user" grep vscode <<< "$user"

# Check for an installation of JupyterLab
check "version" jupyter lab --version

# Check location of JupyterLab installation
packages="$(python3 -m pip list)"
check "location" grep jupyter <<< "$packages"

# Check for git extension
check "jupyterlab_git" grep jupyterlab_git <<< "$packages"

# Report result
reportResults
23 changes: 23 additions & 0 deletions test/python/install_packages_non_root.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/bin/bash

set -e

# Optional: Import test library
source dev-container-features-test-lib

# Always run these checks as the non-root user
user="$(whoami)"
check "user" grep vscode <<< "$user"

# Check for an installation of JupyterLab
check "version" jupyter lab --version

# Check location of JupyterLab installation
packages="$(python3 -m pip list)"
check "location" grep jupyter <<< "$packages"

# Check for git extension
check "jupyterlab_git" grep jupyterlab_git <<< "$packages"

# Report result
reportResults
19 changes: 19 additions & 0 deletions test/python/install_packages_root.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/bin/bash

set -e

# Optional: Import test library
source dev-container-features-test-lib

# Check for an installation of JupyterLab
check "version" jupyter lab --version

# Check location of JupyterLab installation
packages="$(python3 -m pip list)"
check "location" grep jupyter <<< "$packages"

# Check for git extension
check "jupyterlab_git" grep jupyterlab_git <<< "$packages"

# Report result
reportResults
23 changes: 23 additions & 0 deletions test/python/install_packages_versions_locked.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/bin/bash

set -e

# Optional: Import test library
source dev-container-features-test-lib

# Always run these checks as the non-root user
user="$(whoami)"
check "user" grep vscode <<< "$user"

# Check for an installation of JupyterLab
check "version" jupyter lab --version

# Check location of JupyterLab installation
packages="$(python3 -m pip list)"
check "location" grep jupyter <<< "$packages"

# Check for git extension
check "jupyterlab_git" grep jupyterlab_git <<< "$packages"

# Report result
reportResults
36 changes: 36 additions & 0 deletions test/python/scenarios.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,5 +81,41 @@
"version": "3.12"
}
}
},
"install_packages_root": {
"image": "debian:bullseye-slim",
"features": {
"python": {
"version": "3.11",
"packages": "jupyterlab,jupyterlab-git"
}
}
},
"install_packages_non_root": {
"image": "mcr.microsoft.com/devcontainers/base:1-ubuntu-22.04",
"features": {
"python": {
"version": "3.11",
"packages": "jupyterlab,jupyterlab-git"
}
}
},
"install_packages_versions_locked": {
"image": "mcr.microsoft.com/devcontainers/base:1-ubuntu-22.04",
"features": {
"python": {
"version": "3.11",
"packages": "cryptography==41.0.5,jupyterlab==4.0.8,jupyterlab-git==0.43.0"
}
}
},
"install_packages_mixed": {
"image": "mcr.microsoft.com/devcontainers/base:1-ubuntu-22.04",
"features": {
"python": {
"version": "3.11",
"packages": "cryptography==41.0.5,jupyterlab,jupyterlab-git==0.43.0"
}
}
}
}
Loading