370 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			370 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| #
 | |
| # Gramps - a GTK+ based genealogy program
 | |
| #
 | |
| # Copyright (C) 2010       Stephen George
 | |
| #
 | |
| # 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.
 | |
| #
 | |
| # $Id: $
 | |
| import sys
 | |
| import os
 | |
| import _winreg
 | |
| from ctypes.util import find_library
 | |
| import getopt
 | |
| import string
 | |
| 
 | |
| NOT_FOUND_STR ='Not Found'
 | |
| #small selection of DLL's to test
 | |
| testdlls = ['libgdk-win32-2.0-0.dll', 'libglib-2.0-0.dll', 'libgobject-2.0-0.dll', 'libcairo-2.dll', ]
 | |
| 
 | |
| explain_exposed = '''    ***********************************************************
 | |
|     * It seems that other installations are exposing GTK DLL's
 | |
|     * to the operating system as they are in the environment
 | |
|     * path variable BEFORE the runtime directory. 
 | |
|     * You should reorder the path variable to put your GTK
 | |
|     * runtime path before these other installations on the path'''        
 | |
| 
 | |
| explain_safe = '''    ***************************************************************
 | |
|     * While there are other installations of GTK DLL's on the path,
 | |
|     * it should be safe as they are on the path AFTER the runtime
 | |
|     * directory. '''        
 | |
| 
 | |
| def RunExeCommand( app, args ):
 | |
|     cmd = app + ' ' + args
 | |
|     #print "Running: ", cmd
 | |
|     stdin, stdout, stderr = os.popen3( cmd )
 | |
|     output = string.strip(stdout.read())
 | |
|     #print output
 | |
|     err = stderr.read()
 | |
|     if err:
 | |
|         print err
 | |
|     return output
 | |
|         
 | |
| def CheckGtkInReg():
 | |
|     global gtkPathInRegistry, gtkVersionInRegistry, dllPathInRegistry, dllPathShort
 | |
|     print '\n==== Checking Registry for GTK ====='
 | |
|     try:
 | |
|         with _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\GTK\\2.0') as key:
 | |
|             gtkVersionInRegistry = _winreg.QueryValueEx(key, 'Version')[0]
 | |
|             gtkPathInRegistry = _winreg.QueryValueEx(key, 'Path')[0]
 | |
|             dllPathInRegistry = _winreg.QueryValueEx(key, 'DllPath')[0]
 | |
|             print '  Version   :', gtkVersionInRegistry     
 | |
|             print '  Path      :', gtkPathInRegistry
 | |
|             print '  DllPath   :', dllPathInRegistry 
 | |
|             
 | |
|     except WindowsError, e:
 | |
|         print '\n  GTK registry key not found in registry'
 | |
|         print '''    ********************************************************************
 | |
|     * This might not be an error, but means I don't know the directory to 
 | |
|     * your preferred GTK installation. 
 | |
|     *  - try passing in your GTK installation path.\n'''
 | |
|         print '-' * 60
 | |
|         print usage
 | |
|         sys.exit(0)
 | |
|     
 | |
| def WorkOutShortDosPath():
 | |
|     global dllPathShort
 | |
|     print '\n==== Use win32Api to query short path name for GTK ====='
 | |
|     try:
 | |
|         import win32api
 | |
|         dllPathShort =  win32api.GetShortPathName(dllPathInRegistry)
 | |
|         print '  DllPath8.3:', dllPathShort
 | |
|     except ImportError:
 | |
|         print '  **Cant query short path name, Win32Api not installed'
 | |
|         print '    install from http://python.net/crew/mhammond/win32/'
 | |
|         print '    if you want this function to work'
 | |
| 
 | |
| def FindLibsWithCtypes():    
 | |
|     # use ctypes to check where windows finds it's DLL's    
 | |
|     print '\n==== Use ctypes to find dlls ===='
 | |
|     other_paths = []
 | |
|     for dll in testdlls:
 | |
|         dllpathvalid = False
 | |
|         cpath = find_library(dll)
 | |
|         if cpath:
 | |
|         #print cpath
 | |
|             if cpath == os.path.join(dllPathInRegistry, dll) \
 | |
|             or cpath == os.path.join(dllPathShort, dll):
 | |
|                 dllpathvalid = True
 | |
|                 
 | |
|             if not dllpathvalid:
 | |
|                 pp = os.path.dirname(cpath)
 | |
|                 if pp not in other_paths:
 | |
|                     other_paths.append(pp)
 | |
