diff -up mathgl-8.0.1/lang/CMakeLists.txt.lang mathgl-8.0.1/lang/CMakeLists.txt --- mathgl-8.0.1/lang/CMakeLists.txt.lang 2022-01-11 13:48:54.000000000 -0700 +++ mathgl-8.0.1/lang/CMakeLists.txt 2022-10-05 20:17:12.149704032 -0600 @@ -145,4 +145,8 @@ message(STATUS "${oct_prog} ${oct_host} endif(enable-octave-install) set(mgl_clean_files ${mgl_clean_files} mathgl) endif(enable-octave) + +#add_subdirectory( python2 ) +add_subdirectory( python3 ) + set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${mgl_clean_files}") diff -up mathgl-8.0.1/lang/numpy.i.lang mathgl-8.0.1/lang/numpy.i --- mathgl-8.0.1/lang/numpy.i.lang 2022-01-11 13:48:54.000000000 -0700 +++ mathgl-8.0.1/lang/numpy.i 2022-10-05 20:22:27.909092484 -0600 @@ -97,7 +97,7 @@ { /* Given a PyObject, return a string describing its type. */ - char* pytype_string(PyObject* py_obj) { + const char* pytype_string(PyObject* py_obj) { if (py_obj == NULL ) return "C NULL value"; if (py_obj == Py_None ) return "Python None" ; if (PyCallable_Check(py_obj)) return "callable" ; @@ -114,8 +114,8 @@ /* Given a NumPy typecode, return a string describing the type. */ - char* typecode_string(int typecode) { - static char* type_names[25] = {"bool", "byte", "unsigned byte", + const char* typecode_string(int typecode) { + static const char* type_names[25] = {"bool", "byte", "unsigned byte", "short", "unsigned short", "int", "unsigned int", "long", "unsigned long", "long long", "unsigned long long", @@ -157,8 +157,8 @@ } else if is_array(input) { - char* desired_type = typecode_string(typecode); - char* actual_type = typecode_string(array_type(input)); + const char* desired_type = typecode_string(typecode); + const char* actual_type = typecode_string(array_type(input)); PyErr_Format(PyExc_TypeError, "Array of type '%s' required. Array of type '%s' given", desired_type, actual_type); @@ -166,8 +166,8 @@ } else { - char * desired_type = typecode_string(typecode); - char * actual_type = pytype_string(input); + const char * desired_type = typecode_string(typecode); + const char * actual_type = pytype_string(input); PyErr_Format(PyExc_TypeError, "Array of type '%s' required. A '%s' was given", desired_type, actual_type); @@ -305,6 +305,95 @@ return ary1; } + /* The following code was added by Ilmar M. Wilbers for forcing a copy of the + * object even when it is a NumPy array. This is meant for use with the + * IN_ARRAY typemaps, and allows the user to perform changes on an array + * without these chenges being reflected in the calling code. + */ + + /* Convert the given PyObject to a NumPy array with the given + * typecode as a copy. On success, return a valid PyArrayObject* with the + * correct type. On failure, the python error string will be set and + * the routine returns NULL. + */ + PyArrayObject* obj_to_array_force_conversion(PyObject* input, int typecode, + int* is_new_object) + { + PyArrayObject* ary = NULL; + PyObject* py_obj; + if (is_array(input) && (typecode == NPY_NOTYPE || + PyArray_EquivTypenums(array_type(input),typecode))) + { + py_obj = PyArray_Copy((PyArrayObject*) input); + ary = (PyArrayObject*) py_obj; + *is_new_object = 1; + } + else + { + py_obj = PyArray_FROMANY(input, typecode, 0, 0, NPY_DEFAULT); + /* If NULL, PyArray_FromObject will have set python error value.*/ + ary = (PyArrayObject*) py_obj; + *is_new_object = 1; + } + return ary; + } + + /* Convert a given PyObject to a contiguous PyArrayObject of the + * specified type. If the input object is not a contiguous + * PyArrayObject, a new one will be created and the new object flag + * will be set. + */ + PyArrayObject* obj_to_array_contiguous_force_conversion(PyObject* input, + int typecode, + int* is_new_object) + { + int is_new1 = 0; + int is_new2 = 0; + PyArrayObject* ary2; + PyArrayObject* ary1 = obj_to_array_force_conversion(input, typecode, + &is_new1); + if (ary1) + { + ary2 = make_contiguous(ary1, &is_new2, 0, 0); + if ( is_new1 && is_new2) + { + Py_DECREF(ary1); + } + ary1 = ary2; + } + *is_new_object = is_new1 || is_new2; + return ary1; + } + + /* Convert a given PyObject to a Fortran-ordered PyArrayObject of the + * specified type. If the input object is not a Fortran-ordered + * PyArrayObject, a new one will be created and the new object flag + * will be set. + */ + PyArrayObject* obj_to_array_fortran_force_conversion(PyObject* input, + int typecode, + int* is_new_object) + { + int is_new1 = 0; + int is_new2 = 0; + PyArrayObject* ary2; + PyArrayObject* ary1 = obj_to_array_force_conversion(input, typecode, + &is_new1); + if (ary1) + { + ary2 = make_fortran(ary1, &is_new2, 0, 0); + if (is_new1 && is_new2) + { + Py_DECREF(ary1); + } + ary1 = ary2; + } + *is_new_object = is_new1 || is_new2; + return ary1; + } + /* End modifications by Ilmar M. Wilbers + */ + } /* end fragment */ @@ -599,7 +688,7 @@ (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[1] = { $1_dim0 }; - array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + array = obj_to_array_contiguous_force_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 1) || !require_size(array, size, 1)) SWIG_fail; @@ -626,7 +715,7 @@ (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[1] = { -1 }; - array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + array = obj_to_array_contiguous_force_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 1) || !require_size(array, size, 1)) SWIG_fail; @@ -654,7 +743,7 @@ (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[1] = {-1}; - array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + array = obj_to_array_contiguous_force_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 1) || !require_size(array, size, 1)) SWIG_fail; @@ -682,7 +771,7 @@ (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[2] = { $1_dim0, $1_dim1 }; - array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + array = obj_to_array_contiguous_force_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 2) || !require_size(array, size, 2)) SWIG_fail; @@ -709,7 +798,7 @@ (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[2] = { -1, -1 }; - array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + array = obj_to_array_contiguous_force_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 2) || !require_size(array, size, 2)) SWIG_fail; @@ -738,7 +827,7 @@ (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[2] = { -1, -1 }; - array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + array = obj_to_array_contiguous_force_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 2) || !require_size(array, size, 2)) SWIG_fail; @@ -767,7 +856,7 @@ (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[2] = { -1, -1 }; - array = obj_to_array_fortran_allow_conversion($input, DATA_TYPECODE, + array = obj_to_array_fortran_force_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 2) || !require_size(array, size, 2) || !require_fortran(array)) SWIG_fail; @@ -796,7 +885,7 @@ (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[2] = { -1, -1 }; - array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + array = obj_to_array_contiguous_force_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 2) || !require_size(array, size, 2) || !require_fortran(array)) SWIG_fail; @@ -825,7 +914,7 @@ (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[3] = { $1_dim0, $1_dim1, $1_dim2 }; - array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + array = obj_to_array_contiguous_force_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 3) || !require_size(array, size, 3)) SWIG_fail; @@ -853,7 +942,7 @@ (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[3] = { -1, -1, -1 }; - array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + array = obj_to_array_contiguous_force_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 3) || !require_size(array, size, 3)) SWIG_fail; @@ -884,7 +973,7 @@ (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[3] = { -1, -1, -1 }; - array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + array = obj_to_array_contiguous_force_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 3) || !require_size(array, size, 3)) SWIG_fail; @@ -915,7 +1004,7 @@ (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[3] = { -1, -1, -1 }; - array = obj_to_array_fortran_allow_conversion($input, DATA_TYPECODE, + array = obj_to_array_fortran_force_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 3) || !require_size(array, size, 3) | !require_fortran(array)) SWIG_fail; @@ -946,7 +1035,7 @@ (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[3] = { -1, -1, -1 }; - array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + array = obj_to_array_contiguous_force_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 3) || !require_size(array, size, 3) || !require_fortran(array)) SWIG_fail; @@ -1289,7 +1378,7 @@ npy_intp dims[1]; if (!PyInt_Check($input)) { - char* typestring = pytype_string($input); + const char* typestring = pytype_string($input); PyErr_Format(PyExc_TypeError, "Int dimension expected. '%s' given.", typestring); @@ -1317,7 +1406,7 @@ npy_intp dims[1]; if (!PyInt_Check($input)) { - char* typestring = pytype_string($input); + const char* typestring = pytype_string($input); PyErr_Format(PyExc_TypeError, "Int dimension expected. '%s' given.", typestring); diff -up mathgl-8.0.1/lang/python3/CMakeLists.txt.lang mathgl-8.0.1/lang/python3/CMakeLists.txt --- mathgl-8.0.1/lang/python3/CMakeLists.txt.lang 2022-10-05 20:17:12.061703367 -0600 +++ mathgl-8.0.1/lang/python3/CMakeLists.txt 2022-10-05 20:17:12.153704063 -0600 @@ -0,0 +1,75 @@ +set(src_imp_dep +../../include/mgl2/type.h +../../include/mgl2/data.h +../../include/mgl2/mgl.h +../mgl.i +../data.i +../type.i +) + +set(mgl_clean_files "") + +SET_SOURCE_FILES_PROPERTIES(../mathgl.i ../numpy.i PROPERTIES CPLUSPLUS ON) + +if(enable-python) + set(Python_ADDITIONAL_VERSIONS 3.6) + unset(PYTHONINTERP_FOUND) + unset(PYTHON_EXECUTABLE CACHE) + FIND_PACKAGE(PythonInterp 3.6 REQUIRED) + if(NOT PYTHONINTERP_FOUND) + message(SEND_ERROR "Couldn't find python interpreter.") + endif(NOT PYTHONINTERP_FOUND) + + unset(PYTHONLIBS_FOUND) + unset(PYTHON_LIBRARIES CACHE) + unset(PYTHON_INCLUDE_PATH CACHE) + unset(PYTHON_INCLUDE_DIRS CACHE) + unset(PYTHON_DEBUG_LIBRARIES CACHE) + unset(PYTHONLIBS_VERSION_STRING CACHE) + unset(PYTHON_LIBRARY CACHE) + unset(PYTHON_INCLUDE_DIR CACHE) + FIND_PACKAGE(PythonLibs 3.6) + if(NOT PYTHONLIBS_FOUND) + message(SEND_ERROR "Couldn't find python development libraries.") + endif(NOT PYTHONLIBS_FOUND) + execute_process( + COMMAND ${PYTHON_EXECUTABLE} -c "import numpy; print(numpy.get_include())" + OUTPUT_VARIABLE NUMPY_INCLUDE_PATH + RESULT_VARIABLE NUMPY_ERR + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + if(NOT NUMPY_INCLUDE_PATH) + message(SEND_ERROR "Couldn't find numpy.") + endif(NOT NUMPY_INCLUDE_PATH) + + include_directories(${PYTHON_INCLUDE_DIR} ${NUMPY_INCLUDE_PATH}) + execute_process( + COMMAND ${PYTHON_EXECUTABLE} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib(prefix='${CMAKE_INSTALL_PREFIX}'))" + OUTPUT_VARIABLE MGL_PYTHON_SITE_PACKAGES + OUTPUT_STRIP_TRAILING_WHITESPACE) + set(SWIG_MODULE_mathglp3_EXTRA_DEPS ../numpy.i ${src_imp_dep}) + SWIG_ADD_MODULE(mathglp3 python ../mathgl.i) + SWIG_LINK_LIBRARIES(mathglp3 mgl ${PYTHON_LIBRARIES}) + execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('SO'))" + OUTPUT_VARIABLE MGL_PYTHON_LIB_SUFFIX + OUTPUT_STRIP_TRAILING_WHITESPACE) + set_target_properties(_mathglp3 PROPERTIES + BUILD_WITH_INSTALL_RPATH ON + OUTPUT_NAME _mathgl + SUFFIX ${MGL_PYTHON_LIB_SUFFIX}) + add_custom_command(OUTPUT mathgl.pyc + COMMAND ${PYTHON_EXECUTABLE} + ARGS -c \"from py_compile import compile\; compile('mathgl.py') \" + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/lang/python3 + DEPENDS _mathglp3 + ) + add_custom_target(mgl_python_modulep3 ALL DEPENDS _mathglp3 mathgl.pyc) + + install(FILES ${MathGL2_BINARY_DIR}/lang/python3/mathgl.py DESTINATION ${MGL_PYTHON_SITE_PACKAGES}) +# harcoded for now. another way is to make glob search on *pyc in __pycache__ dir + install(FILES ${MathGL2_BINARY_DIR}/lang/python3/__pycache__/mathgl.cpython-36.pyc DESTINATION ${MGL_PYTHON_SITE_PACKAGES}/__pycache__) + install (TARGETS _mathglp3 LIBRARY DESTINATION ${MGL_PYTHON_SITE_PACKAGES}) + set(mgl_clean_files ${mgl_clean_files} mathgl.py) +endif(enable-python) + +set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${mgl_clean_files}")