From 69553d6fa31a60a4694395f0dcadfdbd787c21a8 Mon Sep 17 00:00:00 2001 From: Wayne Stambaugh Date: Sat, 14 Feb 2015 19:23:54 -0500 Subject: [PATCH] wxPython find and version loading fixes. (fixes lp:1408060) * Add test to CMakeLists.txt to verify wxPython is installed when KICAD_SCRIPTING_WXPYTHON=ON. * Add test to make sure wxPython version major and minor numbers match the version of wxWidgets found. * Add code to set the correct version of wxPython to the python scripting initialization code. * Minor code simplification in Pcbnew KIFACE main window creation. --- CMakeLists.txt | 28 ++++++++++++- CMakeModules/config.h.cmake | 5 +++ pcbnew/pcbnew.cpp | 77 ++++++++++++++++------------------ scripting/python_scripting.cpp | 13 ++++-- 4 files changed, 79 insertions(+), 44 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b38fb8eed2..21a0ef1b15 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -635,7 +635,6 @@ if( KICAD_SCRIPTING OR KICAD_SCRIPTING_MODULES ) # FindPythonInterp unless the user specifically defined a custom path. if( NOT PYTHON_SITE_PACKAGE_PATH ) execute_process( COMMAND ${PYTHON_EXECUTABLE} -c "import distutils.sysconfig;print\"%s\"%distutils.sysconfig.get_python_lib(plat_specific=0, standard_lib=0, prefix='')" -# execute_process( COMMAND ${PYTHON_EXECUTABLE} -c "import distutils.sysconfig;print\"%s\"%distutils.sysconfig.get_python_lib()" OUTPUT_VARIABLE PYTHON_SITE_PACKAGE_PATH OUTPUT_STRIP_TRAILING_WHITESPACE ) @@ -662,6 +661,33 @@ if( KICAD_SCRIPTING OR KICAD_SCRIPTING_MODULES ) find_package( PythonLibs 2.6 ) + if( KICAD_SCRIPTING_WXPYTHON ) + # Check to see if the correct version of wxPython is installed based on the version of + # wxWidgets found. At least the major an minor version should match. + set( _wxpy_version "${wxWidgets_VERSION_MAJOR}.${wxWidgets_VERSION_MINOR}" ) + set( _py_cmd "import wxversion;print wxversion.checkInstalled('${_wxpy_version}')" ) + execute_process( COMMAND ${PYTHON_EXECUTABLE} -c "${_py_cmd}" + RESULT_VARIABLE WXPYTHON_VERSION_RESULT + OUTPUT_VARIABLE WXPYTHON_VERSION_FOUND + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + + # message( STATUS "WXPYTHON_VERSION_FOUND: ${WXPYTHON_VERSION_FOUND}" ) + # message( STATUS "WXPYTHON_VERSION_RESULT: ${WXPYTHON_VERSION_RESULT}" ) + + # Check to see if any version of wxPython is installed on the system. + if( WXPYTHON_VERSION_RESULT GREATER 0 ) + message( FATAL_ERROR "wxPython does not appear to be installed on the system." ) + endif() + + if( NOT WXPYTHON_VERSION_FOUND STREQUAL "True" ) + message( FATAL_ERROR "wxPython version ${_wxpy_version} does not appear to be installed on the system." ) + else() + set( WXPYTHON_VERSION_FOUND "${_wxpy_version}" + CACHE STRING "wxPython version found." ) + endif() + endif() + #message( STATUS "PYTHON_INCLUDE_DIRS:${PYTHON_INCLUDE_DIRS}" ) # Infrequently needed headers go at end of search paths, append to INC_AFTER which diff --git a/CMakeModules/config.h.cmake b/CMakeModules/config.h.cmake index 27c1117a16..46272e82c0 100644 --- a/CMakeModules/config.h.cmake +++ b/CMakeModules/config.h.cmake @@ -70,6 +70,11 @@ #define KICAD_DATA_PATH "@CMAKE_INSTALL_PREFIX@/@KICAD_DATA@" #endif +/// The wxPython version found during configuration. +#if defined( KICAD_SCRIPTING_WXPYTHON ) +#define WXPYTHON_VERSION "@WXPYTHON_VERSION_FOUND@" +#endif + /// When defined, build the GITHUB_PLUGIN for pcbnew. #cmakedefine BUILD_GITHUB_PLUGIN diff --git a/pcbnew/pcbnew.cpp b/pcbnew/pcbnew.cpp index 6bd12c4cbb..1f1b4014ba 100644 --- a/pcbnew/pcbnew.cpp +++ b/pcbnew/pcbnew.cpp @@ -3,7 +3,7 @@ * * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck - * Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -109,57 +109,46 @@ static struct IFACE : public KIFACE_I wxWindow* CreateWindow( wxWindow* aParent, int aClassId, KIWAY* aKiway, int aCtlBits = 0 ) { + wxWindow* frame = NULL; + switch( aClassId ) { case FRAME_PCB: - { - PCB_EDIT_FRAME* frame = new PCB_EDIT_FRAME( aKiway, aParent ); + frame = dynamic_cast< wxWindow* >( new PCB_EDIT_FRAME( aKiway, aParent ) ); -#if defined(KICAD_SCRIPTING) - // give the scripting helpers access to our frame - ScriptingSetPcbEditFrame( frame ); +#if defined( KICAD_SCRIPTING ) + // give the scripting helpers access to our frame + ScriptingSetPcbEditFrame( (PCB_EDIT_FRAME*) frame ); #endif - if( Kiface().IsSingle() ) - { - // only run this under single_top, not under a project manager. - CreateServer( frame, KICAD_PCB_PORT_SERVICE_NUMBER ); - } - return frame; + if( Kiface().IsSingle() ) + { + // only run this under single_top, not under a project manager. + CreateServer( frame, KICAD_PCB_PORT_SERVICE_NUMBER ); } + break; case FRAME_PCB_MODULE_EDITOR: - { - FOOTPRINT_EDIT_FRAME* frame = new FOOTPRINT_EDIT_FRAME( aKiway, aParent ); - return frame; - } + frame = dynamic_cast< wxWindow* >( new FOOTPRINT_EDIT_FRAME( aKiway, aParent ) ); break; case FRAME_PCB_MODULE_VIEWER: case FRAME_PCB_MODULE_VIEWER_MODAL: - { - FOOTPRINT_VIEWER_FRAME* frame = new FOOTPRINT_VIEWER_FRAME( - aKiway, aParent, FRAME_T( aClassId ) ); - - return frame; - } + frame = dynamic_cast< wxWindow* >( new FOOTPRINT_VIEWER_FRAME( aKiway, aParent, + FRAME_T( aClassId ) ) ); break; case FRAME_PCB_FOOTPRINT_WIZARD_MODAL: - { - FOOTPRINT_WIZARD_FRAME* frame = new FOOTPRINT_WIZARD_FRAME( - aKiway, aParent, FRAME_T( aClassId ) ); - - return frame; - } + frame = dynamic_cast< wxWindow* >( new FOOTPRINT_WIZARD_FRAME( aKiway, aParent, + FRAME_T( aClassId ) ) ); break; default: ; } - return NULL; + return frame; } /** @@ -193,13 +182,13 @@ KIFACE_I& Kiface() { return kiface; } // KIFACE_GETTER's actual spelling is a substitution macro found in kiway.h. // KIFACE_GETTER will not have name mangling due to declaration in kiway.h. -MY_API( KIFACE* ) KIFACE_GETTER( int* aKIFACEversion, int aKiwayVersion, PGM_BASE* aProgram ) +MY_API( KIFACE* ) KIFACE_GETTER( int* aKIFACEversion, int aKiwayVersion, PGM_BASE* aProgram ) { process = (PGM_BASE*) aProgram; return &kiface; } -#if defined(BUILD_KIWAY_DLL) +#if defined( BUILD_KIWAY_DLL ) PGM_BASE& Pgm() { wxASSERT( process ); // KIFACE_GETTER has already been called. @@ -208,7 +197,7 @@ PGM_BASE& Pgm() #endif -#if defined(KICAD_SCRIPTING) +#if defined( KICAD_SCRIPTING ) static bool scriptingSetup() { wxString path_frag; @@ -218,7 +207,7 @@ static bool scriptingSetup() const wxString python_us( "python27_us" ); // Build our python path inside kicad - wxString kipython = FindKicadFile( python_us + wxT("/python.exe") ); + wxString kipython = FindKicadFile( python_us + wxT( "/python.exe" ) ); //we need only the path: wxFileName fn( kipython ); @@ -231,19 +220,20 @@ static bool scriptingSetup() if( !wxGetEnv( wxT( "PYTHONPATH" ), &ppath ) || !ppath.Contains( python_us ) ) { - ppath << kipython << wxT("/pylib;"); - ppath << kipython << wxT("/lib;"); - ppath << kipython << wxT("/dll"); + ppath << kipython << wxT( "/pylib;" ); + ppath << kipython << wxT( "/lib;" ); + ppath << kipython << wxT( "/dll" ); wxSetEnv( wxT( "PYTHONPATH" ), ppath ); - DBG( std::cout << "set PYTHONPATH to " << TO_UTF8(ppath) << "\n"; ) + // DBG( std::cout << "set PYTHONPATH to " << TO_UTF8( ppath ) << "\n"; ) // Add python executable path: wxGetEnv( wxT( "PATH" ), &ppath ); + if( !ppath.Contains( python_us ) ) { - kipython << wxT(";") << ppath; + kipython << wxT( ";" ) << ppath; wxSetEnv( wxT( "PATH" ), kipython ); - DBG( std::cout << "set PATH to " << TO_UTF8(kipython) << "\n"; ) + // DBG( std::cout << "set PATH to " << TO_UTF8( kipython ) << "\n"; ) } } } @@ -263,14 +253,20 @@ static bool scriptingSetup() // Add default paths to PYTHONPATH wxString pypath; + // User scripting folder (~/Library/Application Support/kicad/scripting/plugins) pypath = GetOSXKicadUserDataDir() + wxT( "/scripting/plugins" ); + // Machine scripting folder (/Library/Application Support/kicad/scripting/plugins) pypath += wxT( ":" ) + GetOSXKicadMachineDataDir() + wxT( "/scripting/plugins" ); + // Bundle scripting folder (/Contents/SharedSupport/scripting/plugins) pypath += wxT( ":" ) + GetOSXKicadDataDir() + wxT( "/scripting/plugins" ); + // Bundle wxPython folder (/Contents/Frameworks/python/site-packages) - pypath += wxT( ":" ) + Pgm().GetExecutablePath() + wxT( "Contents/Frameworks/python/site-packages" ); + pypath += wxT( ":" ) + Pgm().GetExecutablePath() + + wxT( "Contents/Frameworks/python/site-packages" ); + // Original content of $PYTHONPATH if( wxGetenv("PYTHONPATH") != NULL ) { @@ -289,6 +285,7 @@ static bool scriptingSetup() wxLogSysError( wxT( "pcbnewInitPythonScripting() failed." ) ); return false; } + return true; } #endif // KICAD_SCRIPTING diff --git a/scripting/python_scripting.cpp b/scripting/python_scripting.cpp index 494195cf3d..15f0d6c156 100644 --- a/scripting/python_scripting.cpp +++ b/scripting/python_scripting.cpp @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2012 NBEE Embedded Systems, Miguel Angel Ajo - * Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -68,7 +68,7 @@ static void swigAddModule( const char* name, void (* initfunc)() ) } -/* Add the builting python modules */ +/* Add the builtin python modules */ static void swigAddBuiltin() { @@ -140,6 +140,13 @@ bool pcbnewInitPythonScripting( const char * aUserPluginsPath ) #ifdef KICAD_SCRIPTING_WXPYTHON PyEval_InitThreads(); + char cmd[1024]; + // Make sure that that the correct version of wxPython is loaded. In systems where there + // are different versions of wxPython installed this can lead to select wrong wxPython + // version being selected. + snprintf( cmd, 1023, "import wxversion; wxversion.select('%s')", WXPYTHON_VERSION ); + PyRun_SimpleString( cmd ); + // Load the wxPython core API. Imports the wx._core_ module and sets a // local pointer to a function table located there. The pointer is used // internally by the rest of the API functions. @@ -181,7 +188,7 @@ void pcbnewFinishPythonScripting() } -#if defined(KICAD_SCRIPTING_WXPYTHON) +#if defined( KICAD_SCRIPTING_WXPYTHON ) void RedirectStdio() {