|         else:
 | |
|             print "  ERROR:... ctypes failed to find %s" % dll
 | |
|     if other_paths:
 | |
|         for pth in other_paths:
 | |
|             print "  ERROR: ctypes loaded some gtk dll's from %s" % pth
 | |
|     else:
 | |
|         print "  OK ... ctypes found dll's in %s" % os.path.dirname(cpath)
 | |
|         
 | |
| def ScanDependencyFileForErrors(fname):
 | |
|     fin = open(fname, 'r')
 | |
|     lines = fin.readlines()
 | |
|     fin.close()
 | |
|     sysroot = os.environ["SystemRoot"]
 | |
|     capture = False
 | |
|     runtimedlls = {}
 | |
|     for line in lines:
 | |
|         if line.startswith("       Module"): # work out were paths end
 | |
|             pthend_idx = line.find("File Time Stamp")
 | |
|         acceptablePaths = [ dllPathShort.lower(), 
 | |
|                             dllPathInRegistry.lower(),
 | |
|                             os.path.join(sysroot, 'system32').lower()
 | |
|                           ]
 | |
|         if line.startswith('-----  ------------'):
 | |
|             capture = True
 | |
|         if capture and line.startswith('['):
 | |
|             filename = line[5:pthend_idx].strip()
 | |
|             dirname = os.path.dirname(filename).strip()
 | |
|             parts = line[pthend_idx:].split()
 | |
|             OK = False
 | |
|             if dirname.startswith(os.path.join(sysroot, 'winsxs').lower()) \
 | |
|             or dirname.startswith(os.path.join(sys.prefix, 'lib\site-packages\gtk-2.0').lower()):
 | |
|                 OK = True
 | |
|                 
 | |
|             for pth in acceptablePaths:
 | |
|                 if dirname == pth.lower():
 | |
|                     OK = True
 | |
|                     
 | |
|             if 'MSVCR90.DLL' in filename:
 | |
|                 if parts[0] == 'Error':
 | |
|                     runtimedlls[filename] = "Error dll not found"
 | |
|                 else:
 | |
|                     runtimedlls[filename] = parts[16]
 | |
|                 
 | |
|             if OK == False:
 | |
|                 if parts[0] == 'Error':
 | |
|                     print "    %s \tError dll not found" %( filename)
 | |
|                 else:
 | |
|                     print "    ERROR: %s \tVersion %s" %( filename, parts[16])
 | |
|     for rtdll in runtimedlls:
 | |
|         if runtimedlls[rtdll].startswith("Error"):
 | |
|             print '\n    ERROR: MS runtime %s not found'%rtdll
 | |
|         else:
 | |
|             print '\n    MS runtime Version %s loaded from' % runtimedlls[rtdll]
 | |
|             print "    %s" %rtdll 
 | |
|     print 
 | |
|     
 | |
| def CheckWithDependencyWalker():
 | |
|     print '\n==== Checking with Dependency Walker ===='
 | |
|     print '      Please be patient takes some time'
 | |
|     exe = os.path.join(scriptpath, 'depends.exe')
 | |
|     fout = os.path.join(scriptpath, 'depres.txt')
 | |
|     f2check = [ 
 | |
|                 os.path.join(sys.prefix, 'Lib/site-packages/gtk-2.0/gtk/_Gtk.pyd' ),
 | |
|                 os.path.join(sys.prefix, 'Lib/site-packages/gtk-2.0/gobject/_GObject.pyd' ),
 | |
|                 os.path.join(sys.prefix, 'Lib/site-packages/gtk-2.0/pangocairo.pyd' ),
 | |
|                 ]
 | |
|     if os.path.isfile( exe ):
 | |
|         for ftest in f2check:
 | |
|             if os.path.isfile( ftest ):
 | |
|                 #delete the output file before running command
 | |
|                 try:
 | |
|                     os.remove(fout)
 | |
|                 except WindowsError, e:
 | |
|                     pass
 | |
|                 print '  Testing file %s' % ftest
 | |
|                 out = RunExeCommand(exe, '/c /f1 /ot "%s" "%s"' % (fout, ftest) )
 | |
|                 if os.path.isfile(fout):
 | |
|                     ScanDependencyFileForErrors(fout)
 | |
|             else:
 | |
|                 print "  ERROR: file %d does not exist", ftest
 | |
|     else:
 | |
|         print '  Cannot check with dependency walker, not installed in local directory'
 | |
