diff --git a/check_packages.py b/check_packages.py index fff8bb9251..1c06a6880b 100644 --- a/check_packages.py +++ b/check_packages.py @@ -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))