From 6e576fe5563b8c5cd5ea212b090f6385cb9fcfcc Mon Sep 17 00:00:00 2001 From: Martyn Gigg <martyn.gigg@stfc.ac.uk> Date: Fri, 9 Sep 2011 14:40:38 +0000 Subject: [PATCH] Refs #3614. Updates to get the Python stuff going on Windows. --- Code/Mantid/Build/CMake/CommonSetup.cmake | 3 ++ Code/Mantid/Build/CMake/FindPyUnitTest.cmake | 16 ++++++-- Code/Mantid/Build/CMake/WindowsSetup.cmake | 1 + Code/Mantid/Framework/CMakeLists.txt | 2 +- .../api/AlgorithmWrapper.h | 40 +++++++------------ .../kernel/PropertyMarshal.h | 9 +++-- .../PythonInterface/mantid/CMakeLists.txt | 34 ++++++++++++++-- .../PythonInterface/mantid/__init__.py | 15 +++++-- .../PythonInterface/mantid/api/CMakeLists.txt | 14 ++----- .../mantid/api/src/Algorithm.cpp | 8 +--- .../mantid/api/src/AlgorithmManager.cpp | 8 ++-- .../mantid/api/src/AlgorithmWrapper.cpp | 40 ++++++++++++++----- .../mantid/kernel/CMakeLists.txt | 22 +++++----- .../PythonInterface/mantid/kernel/dlopen.py | 27 ++++++++++++- .../test/cpp/PythonObjectInstantiatorTest.h | 7 ++-- .../test/python/AlgorithmManagerTest.py | 7 ++-- .../test/python/PythonAlgorithmTest.py | 12 +++--- 17 files changed, 167 insertions(+), 98 deletions(-) diff --git a/Code/Mantid/Build/CMake/CommonSetup.cmake b/Code/Mantid/Build/CMake/CommonSetup.cmake index 6f6dc1c5771..e2524584f4f 100644 --- a/Code/Mantid/Build/CMake/CommonSetup.cmake +++ b/Code/Mantid/Build/CMake/CommonSetup.cmake @@ -3,6 +3,9 @@ if ( CMAKE_MAJOR_VERSION EQUAL 2 AND CMAKE_MINOR_VERSION LESS 8 ) message ( WARNING " Running tests via CTest will not work with this version of CMake. If you need this functionality, upgrade to CMake 2.8." ) endif () +# Include useful utils +include ( MantidUtils ) + # Make the default build type Release if ( NOT CMAKE_CONFIGURATION_TYPES ) if ( NOT CMAKE_BUILD_TYPE ) diff --git a/Code/Mantid/Build/CMake/FindPyUnitTest.cmake b/Code/Mantid/Build/CMake/FindPyUnitTest.cmake index cccd1474466..ff292d22450 100644 --- a/Code/Mantid/Build/CMake/FindPyUnitTest.cmake +++ b/Code/Mantid/Build/CMake/FindPyUnitTest.cmake @@ -43,10 +43,20 @@ macro ( PYUNITTEST_ADD_TEST _pyunit_testname_file _helper_files ) ${_pyunit_outputdir}/${helper_file} ) endforeach( file ${_helper_files} ) - - add_test (NAME ${_pyunit_testname}_py - COMMAND ${CMAKE_COMMAND} -E chdir "${CMAKE_BINARY_DIR}/bin" + if( MSVC ) + # MSVC needs separate tests for Release and Debug as they have to call different + # python executables so that the debug libraries will load + add_test (NAME ${_pyunit_testname}_Release_py CONFIGURATIONS Release + COMMAND ${CMAKE_COMMAND} -E chdir "${CMAKE_BINARY_DIR}/bin" + ${PYTHON_EXECUTABLE} $<TARGET_FILE_DIR:PythonAPI>/${_pyunit_testname_file} ) + add_test (NAME ${_pyunit_testname}_Debug_py CONFIGURATIONS Debug + COMMAND ${CMAKE_COMMAND} -E chdir "${CMAKE_BINARY_DIR}/bin" + ${PYTHON_EXECUTABLE_DEBUG} $<TARGET_FILE_DIR:PythonAPI>/${_pyunit_testname_file} ) + else() + add_test (NAME ${_pyunit_testname}_py + COMMAND ${CMAKE_COMMAND} -E chdir "${CMAKE_BINARY_DIR}/bin" ${PYTHON_EXECUTABLE} $<TARGET_FILE_DIR:PythonAPI>/${_pyunit_testname_file} ) + endif() # add all of the individual tests - this introduces a race condition #foreach (part ${ARGN}) diff --git a/Code/Mantid/Build/CMake/WindowsSetup.cmake b/Code/Mantid/Build/CMake/WindowsSetup.cmake index 5bef25454a2..06f7a112cd4 100644 --- a/Code/Mantid/Build/CMake/WindowsSetup.cmake +++ b/Code/Mantid/Build/CMake/WindowsSetup.cmake @@ -39,6 +39,7 @@ set ( PYTHON_DEBUG_LIBRARIES ${PYTHON_DEBUG_LIBRARY} ) set ( PYTHON_LIBRARIES optimized ${PYTHON_LIBRARIES} debug ${PYTHON_DEBUG_LIBRARIES} ) ## The executable set ( PYTHON_EXECUTABLE "${CMAKE_LIBRARY_PATH}/Python27/python.exe" ) +set ( PYTHON_EXECUTABLE_DEBUG "${CMAKE_LIBRARY_PATH}/Python27/python_d.exe" ) ## Add the include directory include_directories ( ${PYTHON_INCLUDE_DIRS} ) diff --git a/Code/Mantid/Framework/CMakeLists.txt b/Code/Mantid/Framework/CMakeLists.txt index da71dc66160..a912e6c50c2 100644 --- a/Code/Mantid/Framework/CMakeLists.txt +++ b/Code/Mantid/Framework/CMakeLists.txt @@ -110,7 +110,7 @@ add_subdirectory (API) set ( MANTIDLIBS ${MANTIDLIBS} API ) add_subdirectory (PythonAPI) -#add_subdirectory (PythonInterface) +add_subdirectory (PythonInterface) find_package ( Matlab ) if( MATLAB_FOUND ) diff --git a/Code/Mantid/Framework/PythonInterface/inc/MantidPythonInterface/api/AlgorithmWrapper.h b/Code/Mantid/Framework/PythonInterface/inc/MantidPythonInterface/api/AlgorithmWrapper.h index 3139e82fd8f..6716ad1b6d1 100644 --- a/Code/Mantid/Framework/PythonInterface/inc/MantidPythonInterface/api/AlgorithmWrapper.h +++ b/Code/Mantid/Framework/PythonInterface/inc/MantidPythonInterface/api/AlgorithmWrapper.h @@ -5,14 +5,18 @@ // Includes //----------------------------------------------------------------------------- #include "MantidAPI/Algorithm.h" -#include <boost/python/wrapper.hpp> - +#include "MantidPythonInterface/kernel/WrapperHelpers.h" namespace Mantid { namespace PythonInterface { /** + This class wraps the Algorithm class and allows classes in Python + to inherit from it. + + This class is treated by Boost Python as if it were of type Algorithm. + @author Martyn Gigg, Tessella plc Copyright © 2011 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory @@ -35,34 +39,20 @@ namespace Mantid File change history is stored at: <https://svn.mantidproject.org/mantid/trunk/Code/Mantid>. Code Documentation is available at: <http://doxygen.mantidproject.org> */ - - /** - * This class simply acts as a marker for now. - * It is required so that the export functions - * can properly mark Algorithm as a base class - * of a PythonAlgorithm. - * - * Trying to do this with the wrapper below - * causes a compilation error - */ - class PythonAlgorithm : public API::Algorithm - {}; - - /** - This class wraps the PythonAlgorithm class and allows classes in Python - to inherit from it. - - This class is treated by Boost Python as if it were of type PythonAlgorithm. - */ - - class AlgorithmWrapper : public PythonAlgorithm, public boost::python::wrapper<PythonAlgorithm> + class AlgorithmWrapper : public API::Algorithm, public boost::python::wrapper<API::Algorithm> { public: /// Returns the name of the algorithm virtual const std::string name() const; - /// Returns a version of the algorithm, default = 1 + /// A default version, chosen if no override exists + const std::string defaultName() const; + + /// Returns a version of the algorithm virtual int version() const; - /// Returns a category of the algorithm. A default implementation is provided + /// A default version, chosen if there is no override + int defaultVersion() const; + + /// Returns a category of the algorithm. virtual const std::string category() const; private: diff --git a/Code/Mantid/Framework/PythonInterface/inc/MantidPythonInterface/kernel/PropertyMarshal.h b/Code/Mantid/Framework/PythonInterface/inc/MantidPythonInterface/kernel/PropertyMarshal.h index 4f2f2305924..9eb4ed4da98 100644 --- a/Code/Mantid/Framework/PythonInterface/inc/MantidPythonInterface/kernel/PropertyMarshal.h +++ b/Code/Mantid/Framework/PythonInterface/inc/MantidPythonInterface/kernel/PropertyMarshal.h @@ -1,6 +1,7 @@ #ifndef MANTID_PYTHONINTERFACE_PROPERTYMARSHAL_H_ #define MANTID_PYTHONINTERFACE_PROPERTYMARSHAL_H_ +#include "MantidKernel/System.h" #include "MantidKernel/Property.h" #include "MantidKernel/IPropertyManager.h" @@ -39,7 +40,7 @@ namespace Mantid * its virtual functions are overridden in templated derived classes * that can extract the correct type from the Python object */ - struct PropertyHandler + struct DLLExport PropertyHandler { /// Virtual Destructor virtual ~PropertyHandler() {}; @@ -50,7 +51,7 @@ namespace Mantid * A templated marshal that calls the corresponding setProperty method on the given algorithm */ template<typename CType> - struct TypedHandler : public PropertyHandler + struct DLLExport TypedHandler : public PropertyHandler { /// Set function to handle Python -> C++ calls and get the correct type void set(Kernel::IPropertyManager* alg, const std::string &name, boost::python::object value) @@ -66,7 +67,7 @@ namespace Mantid * assigned polymorphically. This can be removed when the bug is fixed */ template<> - struct TypedHandler<std::string> : public PropertyHandler + struct DLLExport TypedHandler<std::string> : public PropertyHandler { /// Set function to handle Python -> C++ calls and get the correct type void set(Kernel::IPropertyManager* alg, const std::string &name, boost::python::object value) @@ -82,7 +83,7 @@ namespace Mantid * Defines static functions that allow method calls on Python * objects to be routed here */ - class PropertyMarshal + class DLLExport PropertyMarshal { public: /// Typedef the map of python types to C++ functions diff --git a/Code/Mantid/Framework/PythonInterface/mantid/CMakeLists.txt b/Code/Mantid/Framework/PythonInterface/mantid/CMakeLists.txt index 3635fcf22ab..820cde49217 100644 --- a/Code/Mantid/Framework/PythonInterface/mantid/CMakeLists.txt +++ b/Code/Mantid/Framework/PythonInterface/mantid/CMakeLists.txt @@ -23,7 +23,7 @@ MACRO( CREATE_MODULE MODULE_TEMPLATE OUTPUT_FILE EXPORT_FILES SRCS ) string( REGEX REPLACE "void " "" EXPORT "${EXPORT}" ) set ( EXPORT_FUNCTIONS "${EXPORT_FUNCTIONS}\n${EXPORT};" ) endforeach(EXPORT ${EXPORTS}) - endforeach( CPPFILE ${${EXPORT_FILES}} ) + endforeach( CPPFILE ${${EXPORT_FILES}} ) string( STRIP "${EXPORT_DECLARE}" EXPORT_DECLARE ) string( STRIP "${EXPORT_FUNCTIONS}" EXPORT_FUNCTIONS ) @@ -33,6 +33,28 @@ MACRO( CREATE_MODULE MODULE_TEMPLATE OUTPUT_FILE EXPORT_FILES SRCS ) LIST ( APPEND ${SRCS} ${${EXPORT_FILES}} ${OUTPUT_FILE} ) ENDMACRO( ) +#################################################################################### +# Define a function for setting the correct properties on the individual targets +#################################################################################### +FUNCTION( SET_PYTHON_PROPERTIES TARGET_NAME ) + # Library name needs to end in .pyd for Windows + if ( MSVC ) + set_target_properties ( ${TARGET_NAME} PROPERTIES SUFFIX .pyd + COMPILE_FLAGS "/bigobj /w44005 /w44244") # bigobj required for intensive templating + elseif ( APPLE ) + # and in .so on the Mac + set_target_properties ( ${TARGET_NAME} PROPERTIES SUFFIX .so ) + endif () + # No prefix as this is loaded by Python not the OS + set ( CMAKE_SHARED_LIBRARY_PREFIX ) + # Debug python library expects imported module names to end in _d + if ( PYTHON_DEBUG_LIBRARY ) + set_target_properties ( ${TARGET_NAME} PROPERTIES DEBUG_OUTPUT_NAME ${TARGET_NAME}_d ) + endif () + # Group within VS + set_property ( TARGET ${TARGET_NAME} PROPERTY FOLDER "MantidFramework/PythonInterface" ) +ENDFUNCTION() + #################################################################################### # Sub modules #################################################################################### @@ -60,6 +82,10 @@ foreach ( PYFILE ${PY_FILES} ) set ( PYTHON_INSTALL_FILES ${PYTHON_INSTALL_FILES} ${OUTPUT_DIR}/${PYFILE} ) endforeach ( PYFILE ) -# Create a grouped target -add_custom_target ( PythonInterface DEPENDS _kernel _api ${PYTHON_INSTALL_FILES} ) - +# Create a target for non MSVC platforms +if ( MSVC ) + add_custom_target ( mantid DEPENDS _kernel _api ${PYTHON_INSTALL_FILES} ) + set_property ( TARGET mantid PROPERTY FOLDER "MantidFramework/PythonInterface" ) +else () + add_custom_target ( PythonInterface DEPENDS _kernel _api ${PYTHON_INSTALL_FILES} ) +endif( MSVC ) diff --git a/Code/Mantid/Framework/PythonInterface/mantid/__init__.py b/Code/Mantid/Framework/PythonInterface/mantid/__init__.py index 65019939b8f..51cbad12d76 100644 --- a/Code/Mantid/Framework/PythonInterface/mantid/__init__.py +++ b/Code/Mantid/Framework/PythonInterface/mantid/__init__.py @@ -3,16 +3,23 @@ import sys import os -_moduledir = os.path.dirname(__file__) +######################################################## +# Path settings +######################################################## # Ensure the sub modules can see each other +_moduledir = os.path.abspath(os.path.dirname(__file__)) sys.path.append(_moduledir) -# If MANTIDPATH is not set, peek to see if a Mantid.properties file -# is in the parent directory +# Peek to see if a Mantid.properties file is in the parent directory, +# if so assume that it is the required Mantid bin directory containing +# the Mantid libraries and ignore any MANTIDPATH that has been set _bindir = os.path.dirname(_moduledir) -if not os.environ.has_key('MANTIDPATH') and os.path.exists(os.path.join(_bindir, 'Mantid.properties')): +if os.path.exists(os.path.join(_bindir, 'Mantid.properties')): os.environ['MANTIDPATH'] = _bindir +######################################################## +# Mantid imports +######################################################## # Mantid imports from api import framework_mgr diff --git a/Code/Mantid/Framework/PythonInterface/mantid/api/CMakeLists.txt b/Code/Mantid/Framework/PythonInterface/mantid/api/CMakeLists.txt index 259433a539a..519ee13b463 100644 --- a/Code/Mantid/Framework/PythonInterface/mantid/api/CMakeLists.txt +++ b/Code/Mantid/Framework/PythonInterface/mantid/api/CMakeLists.txt @@ -58,14 +58,8 @@ endforeach ( PYFILE ) ############################################################################################# add_library ( _api ${SRC_FILES} ${INC_FILES} ${PYTHON_INSTALL_FILES} ) -# Set the target directory to to be inside the Python package -set_target_properties ( _api PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PYTHON_PKG_ROOT}/api ) -# No prefix as this is loaded by Python not the OS -set ( CMAKE_SHARED_LIBRARY_PREFIX ) -# Debug python library expects imported module names to end in _d -if ( PYTHON_DEBUG_LIBRARY ) - set_target_properties ( _kernel PROPERTIES DEBUG_OUTPUT_NAME _api_d ) -endif () -# Add the required dependencies -target_link_libraries ( _api ${PYTHON_DEPS} ) +set_python_properties( _api ) +move_target ( _api ${OUTPUT_DIR} .pyd ) +# Add the required dependencies +target_link_libraries ( _api _kernel ${PYTHON_DEPS} ) diff --git a/Code/Mantid/Framework/PythonInterface/mantid/api/src/Algorithm.cpp b/Code/Mantid/Framework/PythonInterface/mantid/api/src/Algorithm.cpp index 6458abad271..fabf7c1abb6 100644 --- a/Code/Mantid/Framework/PythonInterface/mantid/api/src/Algorithm.cpp +++ b/Code/Mantid/Framework/PythonInterface/mantid/api/src/Algorithm.cpp @@ -4,6 +4,7 @@ #include <boost/python/class.hpp> #include <boost/python/register_ptr_to_python.hpp> #include <boost/python/return_internal_reference.hpp> +#include <boost/python/pure_virtual.hpp> using Mantid::Kernel::IPropertyManager; @@ -38,12 +39,7 @@ void export_algorithmHierarchy() ; register_ptr_to_python<boost::shared_ptr<Algorithm> >(); - class_<Algorithm, bases<IAlgorithm>, boost::noncopyable>("Algorithm", "Base for all algorithms", no_init) - ; - - register_ptr_to_python<boost::shared_ptr<AlgorithmWrapper> >(); - // We change the name because the boost::python framework makes AlgorithmWrapper appear as it is a PythonAlgorithm - class_<AlgorithmWrapper, bases<Algorithm>, boost::noncopyable>("PythonAlgorithm", "Base for all Python algorithms") + class_<AlgorithmWrapper, bases<IAlgorithm>, boost::noncopyable>("Algorithm", "Base class for all algorithms") ; } diff --git a/Code/Mantid/Framework/PythonInterface/mantid/api/src/AlgorithmManager.cpp b/Code/Mantid/Framework/PythonInterface/mantid/api/src/AlgorithmManager.cpp index 938e0239c3f..8632819cb2a 100644 --- a/Code/Mantid/Framework/PythonInterface/mantid/api/src/AlgorithmManager.cpp +++ b/Code/Mantid/Framework/PythonInterface/mantid/api/src/AlgorithmManager.cpp @@ -32,13 +32,13 @@ namespace // A function to register an algorithm from Python void registerAlgorithm(boost::python::object obj) { - // The current frame should know what a PythonAlgorithm is, or it + // The current frame should know what an Algorithm is, or it // couldn't create one. Get the class object from the f_globals PyObject *defs = PyEval_GetFrame()->f_globals; - PyObject *pyalgClass = PyDict_GetItemString(defs, "PythonAlgorithm"); + PyObject *pyalgClass = PyDict_GetItemString(defs, "Algorithm"); if( !pyalgClass ) { - throw std::runtime_error("Unable to find PythonAlgorithm definition, cannot register algorithm.\nHas the definition been imported into the current scope"); + throw std::runtime_error("Unable to find Algorithm definition, cannot register algorithm.\nHas the definition been imported"); } // obj could be or instance/class, check instance first PyObject *classObject(NULL); @@ -52,7 +52,7 @@ namespace } else { - throw std::invalid_argument("Cannot register an algorithm that does not derive from PythonAlgorithm."); + throw std::invalid_argument("Cannot register an algorithm that does not derive from Algorithm."); } boost::python::object classType(handle<>(borrowed(classObject))); AlgorithmFactory::Instance().subscribe(new PythonObjectInstantiator<Algorithm>(classType)); diff --git a/Code/Mantid/Framework/PythonInterface/mantid/api/src/AlgorithmWrapper.cpp b/Code/Mantid/Framework/PythonInterface/mantid/api/src/AlgorithmWrapper.cpp index 271d802b80c..69dc8709f96 100644 --- a/Code/Mantid/Framework/PythonInterface/mantid/api/src/AlgorithmWrapper.cpp +++ b/Code/Mantid/Framework/PythonInterface/mantid/api/src/AlgorithmWrapper.cpp @@ -17,44 +17,64 @@ namespace Mantid */ const std::string AlgorithmWrapper::name() const { - std::string name(""); - if( boost::python::override fn = this->get_override("name_") ) + static const char * method = "name"; + std::string name; + if( WrapperHelpers::typeHasAttribute(*this, method) ) { - name = boost::python::call<std::string>(fn.ptr()); // Avoid a warning with just calling return fn() which docs say you can do. + name = call<std::string>(get_override(method).ptr()); // Avoid a warning with just calling return fn() which docs say you can do. } else { - // Use the class name - PyObject *self = boost::python::detail::wrapper_base_::get_owner(*this); - name = std::string(self->ob_type->tp_name); + name = this->defaultName(); } return name; } + /** + * Returns the base class version of name + */ + const std::string AlgorithmWrapper::defaultName() const + { + // Use the class name + PyObject *self = boost::python::detail::wrapper_base_::get_owner(*this); + return std::string(self->ob_type->tp_name); + } + /** * Returns the version of the algorithm. If not overridden * it returns 1 */ int AlgorithmWrapper::version() const { + static const char * method = "version"; int version(1); - if( boost::python::override fn = this->get_override("version_") ) + if( WrapperHelpers::typeHasAttribute(*this, method) ) { - version = boost::python::call<int>(fn.ptr()); + version = call<int>(get_override(method).ptr()); // Avoid a warning with just calling return fn() which docs say you can do. + } + else + { + version = this->defaultVersion(); } return version; } + int AlgorithmWrapper::defaultVersion() const + { + return 1; + } + /** * Returns the category of the algorithm. If not overridden * it returns "PythonAlgorithm" */ const std::string AlgorithmWrapper::category() const { + static const char * method = "category"; std::string cat("PythonAlgorithms"); - if ( boost::python::override fn = this->get_override("category_") ) + if ( WrapperHelpers::typeHasAttribute(*this, method) ) { - cat = boost::python::call<std::string>(fn.ptr()); + cat = boost::python::call<std::string>(this->get_override(method).ptr()); } return cat; } diff --git a/Code/Mantid/Framework/PythonInterface/mantid/kernel/CMakeLists.txt b/Code/Mantid/Framework/PythonInterface/mantid/kernel/CMakeLists.txt index cefe0d75a28..c479e4429da 100644 --- a/Code/Mantid/Framework/PythonInterface/mantid/kernel/CMakeLists.txt +++ b/Code/Mantid/Framework/PythonInterface/mantid/kernel/CMakeLists.txt @@ -13,12 +13,14 @@ set ( EXPORT_FILES set ( SRC_FILES src/PropertyMarshal.cpp + src/WrapperHelpers.cpp ) set ( INC_FILES ${HEADER_DIR}/kernel/PythonObjectInstantiator.h ${HEADER_DIR}/kernel/PropertyWithValue.h ${HEADER_DIR}/kernel/PropertyMarshal.h + ${HEADER_DIR}/kernel/WrapperHelpers.h ) set ( PY_FILES @@ -30,7 +32,7 @@ set ( PY_FILES set ( OUTPUT_DIR ${PYTHON_PKG_ROOT}/kernel ) ############################################################################################# -# Generate a source file from the export definitions +# Generate a source file from the export definitions and provided template ############################################################################################# CREATE_MODULE ( ${MODULE_TEMPLATE} ${CMAKE_CURRENT_BINARY_DIR}/kernel.cpp EXPORT_FILES SRC_FILES ) @@ -40,10 +42,10 @@ CREATE_MODULE ( ${MODULE_TEMPLATE} ${CMAKE_CURRENT_BINARY_DIR}/kernel.cpp EXPORT set ( PYTHON_INSTALL_FILES "" ) foreach ( PYFILE ${PY_FILES} ) add_custom_command ( OUTPUT ${OUTPUT_DIR}/${PYFILE} - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${PYFILE} - COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different - ${CMAKE_CURRENT_SOURCE_DIR}/${PYFILE} - ${OUTPUT_DIR}/${PYFILE} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${PYFILE} + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different + ${CMAKE_CURRENT_SOURCE_DIR}/${PYFILE} + ${OUTPUT_DIR}/${PYFILE} ) set ( PYTHON_INSTALL_FILES ${PYTHON_INSTALL_FILES} ${OUTPUT_DIR}/${PYFILE} ) endforeach ( PYFILE ) @@ -53,14 +55,8 @@ endforeach ( PYFILE ) ############################################################################################# add_library ( _kernel ${SRC_FILES} ${INC_FILES} ${PYTHON_INSTALL_FILES} ) -# Set the target directory to to be inside the Python package -set_target_properties ( _kernel PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PYTHON_PKG_ROOT}/kernel ) -# No prefix as this is loaded by Python not the OS -set ( CMAKE_SHARED_LIBRARY_PREFIX ) -# Debug python library expects imported module names to end in _d -if ( PYTHON_DEBUG_LIBRARY ) - set_target_properties ( _kernel PROPERTIES DEBUG_OUTPUT_NAME _kernel_d ) -endif () +set_python_properties( _kernel ) +move_target ( _kernel ${OUTPUT_DIR} .pyd ) # Add the required dependencies target_link_libraries ( _kernel ${PYTHON_DEPS} ) diff --git a/Code/Mantid/Framework/PythonInterface/mantid/kernel/dlopen.py b/Code/Mantid/Framework/PythonInterface/mantid/kernel/dlopen.py index 478e891acb3..e57d5c4c11f 100644 --- a/Code/Mantid/Framework/PythonInterface/mantid/kernel/dlopen.py +++ b/Code/Mantid/Framework/PythonInterface/mantid/kernel/dlopen.py @@ -6,8 +6,32 @@ by default. For Mantid this ensures the singleton symbols are wired up correctly """ import sys +import os import platform +####################################################################### +# Ensure the correct Mantid shared libaries are found when loading the +# python shared libraries +####################################################################### +if sys.platform.startswith('win32'): + _var = 'PATH' + _sep = ';' +else: + _sep = ':' + if sys.platform.startswith('linux'): + _var = 'LD_LIBRARY_PATH' + elif sys.platform.startswith('darwin'): + _var = 'DYLD_LIBRARY_PATH' + else: # Give it a go how it is + _var = '' + _sep = '' +_oldpath = os.environ[_var] +os.environ[_var] = os.environ['MANTIDPATH'] + _sep + _oldpath + +####################################################################### +# Public api +####################################################################### + def setup_dlopen(): """Set the flags for a call to import a shared library such that all symbols are imported. @@ -22,8 +46,8 @@ def setup_dlopen(): Returns the original flags """ + if platform.system() != "Linux": return None old_flags = sys.getdlopenflags() - if platform.system() != "Linux": return old_flags try: import DLFCN as dynload except: @@ -43,4 +67,5 @@ def restore_flags(flags): """Restores the dlopen flags to those provided, usually with the results from a call to setup_dlopen """ + if flags is None: return sys.setdlopenflags(flags) diff --git a/Code/Mantid/Framework/PythonInterface/test/cpp/PythonObjectInstantiatorTest.h b/Code/Mantid/Framework/PythonInterface/test/cpp/PythonObjectInstantiatorTest.h index f881fb0f438..5700cff8c66 100644 --- a/Code/Mantid/Framework/PythonInterface/test/cpp/PythonObjectInstantiatorTest.h +++ b/Code/Mantid/Framework/PythonInterface/test/cpp/PythonObjectInstantiatorTest.h @@ -31,7 +31,7 @@ public: ~PythonObjectInstantiatorTest() { delete m_creator; - //Py_Finalize(); - Causes Python 2.4 to fail. Need to find out why + //Py_Finalize(); //- Causes Python 2.4 to fail. Need to find out why } void test_Bare_Pointer() @@ -60,11 +60,12 @@ private: if( !m_creator ) { std::string propDir = Mantid::Kernel::ConfigService::Instance().getPropertiesDir(); + propDir += "\\"; // Escape the last backslash so python isn't confused //Assume this is where the mantid package is too std::string code = "import sys\n" "sys.path.append(r'" + propDir + "')\n" - "from mantid.api import PythonAlgorithm\n" - "class PyAlg(PythonAlgorithm):\n" + "from mantid.api import Algorithm\n" + "class PyAlg(Algorithm):\n" " pass\n"; PyRun_SimpleString(code.c_str()); PyObject *main = PyImport_AddModule("__main__"); diff --git a/Code/Mantid/Framework/PythonInterface/test/python/AlgorithmManagerTest.py b/Code/Mantid/Framework/PythonInterface/test/python/AlgorithmManagerTest.py index f93be113b87..746a4f8056a 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/AlgorithmManagerTest.py +++ b/Code/Mantid/Framework/PythonInterface/test/python/AlgorithmManagerTest.py @@ -2,10 +2,10 @@ import unittest from mantid.api import algorithm_mgr from mantid.api import (IAlgorithm, Algorithm, AlgorithmProxy, - PythonAlgorithm, register_algorithm) + register_algorithm) import sys -class IsAnAlgorithm(PythonAlgorithm): +class IsAnAlgorithm(Algorithm): def init_(self): pass @@ -40,9 +40,8 @@ class AlgorithmManagerTest(unittest.TestCase): alg = algorithm_mgr.create_unmanaged("ConvertUnits") self.assertTrue(isinstance(alg, Algorithm)) - def test_pyalg_isinstance_of_PythonAlgorithm(self): + def test_pyalg_isinstance_of_Algorithm(self): alg = IsAnAlgorithm() - self.assertTrue(isinstance(alg, PythonAlgorithm)) self.assertTrue(isinstance(alg, Algorithm)) self.assertTrue(isinstance(alg, IAlgorithm)) diff --git a/Code/Mantid/Framework/PythonInterface/test/python/PythonAlgorithmTest.py b/Code/Mantid/Framework/PythonInterface/test/python/PythonAlgorithmTest.py index fbe823b6011..c8c57b741b4 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/PythonAlgorithmTest.py +++ b/Code/Mantid/Framework/PythonInterface/test/python/PythonAlgorithmTest.py @@ -1,23 +1,23 @@ import unittest -from mantid.api import PythonAlgorithm, algorithm_mgr, register_algorithm +from mantid.api import Algorithm, algorithm_mgr, register_algorithm -class TestPyAlgDefaultAttrs(PythonAlgorithm): +class TestPyAlgDefaultAttrs(Algorithm): def init_(self): pass def exec_(self): pass -class TestPyAlgOverriddenAttrs(PythonAlgorithm): +class TestPyAlgOverriddenAttrs(Algorithm): - def name_(self): + def name(self): return 'CoolAlgorithm' - def version_(self): + def version(self): return 2 - def category_(self): + def category(self): return "BestAlgorithms" def init_(self): -- GitLab