infra_virtualenv: Introduce python_venv.
This change will introduce a new script `python_venv` which
transparently executes a Python interpreter in a virtualenv,
possibly creating a new virtualenv if it has not been created
yet.
This script is a better replacement to `find_virtualenv.sh`
because:
1. `python_venv` does not require to be sourced from bash.
This allows any program (e.g. Python) to run a Python
interpreter in a virtualenv. Also it makes it easy to run
an interactive Python shell in a virtualenv, which is
convenient to manually inspect the virtualenv environment
for debug.
2. `python_venv` can be called from any working directory,
which makes the caller code simpler.
BUG=chromium:733103
TEST=bin/run_tests
TEST=bin/turtle
Change-Id: I94e85a3f3e5ec31d29094e273f0ff9466a8405a2
Reviewed-on: https://chromium-review.googlesource.com/563279
Commit-Ready: Shuhei Takahashi <nya@chromium.org>
Tested-by: Shuhei Takahashi <nya@chromium.org>
Reviewed-by: Shuhei Takahashi <nya@chromium.org>
diff --git a/README.md b/README.md
index 21252ed..87f3428 100644
--- a/README.md
+++ b/README.md
@@ -14,8 +14,7 @@
directory will be importable inside the virtualenv.
2. Create a `requirements.txt` file inside `venv` to list external
packages to install.
-3. Copy `bin/find_virtualenv.sh` and `bin/turtle` which serve as
- templates.
+3. Copy `bin/python_venv` and `bin/turtle` which serve as templates.
Adding pre-built packages
-------------------------
@@ -29,10 +28,10 @@
Low level API
-------------
-The `create_venv` script prepares a virtualenv using a
+The `bin/create_venv` script prepares a virtualenv using a
`requirements.txt` file.
- $ create_venv requirements.txt
+ $ bin/create_venv requirements.txt
The script will print the path to the virtualenv to stdout. Note that
the output ends with a newline; Bash handles this, but Python does
@@ -43,7 +42,7 @@
Together, this might look up:
- $ venv=$(create_venv requirements.txt)
+ $ venv=$(bin/create_venv requirements.txt)
$ ${venv}/bin/python
NOTE: it is not generally safe to run the other scripts in the
diff --git a/bin/find_virtualenv.sh b/bin/find_virtualenv.sh
deleted file mode 100644
index e40081a..0000000
--- a/bin/find_virtualenv.sh
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/bin/bash
-# Copyright 2017 The Chromium OS Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-#
-# Find the virtualenv repo to use.
-#
-# This is meant to be sourced in scripts that need virtualenv. The
-# sourcing script should cd into the directory containing this script
-# first. This script defines functions for performing common tasks:
-#
-# exec_python_module -- Execute Python module inside of virtualenv
-#
-# This script is a canonical template that can be copied to other
-# repositories. The venv_repo variable should be changed to point to
-# this repository.
-set -eu
-
-realpath() {
- readlink -f -- "$1"
-}
-
-# venv_repo should be changed if this script is copied to other repos.
-readonly venv_repo=$(realpath ..)
-readonly create_script=$(realpath "${venv_repo}/bin/create_venv")
-readonly venv_home=$(realpath ../venv)
-readonly reqs_file=$(realpath "${venv_home}/requirements.txt")
-
-exec_python_module() {
- venvdir=$("${create_script}" "$reqs_file")
- export PYTHONPATH=${venv_home}
- exec "${venvdir}/bin/python" -m "$@"
-}
diff --git a/bin/python_venv b/bin/python_venv
new file mode 100755
index 0000000..c4f6b87
--- /dev/null
+++ b/bin/python_venv
@@ -0,0 +1,74 @@
+#!/bin/bash
+# Copyright 2017 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# Starts a python interpreter in virtualenv.
+#
+# This script will set up a virtualenv when it has not been created yet and
+# executes the Python interpreter.
+#
+# This script is a canonical template that can be copied to other
+# repositories. The infra_virtualenv_path variable should be changed to point
+# to this repository.
+
+set -eu
+
+# Change this constant to the path(s) to infra_virtualenv directory when you
+# copy this script to other repos.
+# A path can be a relative path from this script, or an absolute path. If this
+# array contains multiple paths, they are searched in the listed order.
+readonly -a infra_virtualenv_paths=(
+ ".."
+)
+
+readonly bin_dir="$(readlink -e -- "$(dirname -- "$0")")"
+if [[ ! -d "${bin_dir}" ]]; then
+ echo "ERROR: Can not locate the location of python_env!" >&2
+ exit 1
+fi
+
+realpath() {
+ pushd "${bin_dir}" > /dev/null 2>&1
+ readlink -e -- "$1"
+ popd > /dev/null 2>&1
+}
+
+find_create_venv() {
+ local p
+ for p in "${infra_virtualenv_paths[@]}"; do
+ local create_venv=$(realpath "${p}/bin/create_venv")
+ if [[ -f "${create_venv}" ]]; then
+ echo "${create_venv}"
+ break
+ fi
+ done
+}
+
+readonly create_venv=$(find_create_venv)
+if [[ ! -f "${create_venv}" ]]; then
+ cat <<EOF >&2
+ERROR: create_venv script could not be located.
+You need to update a constant inside python_venv, or your checkout might be
+incomplete.
+EOF
+ exit 1
+fi
+
+readonly extra_imports_dir=$(realpath ../venv)
+if [[ ! -d "${extra_imports_dir}" ]]; then
+ cat <<EOF >&2
+ERROR: venv directory is not found at ${bin_dir}/..
+See infra_virtualenv/README.md for details.
+EOF
+ exit 1
+fi
+
+readonly venv_dir=$("${create_venv}" "${extra_imports_dir}/requirements.txt")
+if [[ ! -d "${venv_dir}" ]]; then
+ echo "ERROR: Failed to set up a virtualenv." >&2
+ exit 1
+fi
+
+export PYTHONPATH="${extra_imports_dir}"
+exec "${venv_dir}/bin/python" "$@"
diff --git a/bin/run_tests b/bin/run_tests
index 851e5bc..967e7df 100755
--- a/bin/run_tests
+++ b/bin/run_tests
@@ -6,9 +6,9 @@
# Run unit tests.
set -eu
-cd -- "$(readlink -e -- "$(dirname -- "$0")")"
-. ./find_virtualenv.sh
-cd ../venv
+readonly bin_dir="$(readlink -e -- "$(dirname -- "$0")")"
+
+cd "${bin_dir}/../venv"
find . -name "*.pyc" -print0 | xargs -0 rm -f
while getopts v name; do
@@ -18,4 +18,4 @@
esac
done
-exec_python_module unittest discover "${verbose:+-v}" -s cros_venv
+exec "${bin_dir}/python_venv" -m unittest discover "${verbose:+-v}" -s cros_venv
diff --git a/bin/turtle b/bin/turtle
index 4c491ef..4b8d314 100755
--- a/bin/turtle
+++ b/bin/turtle
@@ -9,9 +9,6 @@
# repositories.
set -eu
-original=$(pwd)
-cd -- "$(readlink -e -- "$(dirname -- "$0")")"
-. ./find_virtualenv.sh
-cd -- "$original"
+readonly bin_dir="$(readlink -e -- "$(dirname -- "$0")")"
-exec_python_module turtle "$@"
+exec "${bin_dir}/python_venv" -m turtle "$@"