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

4.x: Check packages comparison to YAML files #1482

Merged
merged 6 commits into from
Mar 31, 2020
180 changes: 97 additions & 83 deletions check_packages.py
Original file line number Diff line number Diff line change
@@ -1,102 +1,116 @@
"""
Checking and reinstalling the external packages
Check the existing environment against expected values
"""
from __future__ import print_function

import re
import sys

# Fix for error: hash-collision-3-both-1-and-1/
# See http://jaredforsyth.com/blog/2010/apr/28/accessinit-hash-collision-3-both-1-and-1/
import subprocess
try:
import PIL.Image
import yaml
from colorama import Fore, Style
except ImportError:
pass
else:
sys.modules['Image'] = PIL.Image
print("The PyYaml and colorama packages are required for this module. To " +
"install them, please try one of the following:")
print("\tAnaconda: conda install pyyaml colorama")
print("\tBase python: pip install pyyaml colorama")
quit()

if sys.version_info[0] > 2:
print("To use the sasview GUI you must use Python 2\n")

common_required_package_list = {
'setuptools': {'version': '0.6c11', 'import_name': 'setuptools', 'test': '__version__'},
'pyparsing': {'version': '1.5.5', 'import_name': 'pyparsing', 'test': '__version__'},
'html5lib': {'version': '0.95', 'import_name': 'html5lib', 'test': '__version__'},
'reportlab': {'version': '2.5', 'import_name': 'reportlab', 'test': 'Version'},
'h5py': {'version': '2.5', 'import_name': 'h5py', 'test': '__version__'},
'lxml': {'version': '2.3', 'import_name': 'lxml.etree', 'test': 'LXML_VERSION'},
'PIL': {'version': '1.1.7', 'import_name': 'Image', 'test': 'VERSION'},
'pylint': {'version': None, 'import_name': 'pylint', 'test': None},
'periodictable': {'version': '1.5.0', 'import_name': 'periodictable', 'test': '__version__'},
'bumps': {'version': '0.7.5.9', 'import_name': 'bumps', 'test': '__version__'},
'numpy': {'version': '1.7.1', 'import_name': 'numpy', 'test': '__version__'},
'scipy': {'version': '0.18.0', 'import_name': 'scipy', 'test': '__version__'},
'wx': {'version': '2.8.12.1', 'import_name': 'wx', 'test': '__version__'},
'matplotlib': {'version': '1.1.0', 'import_name': 'matplotlib', 'test': '__version__'},
'xhtml2pdf': {'version': '3.0.33', 'import_name': 'xhtml2pdf', 'test': '__version__'},
'sphinx': {'version': '1.2.1', 'import_name': 'sphinx', 'test': '__version__'},
'unittest-xml-reporting': {'version': '1.10.0', 'import_name': 'xmlrunner', 'test': '__version__'},
'pyopencl': {'version': '2015.1', 'import_name': 'pyopencl', 'test': 'VERSION_TEXT'},
}
win_required_package_list = {
'comtypes': {'version': '0.6.2', 'import_name': 'comtypes', 'test': '__version__'},
'pywin': {'version': '217', 'import_name': 'pywin', 'test': '__version__'},
'py2exe': {'version': '0.6.9', 'import_name': 'py2exe', 'test': '__version__'},
}
mac_required_package_list = {
'py2app': {'version': None, 'import_name': 'py2app', 'test': '__version__'},
}
# Output strings
CORRECT = Style.RESET_ALL + " - {0} - Expected Version Installed: {1}"
VERSION_MISMATCH = Fore.LIGHTYELLOW_EX +\
" - {0} - Version Mismatch - Installed: {1}, Expected: {2}"
VERSION_UNKNOWN = Fore.YELLOW +\
" - {0} - Version Cannot Be Determined - Expected: {1}"
NOT_INSTALLED = Fore.LIGHTRED_EX + " - {0} NOT INSTALLED"

deprecated_package_list = {
'pyPdf': {'version': '1.13', 'import_name': 'pyPdf', 'test': '__version__'},
}

print("Checking Required Package Versions....\n")
print("Common Packages")
# Location of yaml files
if sys.platform == 'win32':
file_location = './build_tools/conda/ymls/sasview-env-build_win.yml'
elif sys.platform == 'darwin':
file_location = './build_tools/conda/ymls/sasview-env-build_osx.yml'
else:
file_location = './build_tools/conda/ymls/sasview-env-build_linux.yml'

