From aca2eefce595a6366a4fdab7a2b0c26987adb39b Mon Sep 17 00:00:00 2001 From: Richard Berger Date: Tue, 15 Dec 2020 15:11:21 -0500 Subject: [PATCH] Transform LAMMPS Python module into package - Moves lammps.py into its own package - Imports entire module in __init__.py - Changes both how legacy and CMake build systems install - Added traditional setup.py for Python-only installation Note: the CMake install target runs setup.py build and install in a way that produces files in CMAKE_BINARY_DIR/python instead of python/build. This is to maintain out-of-source compilation support. --- cmake/CMakeLists.txt | 9 ++---- python/install.py | 54 +++++++++++++++++++---------------- python/lammps/__init__.py | 1 + python/{ => lammps}/lammps.py | 0 python/setup.py | 26 +++++++++++++++++ src/Makefile | 2 +- 6 files changed, 60 insertions(+), 32 deletions(-) create mode 100644 python/lammps/__init__.py rename python/{ => lammps}/lammps.py (100%) create mode 100644 python/setup.py diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 42e6d12ffb..854937dec8 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -661,7 +661,7 @@ if(BUILD_SHARED_LIBS) add_custom_target( install-python ${Python_EXECUTABLE} install.py -v ${LAMMPS_SOURCE_DIR}/version.h - -m ${LAMMPS_PYTHON_DIR}/lammps.py + -p ${LAMMPS_PYTHON_DIR}/lammps -l ${CMAKE_BINARY_DIR}/liblammps${CMAKE_SHARED_LIBRARY_SUFFIX} WORKING_DIRECTORY ${LAMMPS_PYTHON_DIR} COMMENT "Installing LAMMPS Python module") @@ -691,11 +691,8 @@ if(BUILD_SHARED_LIBS OR PKG_PYTHON) find_package(Python COMPONENTS Interpreter) endif() if (Python_EXECUTABLE) - execute_process(COMMAND ${Python_EXECUTABLE} - -c "import distutils.sysconfig as cg; print(cg.get_python_lib(1,0,prefix='${CMAKE_INSTALL_PREFIX}'))" - OUTPUT_VARIABLE PYTHON_DEFAULT_INSTDIR OUTPUT_STRIP_TRAILING_WHITESPACE) - set(PYTHON_INSTDIR ${PYTHON_DEFAULT_INSTDIR} CACHE PATH "Installation folder for LAMMPS Python module") - install(FILES ${LAMMPS_PYTHON_DIR}/lammps.py DESTINATION ${PYTHON_INSTDIR}) + file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/python) + install(CODE "execute_process(COMMAND ${Python_EXECUTABLE} setup.py build -b ${CMAKE_BINARY_DIR}/python install --prefix=${CMAKE_INSTALL_PREFIX} WORKING_DIRECTORY ${LAMMPS_PYTHON_DIR})") endif() endif() diff --git a/python/install.py b/python/install.py index 7f7062103a..a6b69c1ee6 100644 --- a/python/install.py +++ b/python/install.py @@ -1,42 +1,42 @@ #!/usr/bin/env python """ -Installer script to install the LAMMPS python module and the corresponding +Installer script to install the LAMMPS python package and the corresponding shared library into either the system-wide site-packages tree, or - failing that - into the corresponding user tree. Called from the 'install-python' build target in the conventional and CMake based build systems """ -# copy LAMMPS shared library and lammps.py to system dirs +# copy LAMMPS shared library and lammps package to system dirs from __future__ import print_function import sys,os,shutil from argparse import ArgumentParser parser = ArgumentParser(prog='install.py', - description='LAMMPS python module installer script') + description='LAMMPS python package installer script') -parser.add_argument("-m", "--module", required=True, - help="path to the source of the LAMMPS Python module") +parser.add_argument("-p", "--package", required=True, + help="path to the LAMMPS Python package") parser.add_argument("-l", "--lib", required=True, help="path to the compiled LAMMPS shared library") parser.add_argument("-v", "--version", required=True, help="path to the LAMMPS version.h header file") parser.add_argument("-d","--dir", - help="Legacy custom installation folder selection for module and library") + help="Legacy custom installation folder selection for package and library") args = parser.parse_args() # validate arguments and make paths absolute -if args.module: - if not os.path.exists(args.module): - print( "ERROR: LAMMPS module file %s does not exist" % args.module) +if args.package: + if not os.path.exists(args.package): + print( "ERROR: LAMMPS package %s does not exist" % args.package) parser.print_help() sys.exit(1) else: - args.module = os.path.abspath(args.module) + args.package = os.path.abspath(args.package) if args.lib: if not os.path.exists(args.lib): @@ -66,9 +66,9 @@ if args.dir: # without any special processing or additional steps to that folder if args.dir: - print("Copying LAMMPS Python module to custom folder %s" % args.dir) + print("Copying LAMMPS Python package to custom folder %s" % args.dir) try: - shutil.copyfile(args.module, os.path.join(args.dir,'lammps.py')) + shutil.copytree(args.package, os.path.join(args.dir,'lammps')) except shutil.Error: pass # fail silently @@ -81,15 +81,19 @@ if args.dir: sys.exit() # extract version string from header -fp = open(args.version,'r') -txt=fp.read().split('"')[1].split() -verstr=txt[0]+txt[1]+txt[2] -fp.close() +def get_lammps_version(header): + with open(header, 'r') as f: + line = f.readline() + start_pos = line.find('"')+1 + end_pos = line.find('"', start_pos) + return "".join(line[start_pos:end_pos].split()) -print("Installing LAMMPS Python module version %s into site-packages folder" % verstr) +verstr = get_lammps_version(args.version) -# we need to switch to the folder of the python module -os.chdir(os.path.dirname(args.module)) +print("Installing LAMMPS Python package version %s into site-packages folder" % verstr) + +# we need to switch to the folder of the python package +os.chdir(os.path.dirname(args.package)) from distutils.core import setup from distutils.sysconfig import get_python_lib @@ -103,10 +107,10 @@ try: author = "Steve Plimpton", author_email = "sjplimp@sandia.gov", url = "https://lammps.sandia.gov", - description = "LAMMPS Molecular Dynamics Python module", + description = "LAMMPS Molecular Dynamics Python package", license = "GPL", - py_modules = ["lammps"], - data_files = [(get_python_lib(), [args.lib])]) + packages=['lammps'], + data_files = [(os.path.join(get_python_lib(), 'lammps'), [args.lib])]) except: tryuser=True print ("Installation into global site-packages folder failed.\nTrying user folder %s now." % site.USER_SITE) @@ -119,9 +123,9 @@ if tryuser: author = "Steve Plimpton", author_email = "sjplimp@sandia.gov", url = "https://lammps.sandia.gov", - description = "LAMMPS Molecular Dynamics Python module", + description = "LAMMPS Molecular Dynamics Python package", license = "GPL", - py_modules = ["lammps"], - data_files = [(site.USER_SITE, [args.lib])]) + packages=['lammps'], + data_files = [(os.path.join(site.USER_SITE, 'lammps'), [args.lib])]) except: print("Installation into user site package folder failed.") diff --git a/python/lammps/__init__.py b/python/lammps/__init__.py new file mode 100644 index 0000000000..2f29663b75 --- /dev/null +++ b/python/lammps/__init__.py @@ -0,0 +1 @@ +from .lammps import * diff --git a/python/lammps.py b/python/lammps/lammps.py similarity index 100% rename from python/lammps.py rename to python/lammps/lammps.py diff --git a/python/setup.py b/python/setup.py new file mode 100644 index 0000000000..9be04138d5 --- /dev/null +++ b/python/setup.py @@ -0,0 +1,26 @@ +# this only installs the LAMMPS python package +# it assumes the LAMMPS shared library is already installed +from distutils.core import setup +import os + +LAMMPS_PYTHON_DIR = os.path.dirname(os.path.realpath(__file__)) +LAMMPS_DIR = os.path.dirname(LAMMPS_PYTHON_DIR) +LAMMPS_SOURCE_DIR = os.path.join(LAMMPS_DIR, 'src') + +def get_lammps_version(): + with open(os.path.join(LAMMPS_SOURCE_DIR, 'version.h'), 'r') as f: + line = f.readline() + start_pos = line.find('"')+1 + end_pos = line.find('"', start_pos) + return "".join(line[start_pos:end_pos].split()) + +setup( + name = "lammps", + version = get_lammps_version(), + author = "Steve Plimpton", + author_email = "sjplimp@sandia.gov", + url = "https://lammps.sandia.gov", + description = "LAMMPS Molecular Dynamics Python package", + license = "GPL", + packages=["lammps"] +) diff --git a/src/Makefile b/src/Makefile index 149dedd35b..7a5e1aa728 100644 --- a/src/Makefile +++ b/src/Makefile @@ -278,7 +278,7 @@ mpi-stubs: sinclude ../lib/python/Makefile.lammps install-python: @$(PYTHON) ../python/install.py -v ../src/version.h \ - -m ../python/lammps.py -l ../src/liblammps.so + -p ../python/lammps -l ../src/liblammps.so # Create a tarball of src dir and packages