|         print '  get dependency walker from http://www.dependencywalker.com/'
 | |
|         print '  and unzip into this directory for it to work.'
 | |
|     
 | |
| def CheckPathForOtherGtkInstalls():     
 | |
|     print '\n====Checking environment path for other gtk installations===='
 | |
|     ePath = os.environ['path']
 | |
|     dirs = ePath.split(';')
 | |
|     gtkpth_idx = 9999
 | |
|     other_paths = []
 | |
|     explain_level = 0
 | |
|     for i, d in enumerate(dirs):
 | |
|         #print '==%s==' %d
 | |
|         if d == gtkPathInRegistry or d == dllPathInRegistry\
 | |
|         or d == dllPathShort:
 | |
|             gtkpth_idx = i
 | |
|             continue
 | |
|         for fname in testdlls:
 | |
|             f = os.path.join(d, fname)
 | |
|             if os.path.isfile( f ):
 | |
|                 #print '   Found Erronous gtk DLL %s' % f
 | |
|                 if d not in other_paths:
 | |
|                     other_paths.append(d)
 | |
|                     if i < gtkpth_idx: # path appears BEFORE runtime path
 | |
|                         print '  ERROR: %s should not appear before runtime path' % d
 | |
|                         explain_level = 2
 | |
|                     else:
 | |
|                         print '  FOUND: %s, Probably OK as appears AFTER runtime path' % d
 | |
|                         if explain_level <= 1:
 | |
|                             explain_level = 1
 | |
|     if gtkpth_idx == 9999:
 | |
|         print '\n  ERROR: Runtime directory not on enviroment path'
 | |
|         print "         ** Runtime needs to be on path to load DLL's from\n"
 | |
|     if explain_level == 2:
 | |
|         print explain_exposed
 | |
|     elif explain_level == 1:
 | |
|         print explain_safe
 | |
|     if len(other_paths) == 0:
 | |
|         print '  No other gtk installatons found\n'
 | |
|                 
 | |
| # ==== report what python thinks it's using =====
 | |
| MIN_PYTHON_VER   = (2,5,1)
 | |
| UNTESTED_PYTHON_VER = (3,0,0)
 | |
| 
 | |
| MIN_GTK_VER      = (2,10,11)
 | |
| UNTESTED_GTK_VER = (2,16,7)
 | |
| 
 | |
| MIN_PYGTK_VER    = (2,10,6)
 | |
| UNTESTED_PYGTK_VER    = (2,12,2)
 | |
| 
 | |
| MIN_GOBJECT_VER  = (2,12,3)
 | |
| UNTESTED_GOBJECT_VER  = (2,14,3)
 | |
| 
 | |
| MIN_CAIRO_VER    = (1,2,6)
 | |
| UNTESTED_CAIRO_VER    = (1,4,13)
 | |
| 
 | |
| def PrintFailedImport(appl, minVersion, result):
 | |
|     print appl,
 | |
|     print 'version %d.%d.%d or above.....\t' % minVersion ,
 | |
|     print result
 | |
| 
 | |
| def PrintVersionResult(appl, minVersion, actualVersion, untestedVersion):
 | |
|     print appl,
 | |
|     print 'version %d.%d.%d or above.....\t' % minVersion ,
 | |
|     print 'found %d.%d.%d' % actualVersion ,
 | |
|     if minVersion <= actualVersion < untestedVersion: 
 | |
|         print '...OK'
 | |
|     elif  actualVersion >= untestedVersion:
 | |
|         print '...UNTESTED VERSION'
 | |
|     else:
 | |
|         print '...FAILED'
 | |
|             
 | |
| def Import_pyGtkIntoPython():
 | |
|     print '\n==== Test import into python ===='
 | |
|     #py_str = 'found %d.%d.%d' %  sys.version_info[:3]
 | |
|     PrintVersionResult('  Python ', MIN_PYTHON_VER, sys.version_info[:3], UNTESTED_PYTHON_VER)
 | |
| 
 | |
|     # Test the GTK version
 | |
|     try:
 | |
|         import gtk
 | |
|         
 | |
|         PrintVersionResult('  GTK+   ', MIN_GTK_VER, Gtk.gtk_version, UNTESTED_GTK_VER )
 | |
|         
 | |
|         #test the pyGTK version (which is in the gtk namespace)
 | |
|         PrintVersionResult('  pyGTK  ', MIN_PYGTK_VER, Gtk.pygtk_version, UNTESTED_PYGTK_VER )
 | |
