# # Copyright (C) 2012, Martin Zibricky # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA # Install necessary 3rd party Python modules to run all tests. # This script is supposed to be used in a continuous integration system: # https://jenkins.shiningpanda.com/pyinstaller/ # Python there is mostly 64bit. Only Python 2.4 is 32bit on Windows 7. import glob import optparse import os import platform import sys # easy_install command used in a Python script. from setuptools.command import easy_install try: import PyInstaller except ImportError: # if importing PyInstaller fails, try to load from parent # directory to support running without installation import imp if not hasattr(os, "getuid") or os.getuid() != 0: imp.load_module('PyInstaller', *imp.find_module('PyInstaller', [os.path.dirname(os.path.dirname(os.path.abspath(__file__)))])) from PyInstaller.compat import is_py24, is_py25, is_py26 PYVER = '.'.join([str(x) for x in sys.version_info[0:2]]) def py_arch(): """ .exe installers of Python modules contain architecture name in filename. """ mapping = {'32bit': 'win32', '64bit': 'win-amd64'} arch = platform.architecture()[0] return mapping[arch] _PACKAGES = { # 'modulename': 'pypi_name_or_url_or_path' 'MySQLdb': ['MySQL-python-*%s-py%s.exe' % (py_arch(), PYVER)], 'numpy': ['numpy-unoptimized-*%s-py%s.exe' % (py_arch(), PYVER)], 'PIL': ['PIL-*%s-py%s.exe' % (py_arch(), PYVER)], 'psycopg2': ['psycopg2-*%s-py%s.exe' % (py_arch(), PYVER)], 'pycrypto': ['pycrypto'], 'pyodbc': ['pyodbc'], 'simplejson': ['simplejson'], 'sqlalchemy': ['SQLAlchemy-*%s-py%s.exe' % (py_arch(), PYVER)], 'wx': ['wxPython-common-*%s-py%s.exe' % (py_arch(), PYVER), 'wxPython-2*%s-py%s.exe' % (py_arch(), PYVER)], 'win32api': ['http://downloads.sourceforge.net/project/pywin32/pywin32/Build%%20217/pywin32-217.%s-py%s.exe' % (py_arch(), PYVER)], } _PY_VERSION = { 'MySQLdb': is_py26, 'numpy': is_py26, 'PIL': is_py26, 'psycopg2': is_py26, 'simplejson': is_py25, 'sqlalchemy': is_py24, # Installers are available only for Python 2.6/2.7. 'wx': is_py26, } def main(): parser = optparse.OptionParser() parser.add_option('-d', '--download-dir', help='Directory with maually downloaded python modules.' ) opts, _ = parser.parse_args() # Install packages. for k, v in _PACKAGES.items(): # Test python version for module. if k in _PY_VERSION: # Python version too old, skip module. if PYVER < _PY_VERSION[k]: continue try: __import__(k) print 'Already installed... %s' % k # Module is not available - install it. except ImportError: # If not url or module name then look for installers in download area. if not v[0].startswith('http') and v[0].endswith('exe'): files = [] # Try all file patterns. for pattern in v: pattern = os.path.join(opts.download_dir, pattern) files += glob.glob(pattern) # No file with that pattern was not found - skip it. if not files: print 'Skipping module... %s' % k continue # Full path to installers in download directory. v = files print 'Installing module... %s' % k # Some modules might require several .exe files to install. for f in v: print ' %s' % f # Use --no-deps ... installing module dependencies might fail # because easy_install tries to install the same module from # PYPI from source code and if fails because of C code that # that needs to be compiled. easy_install.main(['--no-deps', '--always-unzip', f]) if __name__ == '__main__': main()