From 599ff11eb0cdcc03320f814fdf15bdee2d8dca23 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 8 Feb 2025 05:05:00 -0500 Subject: [PATCH] remove compatibility for compiling LAMMPS with Python 2.x and Python 3.5 and older --- lib/python/Makefile.lammps.python2 | 7 ----- ...s.python2.7 => Makefile.lammps.python3.13} | 0 lib/python/README | 27 +++++++++---------- src/KOKKOS/mliap_model_python_kokkos.cpp | 4 +-- src/ML-IAP/mliap_model_python.cpp | 4 +-- src/PYTHON/fix_python_invoke.cpp | 2 +- src/PYTHON/fix_python_move.cpp | 4 +-- src/PYTHON/pair_python.cpp | 4 +-- src/PYTHON/python_compat.h | 21 +++------------ src/PYTHON/python_impl.cpp | 8 +++--- 10 files changed, 29 insertions(+), 52 deletions(-) delete mode 100644 lib/python/Makefile.lammps.python2 rename lib/python/{Makefile.lammps.python2.7 => Makefile.lammps.python3.13} (100%) diff --git a/lib/python/Makefile.lammps.python2 b/lib/python/Makefile.lammps.python2 deleted file mode 100644 index 7b54b4c3df..0000000000 --- a/lib/python/Makefile.lammps.python2 +++ /dev/null @@ -1,7 +0,0 @@ -# Settings that the LAMMPS build will import when this package library is used -# See the README file for more explanation - -python_SYSINC = $(shell which python2-config > /dev/null 2>&1 && python2-config --includes || (which python-config > /dev/null 2>&1 && python-config --includes || :)) -python_SYSLIB = $(shell which python2-config > /dev/null 2>&1 && python2-config --ldflags || (which python-config > /dev/null 2>&1 && python-config --ldflags || :)) -python_SYSPATH = -PYTHON=$(shell which python2 > /dev/null 2>&1 && echo python2 || echo python) diff --git a/lib/python/Makefile.lammps.python2.7 b/lib/python/Makefile.lammps.python3.13 similarity index 100% rename from lib/python/Makefile.lammps.python2.7 rename to lib/python/Makefile.lammps.python3.13 diff --git a/lib/python/README b/lib/python/README index 8de2bc4bd7..c84b291f05 100644 --- a/lib/python/README +++ b/lib/python/README @@ -9,30 +9,29 @@ installation. If needed, you can copy one of the other provided Makefile.lammps.* files to to Makefile.lammps before building LAMMPS itself. -The files Makefile.lammps.python2 and Makefile.lammps.python3 are -similar to the default file, but meant for the case that both, -python 2 and python 3, are installed simultaneously and you want -to prefer one over the other. If neither of these files work, you -may have to create a custom Makefile.lammps file suitable for -the version of Python on your system. To illustrate, these are -example settings from the Makefile.lammps.python2.7 file: +The file Makefile.lammps.python3 is similar to the default file, but +meant for the case that both, python 2 and python 3, are installed +simultaneously. LAMMPS only supports python 3. If neither of these +files work, you may have to create a custom Makefile.lammps file +suitable for the version of Python on your system. To illustrate, these +are example settings from the Makefile.lammps.python3.13 file: -python_SYSINC = -I/usr/local/include/python2.7 -python_SYSLIB = -lpython2.7 -lnsl -ldl -lreadline -ltermcap -lpthread -lutil -lm -python_SYSPATH = -PYTHON=python2.7 +python_SYSINC = -I/usr/local/include/python3.13 +python_SYSLIB = -lpython3.13 -ldl -lm +python_SYSPATH = -L/usr/lib64 +PYTHON=python3.13 python_SYSINC refers to the directory where Python's Python.h file is found. LAMMPS includes this file. python_SYSLIB refers to the libraries needed to link to from an application (LAMMPS in this case) to "embed" Python in the -application. The Python library itself is listed (-lpython2.7) are +application. The Python library itself is listed (-lpython3.13) are are several system libraries needed by Python. python_SYSPATH refers to the path (e.g. -L/usr/local/lib) where the Python library can be found. You may not need this setting if the -path is already included in your LD_LIBRARY_PATH environment variable. +path is already included in your LIBRARY_PATH environment variable. PYTHON is the name of the python interpreter. It is used for installing the LAMMPS python module with "make install-python" @@ -45,7 +44,7 @@ run in embedded mode on your machine. Here is what this Python doc page says about it: -https://docs.python.org/2/extending/embedding.html#compiling-and-linking-under-unix-like-systems +https://docs.python.org/3/extending/embedding.html#compiling-and-linking-under-unix-like-systems "It is not necessarily trivial to find the right flags to pass to your compiler (and linker) in order to embed the Python interpreter into diff --git a/src/KOKKOS/mliap_model_python_kokkos.cpp b/src/KOKKOS/mliap_model_python_kokkos.cpp index 4435a0371a..1b010cc286 100644 --- a/src/KOKKOS/mliap_model_python_kokkos.cpp +++ b/src/KOKKOS/mliap_model_python_kokkos.cpp @@ -68,12 +68,12 @@ MLIAPModelPythonKokkos::MLIAPModelPythonKokkos(LAMMPS *lmp, char *co // Recipe from lammps/src/pair_python.cpp : // add current directory to PYTHONPATH PyObject *py_path = PySys_GetObject((char *) "path"); - PyList_Append(py_path, PY_STRING_FROM_STRING(".")); + PyList_Append(py_path, PyUnicode_FromString(".")); // if LAMMPS_POTENTIALS environment variable is set, add it to PYTHONPATH as well const char *potentials_path = getenv("LAMMPS_POTENTIALS"); if (potentials_path != nullptr) { - PyList_Append(py_path, PY_STRING_FROM_STRING(potentials_path)); + PyList_Append(py_path, PyUnicode_FromString(potentials_path)); } PyGILState_Release(gstate); if (coefffilename) read_coeffs(coefffilename); diff --git a/src/ML-IAP/mliap_model_python.cpp b/src/ML-IAP/mliap_model_python.cpp index c06bbdc121..c1c534401a 100644 --- a/src/ML-IAP/mliap_model_python.cpp +++ b/src/ML-IAP/mliap_model_python.cpp @@ -62,12 +62,12 @@ MLIAPModelPython::MLIAPModelPython(LAMMPS *lmp, char *coefffilename, bool is_chi // Recipe from lammps/src/pair_python.cpp : // add current directory to PYTHONPATH PyObject *py_path = PySys_GetObject((char *) "path"); - PyList_Append(py_path, PY_STRING_FROM_STRING(".")); + PyList_Append(py_path, PyUnicode_FromString(".")); // if LAMMPS_POTENTIALS environment variable is set, add it to PYTHONPATH as well const char *potentials_path = getenv("LAMMPS_POTENTIALS"); if (potentials_path != nullptr) { - PyList_Append(py_path, PY_STRING_FROM_STRING(potentials_path)); + PyList_Append(py_path, PyUnicode_FromString(potentials_path)); } PyGILState_Release(gstate); if (coefffilename) read_coeffs(coefffilename); diff --git a/src/PYTHON/fix_python_invoke.cpp b/src/PYTHON/fix_python_invoke.cpp index 6f27831438..2485371690 100644 --- a/src/PYTHON/fix_python_invoke.cpp +++ b/src/PYTHON/fix_python_invoke.cpp @@ -70,7 +70,7 @@ FixPythonInvoke::FixPythonInvoke(LAMMPS *lmp, int narg, char **arg) : error->all(FLERR,"Could not find Python function"); } - lmpPtr = PY_VOID_POINTER(lmp); + lmpPtr = PyCapsule_New((void *)lmp, nullptr, nullptr); // nvalid = next step on which end_of_step or post_force does something // add nextvalid() to all computes that store invocation times diff --git a/src/PYTHON/fix_python_move.cpp b/src/PYTHON/fix_python_move.cpp index caa1557503..c0be31dee6 100644 --- a/src/PYTHON/fix_python_move.cpp +++ b/src/PYTHON/fix_python_move.cpp @@ -44,7 +44,7 @@ FixPythonMove::FixPythonMove(LAMMPS *lmp, int narg, char **arg) : // add current directory to PYTHONPATH PyObject *py_path = PySys_GetObject((char *)"path"); - PyList_Append(py_path, PY_STRING_FROM_STRING(".")); + PyList_Append(py_path, PyUnicode_FromString(".")); // create integrator instance @@ -73,7 +73,7 @@ FixPythonMove::FixPythonMove(LAMMPS *lmp, int narg, char **arg) : error->all(FLERR,"Could not find integrator class {} in module {}", cls_name, module_name); } - PyObject *ptr = PY_VOID_POINTER(lmp); + PyObject *ptr = PyCapsule_New((void *)lmp, nullptr, nullptr); PyObject *py_move_obj = PyObject_CallFunction(py_move_type, (char *)"O", ptr); Py_CLEAR(ptr); diff --git a/src/PYTHON/pair_python.cpp b/src/PYTHON/pair_python.cpp index 695954604c..0f7baa0104 100644 --- a/src/PYTHON/pair_python.cpp +++ b/src/PYTHON/pair_python.cpp @@ -54,14 +54,14 @@ PairPython::PairPython(LAMMPS *lmp) : Pair(lmp) { PyUtils::GIL lock; PyObject *py_path = PySys_GetObject((char *)"path"); - PyList_Append(py_path, PY_STRING_FROM_STRING(".")); + PyList_Append(py_path, PyUnicode_FromString(".")); // if LAMMPS_POTENTIALS environment variable is set, // add it to PYTHONPATH as well const char *potentials_path = getenv("LAMMPS_POTENTIALS"); if (potentials_path != nullptr) { - PyList_Append(py_path, PY_STRING_FROM_STRING(potentials_path)); + PyList_Append(py_path, PyUnicode_FromString(potentials_path)); } } diff --git a/src/PYTHON/python_compat.h b/src/PYTHON/python_compat.h index d1194056d8..88c0969a59 100644 --- a/src/PYTHON/python_compat.h +++ b/src/PYTHON/python_compat.h @@ -16,22 +16,11 @@ #include -// Wrap API changes between Python 2 and 3 using macros -#if PY_MAJOR_VERSION == 2 -#if defined(_MSC_VER) || defined(__MINGW32__) -#define PY_INT_FROM_LONG(X) PyLong_FromLongLong(X) -#define PY_INT_AS_LONG(X) PyLong_AsLongLong(X) -#define PY_LONG_FROM_STRING(X) std::stoll(X) -#else -#define PY_INT_FROM_LONG(X) PyInt_FromLong(X) -#define PY_INT_AS_LONG(X) PyInt_AsLong(X) -#define PY_LONG_FROM_STRING(X) std::stol(X) +#if PY_VERSION_HEX < 0x030600f0 +#error Python version 3.6 or later is required by LAMMPS #endif -#define PY_STRING_FROM_STRING(X) PyString_FromString(X) -#define PY_VOID_POINTER(X) PyCObject_FromVoidPtr((void *) X, nullptr) -#define PY_STRING_AS_STRING(X) PyString_AsString(X) -#elif PY_MAJOR_VERSION == 3 +// Wrap API differences between platforms using macros #if defined(_MSC_VER) || defined(__MINGW32__) #define PY_INT_FROM_LONG(X) PyLong_FromLongLong(X) #define PY_INT_AS_LONG(X) PyLong_AsLongLong(X) @@ -41,9 +30,5 @@ #define PY_INT_AS_LONG(X) PyLong_AsLong(X) #define PY_LONG_FROM_STRING(X) std::stol(X) #endif -#define PY_STRING_FROM_STRING(X) PyUnicode_FromString(X) -#define PY_VOID_POINTER(X) PyCapsule_New((void *) X, nullptr, nullptr) -#define PY_STRING_AS_STRING(X) PyUnicode_AsUTF8(X) -#endif #endif diff --git a/src/PYTHON/python_impl.cpp b/src/PYTHON/python_impl.cpp index 91e0a7abe5..e4ec8d74d8 100644 --- a/src/PYTHON/python_impl.cpp +++ b/src/PYTHON/python_impl.cpp @@ -361,12 +361,12 @@ void PythonImpl::invoke_function(int ifunc, char *result) if (!str) error->all(FLERR, "Could not evaluate Python function {} input variable: {}", pfuncs[ifunc].name, pfuncs[ifunc].svalue[i]); - pValue = PY_STRING_FROM_STRING(str); + pValue = PyUnicode_FromString(str); } else { - pValue = PY_STRING_FROM_STRING(pfuncs[ifunc].svalue[i]); + pValue = PyUnicode_FromString(pfuncs[ifunc].svalue[i]); } } else if (itype == PTR) { - pValue = PY_VOID_POINTER(lmp); + pValue = PyCapsule_New((void *)lmp, nullptr, nullptr); } else { error->all(FLERR, "Unsupported variable type: {}", itype); } @@ -397,7 +397,7 @@ void PythonImpl::invoke_function(int ifunc, char *result) auto value = fmt::format("{:.15g}", PyFloat_AsDouble(pValue)); strncpy(result, value.c_str(), Variable::VALUELENGTH - 1); } else if (otype == STRING) { - const char *pystr = PY_STRING_AS_STRING(pValue); + const char *pystr = PyUnicode_AsUTF8(pValue); if (pfuncs[ifunc].longstr) strncpy(pfuncs[ifunc].longstr, pystr, pfuncs[ifunc].length_longstr); else