|         
 | |
|     except ImportError:
 | |
|         PrintFailedImport('  GTK+   ', MIN_GTK_VER, NOT_FOUND_STR)
 | |
|         PrintFailedImport('  pyGTK  ', MIN_PYGTK_VER, 'Cannot test, ...GTK+ missing')
 | |
| 
 | |
|         
 | |
|     #test the gobject version
 | |
|     try:
 | |
|         import gobject
 | |
|         PrintVersionResult('  gobject', MIN_GOBJECT_VER, GObject.pygobject_version, UNTESTED_GOBJECT_VER) 
 | |
|         
 | |
|     except ImportError:
 | |
|         PrintFailedImport('  gobject', MIN_GOBJECT_VER, NOT_FOUND_STR)
 | |
| 
 | |
| 
 | |
|     #test the cairo version
 | |
|     try:
 | |
|         import cairo
 | |
|         PrintVersionResult('  cairo  ', MIN_CAIRO_VER, cairo.version_info, UNTESTED_CAIRO_VER ) 
 | |
|         
 | |
|     except ImportError:
 | |
|         PrintFailedImport('  cairo  ', MIN_CAIRO_VER, NOT_FOUND_STR)
 | |
| 
 | |
|     #test for glade
 | |
|     print '\n==== See if libglade installed ===='
 | |
| 
 | |
|     try:
 | |
|         import Gtk.glade
 | |
|         print '  Glade   tesing import of libglade .......\tOK\n'
 | |
|     except ImportError, e:
 | |
|         print '  Glade   importError: %s\n' % e
 | |
| 
 | |
| if __name__ == '__main__':
 | |
|     usage = '''Check for common problems in GTK/pyGTK installation.
 | |
| Usage:
 | |
|     python %s [options] [gtkPath]
 | |
| 
 | |
| Arguments:
 | |
|     gtkPath                    Path to your GTK installation directory (not the bin dir)
 | |
|     
 | |
| Options:
 | |
|     None
 | |
|     ''' %(os.path.basename(__file__) )
 | |
| 
 | |
|     gtkPath = None
 | |
|     gtkPathInRegistry = NOT_FOUND_STR
 | |
|     gtkVersionInRegistry = NOT_FOUND_STR
 | |
|     dllPathInRegistry = NOT_FOUND_STR
 | |
|     dllPathShort = 'NoShortPath'
 | |
|     scriptpath = os.path.dirname(sys.argv[0])
 | |
|     try:
 | |
|         opts, args = getopt.getopt(sys.argv[1:], "",
 | |
|                                   [])
 | |
| 
 | |
|         for o, a in opts:
 | |
|             if o in ("-h", "--help"):
 | |
|                 print usage
 | |
|                 sys.exit(0)
 | |
| 
 | |
|         if len(args) > 1:
 | |
|             raise getopt.GetoptError, '\nERROR: Too many arguments'
 | |
|         for arg in args:
 | |
|             if os.path.isdir(arg):
 | |
|                 gtkPath = arg
 | |
|             else:
 | |
|                 raise  getopt.GetoptError, '\nERROR: Not a valid GTK path %s' % arg
 | |
|                 
 | |
|     except getopt.GetoptError, msg:
 | |
|         print msg
 | |
|         print '\n %s' % usage
 | |
|         sys.exit(2)
 | |
| 
 | |
|     import platform
 | |
|     winver = platform.win32_ver()
 | |
|     if len(winver) == 4:
 | |
|         print   '''\n==== platform.win32_ver() reports ====
 | |
|   Operating System: %s
 | |
|   Version         : %s
 | |
|   Service Pack    : %s
 | |
|   OS type         : %s''' %  winver
 | |
|     else:
 | |
|         print winver
 | |
|         
 | |
|     if gtkPath:
 | |
|         gtkPathInRegistry = gtkPath
 | |
|         dllPathInRegistry = os.path.join(gtkPath, 'bin')
 | |
|         print '  Using %s as GTK install path' % gtkPathInRegistry
 | |
|         print '  Using %s as GTK dll path' % dllPathInRegistry
 | |
|     else:
 | |
|         CheckGtkInReg()
 | |
| 
 | |
|     WorkOutShortDosPath()
 | |
|     FindLibsWithCtypes()
 | |
|     CheckPathForOtherGtkInstalls()
 | |
|     Import_pyGtkIntoPython()
 | |
|     
 | |
|     CheckWithDependencyWalker()
 | |
|     
 |