From 75bfee3abde757e60fcf149fe56e6e9eff512fa0 Mon Sep 17 00:00:00 2001 From: Andreas Maier Date: Thu, 18 Apr 2024 12:49:30 +0200 Subject: [PATCH] Fixed pywbem install error with ImportError on Python 2.7; Fixed tests Details: * Fixed pywbem install error with ImportError for "._vendor.nocasedict" on Python 2.7. (issue #3163): The pywbem/_vendor/__init__.py file was missing from the wheel distribution archive and Python 2 cannot deal with that. Fixed by adding the file. * Fixed the test_install.sh script to catch the install error that was previously not detected. The main failure was that the import check was done in the main directory of the repo, so the __init__.py file came from there and had precedence over the resulting installation, so that the installation was not actually tested at all. This was fixed by performing the import check in the install test directory. * Improved the test_install.sh script by: - Adding empty lines around the sections it has, for better readability in the log file. - Echoed the commands that are executed. - Listed the Python packages in the virtualenv after installation, for better debugging issues. - Made directory paths absolute because now directories are changed during the test. Signed-off-by: Andreas Maier --- MANIFEST.in | 1 + Makefile | 2 + docs/changes.rst | 3 + tests/installtest/test_install.sh | 97 +++++++++++++++++++++---------- 4 files changed, 71 insertions(+), 32 deletions(-) diff --git a/MANIFEST.in b/MANIFEST.in index db94220c1..a43be39be 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -11,6 +11,7 @@ include mof_compiler include mof_compiler.bat include pywbem/*.py include pywbem_mock/*.py +include pywbem/_vendor/__init__.py include pywbem/_vendor/nocasedict/*.py include pywbem/_vendor/nocaselist/*.py include pywbem/_vendor/nocasedict/LICENSE diff --git a/Makefile b/Makefile index 71e963031..630f5dc3d 100644 --- a/Makefile +++ b/Makefile @@ -320,6 +320,7 @@ dist_manifest_in_files := \ mof_compiler.bat \ $(package_name)/*.py \ $(mock_package_name)/*.py \ + $(vendor_dir)/__init__.py \ $(vendor_dir)/nocasedict/*.py \ $(vendor_dir)/nocaselist/*.py \ $(vendor_dir)/nocasedict/LICENSE \ @@ -340,6 +341,7 @@ dist_dependent_files := \ mof_compiler.bat \ $(wildcard $(package_name)/*.py) \ $(wildcard $(mock_package_name)/*.py) \ + $(wildcard $(vendor_dir)/__init__.py) \ $(wildcard $(vendor_dir)/nocasedict/*.py) \ $(wildcard $(vendor_dir)/nocaselist/*.py) \ $(vendor_dir)/nocasedict/LICENSE \ diff --git a/docs/changes.rst b/docs/changes.rst index 4226091eb..3fe4a42c1 100644 --- a/docs/changes.rst +++ b/docs/changes.rst @@ -30,6 +30,9 @@ Released: not yet * Fix issue where pywbemlistener that fails startup can cause thread exception. See issue #3157 +* Fixed pywbem install error with ImportError for "._vendor.nocasedict" on + Python 2.7. Fixed the install tests to catch this error. (issue #3163) + **Enhancements:** **Cleanup:** diff --git a/tests/installtest/test_install.sh b/tests/installtest/test_install.sh index 8a1365497..e4ea4a137 100755 --- a/tests/installtest/test_install.sh +++ b/tests/installtest/test_install.sh @@ -32,7 +32,7 @@ DEBUG="false" VERBOSE="true" MYNAME=$(basename "$0") -MYDIR=$(dirname "$0") # Directory of this script, as seen by caller +MYDIR=$(abspath $(dirname "$0")) # Absolute path of directory of this script # Repo root dir, as seen by caller # Using MYDIR makes the script run with any caller's CWD. @@ -100,6 +100,15 @@ function verbose() fi } +function heading() +{ + local msg + msg="$1" + echo "" + echo -e "${green}${msg}${endcolor}" + echo "" +} + function info() { local msg @@ -185,11 +194,6 @@ function make_virtualenv() run "pip install pip $PIP_OPTS" "Reinstalling pip with PACKAGE_LEVEL=$PACKAGE_LEVEL" run "pip install setuptools $PIP_OPTS -c $(abspath $ROOT_DIR/requirements.txt)" "Reinstalling setuptools with PACKAGE_LEVEL=$PACKAGE_LEVEL and constraints from requirements.txt" run "pip install wheel $PIP_OPTS" "Reinstalling wheel with PACKAGE_LEVEL=$PACKAGE_LEVEL" - - verbose "Virtualenv before actual install test:" - verbose "Pip version: $(pip --version 2>&1)" - verbose "Packages:" - pip list --format=columns 2>/dev/null || pip list 2>/dev/null } function remove_virtualenv() @@ -213,6 +217,15 @@ function remove_virtualenv() fi } +function list_virtualenv() +{ + local curdir msg + curdir="$1" + msg="$2" + echo "$msg" + sh -c "cd $curdir; pip list --format=columns || pip list" +} + function assert_eq() { local v1 v2 @@ -238,11 +251,12 @@ function run() verbose "$msg" fi if [[ "$DEBUG" == "true" ]]; then - echo "Debug: running in this shell: $cmd" + echo "Debug: Command: $cmd" eval "$cmd" rc=$? echo "Debug: command returns: rc=$rc" else + verbose "Command: $cmd" eval "$cmd" >$CMD_LOG_FILE 2>&1 rc=$? fi @@ -263,10 +277,12 @@ function call() verbose "$msg" fi if [[ "$DEBUG" == "true" ]]; then - echo "Debug: running in sub-shell: $cmd" + echo "Debug: Command (in subshell): $cmd" sh -c "$cmd" rc=$? + echo "Debug: command returns: rc=$rc" else + verbose "Command (in subshell): $cmd" sh -c "$cmd" >$CMD_LOG_FILE 2>&1 rc=$? fi @@ -284,10 +300,12 @@ function assert_run_ok() cmd="$1" msg="$2" if [[ "$DEBUG" == "true" ]]; then - echo "Debug: running in this shell: $cmd" + echo "Debug: Command: $cmd" eval "$cmd" rc=$? + echo "Debug: command returns: rc=$rc" else + verbose "Command: $cmd" eval "$cmd" >$CMD_LOG_FILE 2>&1 rc=$? fi @@ -308,10 +326,12 @@ function assert_run_fails() cmd="$1" msg="$2" if [[ "$DEBUG" == "true" ]]; then - echo "Debug: running in this shell: $cmd" + echo "Debug: Command: $cmd" eval "$cmd" rc=$? + echo "Debug: command returns: rc=$rc" else + verbose "Command: $cmd" eval "$cmd" >$CMD_LOG_FILE 2>&1 rc=$? fi @@ -332,25 +352,32 @@ function ensure_uninstalled() pkg="$1" cmd="pip uninstall -y -q $pkg" if [[ "$DEBUG" == "true" ]]; then - echo "Debug: running: $cmd" + echo "Debug: Command: $cmd" + eval "$cmd" + rc=$? + echo "Debug: command returns: rc=$rc" + else + verbose "Command: $cmd" + eval "$cmd" >/dev/null 2>/dev/null fi - eval $cmd >/dev/null 2>/dev/null } function assert_import_ok() { - local module + local module dir module="$1" - verbose "Checking for successful import of module: $module" - assert_run_ok "python -c \"import ${module}\"" "Python module '${module}' cannot be imported" + dir="$2" + verbose "Checking for successful import of module $module in directory $dir" + assert_run_ok "cd ${dir}; python -c \"import ${module}\"" "Python module '${module}' cannot be imported in directory $dir" } function assert_import_fails() { - local module + local module dir module="$1" - verbose "Checking for failing import of module: $module" - assert_run_fails "python -c \"import ${module}\"" "Python module '${module}' can be imported but should have failed" + dir="$2" + verbose "Checking for failing import of module $module in directory $dir" + assert_run_fails "cd ${dir}; python -c \"import ${module}\"" "Python module '${module}' can be imported in directory $dir but should have failed" } function get_ply_version() @@ -411,7 +438,7 @@ function ensure_fresh() function prep() { - info "Preparing for the tests" + heading "Preparing for the tests" if [[ -d $TMP_TEST_DIR ]]; then echo "Removing test directory: $TMP_TEST_DIR" @@ -433,7 +460,7 @@ function prep() function cleanup() { - info "Cleaning up from the tests" + heading "Cleaning up from the tests" if [[ "$DEBUG" == "true" ]]; then echo "Debug: Not removing $TMP_TEST_DIR for debug inspection" @@ -459,13 +486,15 @@ function cleanup_egg_file() function test1() { testcase="test1" - info "Testcase $testcase: Pip install from repo root directory: $ROOT_DIR" + heading "Testcase $testcase: Pip install from repo root directory: $ROOT_DIR" make_virtualenv "$testcase" + list_virtualenv "$TMP_TEST_DIR" "Python packages in virtualenv before installation (PACKAGE_LEVEL=$PACKAGE_LEVEL)" call "cd $ROOT_DIR; pip install . $PIP_OPTS" "Installing with pip from repo root directory (PACKAGE_LEVEL=$PACKAGE_LEVEL)" - assert_import_ok "pywbem" - assert_import_ok "pywbem_mock" + list_virtualenv "$TMP_TEST_DIR" "Python packages in virtualenv after installation (PACKAGE_LEVEL=$PACKAGE_LEVEL)" + assert_import_ok "pywbem" "$TMP_TEST_DIR" + assert_import_ok "pywbem_mock" "$TMP_TEST_DIR" assert_no_moftab_build remove_virtualenv "$testcase" cleanup_egg_file @@ -474,13 +503,15 @@ function test1() function test3() { testcase="test3" - info "Testcase $testcase: Pip install from wheel distribution archive: $WHL_DISTFILE" + heading "Testcase $testcase: Pip install from wheel distribution archive: $WHL_DISTFILE" make_virtualenv "$testcase" + list_virtualenv "$TMP_TEST_DIR" "Python packages in virtualenv before installation (PACKAGE_LEVEL=$PACKAGE_LEVEL)" call "cd $TMP_TEST_DIR; pip install $(abspath $WHL_DISTFILE) $PIP_OPTS" "Installing with pip from wheel distribution archive (PACKAGE_LEVEL=$PACKAGE_LEVEL)" - assert_import_ok "pywbem" - assert_import_ok "pywbem_mock" + list_virtualenv "$TMP_TEST_DIR" "Python packages in virtualenv after installation (PACKAGE_LEVEL=$PACKAGE_LEVEL)" + assert_import_ok "pywbem" "$TMP_TEST_DIR" + assert_import_ok "pywbem_mock" "$TMP_TEST_DIR" assert_no_moftab_build remove_virtualenv "$testcase" cleanup_egg_file @@ -489,13 +520,15 @@ function test3() function test4() { testcase="test4" - info "Testcase $testcase: Pip install from source distribution archive: $SRC_DISTFILE" + heading "Testcase $testcase: Pip install from source distribution archive: $SRC_DISTFILE" make_virtualenv "$testcase" + list_virtualenv "$TMP_TEST_DIR" "Python packages in virtualenv before installation (PACKAGE_LEVEL=$PACKAGE_LEVEL)" call "cd $TMP_TEST_DIR; pip install $(abspath $SRC_DISTFILE) $PIP_OPTS" "Installing with pip from source distribution archive (PACKAGE_LEVEL=$PACKAGE_LEVEL)" - assert_import_ok "pywbem" - assert_import_ok "pywbem_mock" + list_virtualenv "$TMP_TEST_DIR" "Python packages in virtualenv after installation (PACKAGE_LEVEL=$PACKAGE_LEVEL)" + assert_import_ok "pywbem" "$TMP_TEST_DIR" + assert_import_ok "pywbem_mock" "$TMP_TEST_DIR" assert_no_moftab_build remove_virtualenv "$testcase" cleanup_egg_file @@ -503,8 +536,8 @@ function test4() #----- main -WHL_DISTFILE="$1" # absolute or relative to caller's cwd -SRC_DISTFILE="$2" # absolute or relative to caller's cwd +WHL_DISTFILE=$(abspath "$1") # absolute or relative to caller's cwd +SRC_DISTFILE=$(abspath "$2") # absolute or relative to caller's cwd PYTHON_CMD="$3" # Python command to use (outside of the created virtualenvs) if [[ -z $PYTHON_CMD ]]; then @@ -532,4 +565,4 @@ test4 cleanup -info "All testcases succeeded." +heading "All testcases succeeded."