for package_name, test_vals in common_required_package_list.items():
# Open yaml and get packages
with open(file_location, 'r') as stream:
try:
i = __import__(test_vals['import_name'], fromlist=[''])
if test_vals['test'] is None:
print("%s Installed (Unknown version)" % package_name)
elif package_name == 'lxml':
verstring = str(getattr(i, 'LXML_VERSION'))
print("%s Version Installed: %s"% (package_name, verstring.replace(', ', '.').lstrip('(').rstrip(')')))
else:
print("%s Version Installed: %s"% (package_name, getattr(i, test_vals['test'])))
except ImportError:
print('%s NOT INSTALLED'% package_name)
yaml_dict = yaml.load(stream, Loader=yaml.SafeLoader)
yaml_packages = yaml_dict['dependencies']
inter_package_list = [p for entry in yaml_packages for p in (
entry['pip'] if isinstance(entry, dict) else [entry])]
common_required_package_list = [re.sub("[<>=]=", "=", package) for
package in inter_package_list]
except Exception as e:
print(e)

if sys.platform == 'win32':
print("")
print("Windows Specific Packages:")
for package_name, test_vals in win_required_package_list.items():
try:
i = __import__(test_vals['import_name'], fromlist=[''])
print("%s Version Installed: %s"% (package_name, getattr(i, test_vals['test'], "unknown")))
except ImportError:
print('%s NOT INSTALLED'% package_name)
# Get list of system packages (conda or pip)
isConda = True
try:
reqs = subprocess.check_output(['conda', 'list'])
except Exception:
reqs = subprocess.check_output([sys.executable, '-m', 'pip', 'freeze'])
isConda = False

if sys.platform == 'darwin':
print("")
print("MacOS Specific Packages:")
for package_name, test_vals in mac_required_package_list.items():
try:
i = __import__(test_vals['import_name'], fromlist=[''])
print("%s Version Installed: %s"% (package_name, getattr(i, test_vals['test'])))
except ImportError:
print('%s NOT INSTALLED'% package_name)
packages_installed = []
versions_installed = []
packages_specified = 0
packages_correct = 0
packages_mismatch = 0
packages_not_installed = 0

if isConda:
for r in reqs.splitlines():
if r.decode().split()[0] == "#" or len(r.decode().split()) < 2:
continue
package = r.decode().split()[0].lower()
version = r.decode().split()[1]
packages_installed.append(package)
versions_installed.append(version)
else:
packages_installed = [r.decode().split('==')[0].lower() for r in
reqs.split()]
versions_installed = [r.decode().split('==')[1] for r in reqs.split()]

print("")
print("Deprecated Packages")
print("You can remove these unless you need them for other reasons!")
for package_name, test_vals in deprecated_package_list.items():
print("....COMPARING PACKAGES LISTED IN {0} to INSTALLED PACKAGES....".format(
file_location))
print("")

# Step through each yaml package and check its version against system
for yaml_name in common_required_package_list:
try:
i = __import__(test_vals['import_name'], fromlist=[''])
if package_name == 'pyPdf':
# pyPdf doesn't have the version number internally
print('pyPDF Installed (Version unknown)')
text_split = yaml_name.split('=')
package_name = text_split[0].lower()
package_version = text_split[1]
except (AttributeError, IndexError) as e:
# No version specified
package_name = yaml_name
package_version = '0.0'

try:
packages_specified += 1
if package_name == 'python':
full_version = sys.version.split()
installed_version = full_version[0]
else:
i = packages_installed.index(package_name)
installed_version = versions_installed[i]
if package_version == installed_version:
print(CORRECT.format(package_name, installed_version))
packages_correct += 1
else:
print("%s Version Installed: %s"% (package_name, getattr(i, test_vals['test'])))
except ImportError:
print('%s NOT INSTALLED'% package_name)
print(VERSION_MISMATCH.format(package_name, installed_version,
package_version))
packages_mismatch += 1
except ValueError:
print(NOT_INSTALLED.format(package_name))
packages_not_installed += 1

print(Style.RESET_ALL)
print("check_packages.py has finished:")
print("\tPackages required: {0}".format(packages_specified))
print("\tInstalled correctly: {0}".format(packages_correct))
print("\tMismatched versions: {0}".format(packages_mismatch))
print("\tNot installed: {0}".format(packages_not_installed))