From 757270eb1dac65fa427096ac24e54d3799be59f6 Mon Sep 17 00:00:00 2001 From: ye11owSub Date: Thu, 8 Aug 2024 02:21:19 +0300 Subject: [PATCH] format of setup.py --- setup.py | 397 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 224 insertions(+), 173 deletions(-) diff --git a/setup.py b/setup.py index e85e20506..c88b725f9 100644 --- a/setup.py +++ b/setup.py @@ -8,28 +8,27 @@ import argparse import glob -import os import io as cStringIO +import os import pathlib import re +import shutil import sys import sysconfig -import shutil import time from collections import defaultdict from subprocess import PIPE, Popen -from setuptools import setup, Extension +import numpy +from setuptools import Extension, setup from setuptools.command.build_ext import build_ext from setuptools.command.build_py import build_py from setuptools.command.install import install -import numpy - # non-empty DEBUG variable turns off optimization and adds -g flag -DEBUG = bool(os.getenv('DEBUG', '')) -WIN = sys.platform.startswith('win') -MAC = sys.platform.startswith('darwin') +DEBUG = bool(os.getenv("DEBUG", "")) +WIN = sys.platform.startswith("win") +MAC = sys.platform.startswith("darwin") # Have to copy from "create_shadertext.py" script due to the use of pyproject.toml @@ -181,118 +180,140 @@ def str2bool(v: str) -> bool: elif v.lower() == "false": return False else: - raise argparse.ArgumentTypeError('Boolean value expected.') + raise argparse.ArgumentTypeError("Boolean value expected.") + class options: osx_frameworks = True - jobs = int(os.getenv('JOBS', 0)) + jobs = int(os.getenv("JOBS", 0)) no_libxml = False no_glut = True - use_msgpackc = 'guess' + use_msgpackc = "guess" testing = False openvr = False - use_openmp = 'no' if MAC else 'yes' - use_vtkm = 'no' + use_openmp = "no" if MAC else "yes" + use_vtkm = "no" vmd_plugins = True parser = argparse.ArgumentParser() -parser.add_argument('--glut', dest='no_glut', type=str2bool, - help="link with GLUT (legacy GUI)") -parser.add_argument('--no-osx-frameworks', dest='osx_frameworks', - help="on MacOS use XQuartz instead of native frameworks", - type=str2bool) -parser.add_argument('--jobs', '-j', type=int, help="for parallel builds " - "(defaults to number of processors)") -parser.add_argument('--no-libxml', type=str2bool, - help="skip libxml2 dependency, disables COLLADA export") -parser.add_argument('--use-openmp', choices=('yes', 'no'), - help="Use OpenMP") -parser.add_argument('--use-vtkm', choices=('1.5', '1.6', '1.7', 'no'), - help="Use VTK-m for isosurface generation") -parser.add_argument('--use-msgpackc', choices=('c++11', 'c', 'guess', 'no'), - help="c++11: use msgpack-c header-only library; c: link against " - "shared library; no: disable fast MMTF load support") -parser.add_argument('--testing', type=str2bool, - help="Build C-level tests") -parser.add_argument('--openvr', dest='openvr', type=str2bool) -parser.add_argument('--no-vmd-plugins', dest='vmd_plugins', - type=str2bool, - help='Disable VMD molfile plugins (libnetcdf dependency)') +parser.add_argument( + "--glut", dest="no_glut", type=str2bool, help="link with GLUT (legacy GUI)" +) +parser.add_argument( + "--no-osx-frameworks", + dest="osx_frameworks", + help="on MacOS use XQuartz instead of native frameworks", + type=str2bool, +) +parser.add_argument( + "--jobs", + "-j", + type=int, + help="for parallel builds " "(defaults to number of processors)", +) +parser.add_argument( + "--no-libxml", + type=str2bool, + help="skip libxml2 dependency, disables COLLADA export", +) +parser.add_argument("--use-openmp", choices=("yes", "no"), help="Use OpenMP") +parser.add_argument( + "--use-vtkm", + choices=("1.5", "1.6", "1.7", "no"), + help="Use VTK-m for isosurface generation", +) +parser.add_argument( + "--use-msgpackc", + choices=("c++11", "c", "guess", "no"), + help="c++11: use msgpack-c header-only library; c: link against " + "shared library; no: disable fast MMTF load support", +) +parser.add_argument("--testing", type=str2bool, help="Build C-level tests") +parser.add_argument("--openvr", dest="openvr", type=str2bool) +parser.add_argument( + "--no-vmd-plugins", + dest="vmd_plugins", + type=str2bool, + help="Disable VMD molfile plugins (libnetcdf dependency)", +) options, sys.argv[1:] = parser.parse_known_args(namespace=options) def get_prefix_path() -> list[str]: - ''' + """ Return a list of paths which will be searched for "include", "include/freetype2", "lib", "lib64" etc. - ''' + """ paths = [] - if (prefix_path := os.environ.get('PREFIX_PATH')) is not None: + if (prefix_path := os.environ.get("PREFIX_PATH")) is not None: paths += prefix_path.split(os.pathsep) - if sys.platform.startswith('freebsd'): - paths += ['/usr/local'] + if sys.platform.startswith("freebsd"): + paths += ["/usr/local"] if not options.osx_frameworks: - paths += ['usr/X11'] + paths += ["usr/X11"] if MAC: - for prefix in ['/sw', '/opt/local', '/usr/local']: + for prefix in ["/sw", "/opt/local", "/usr/local"]: if sys.base_prefix.startswith(prefix): paths += [prefix] if is_conda_env(): if WIN: - if 'CONDA_PREFIX' in os.environ: - paths += [os.path.join(os.environ['CONDA_PREFIX'], 'Library')] - paths += [os.path.join(sys.prefix, 'Library')] + if "CONDA_PREFIX" in os.environ: + paths += [os.path.join(os.environ["CONDA_PREFIX"], "Library")] + paths += [os.path.join(sys.prefix, "Library")] paths += [sys.prefix] + paths - paths += ['/usr'] + paths += ["/usr"] return paths def is_conda_env(): return ( - 'conda' in sys.prefix or - 'conda' in sys.version or - 'Continuum' in sys.version or - sys.prefix == os.getenv('CONDA_PREFIX')) + "conda" in sys.prefix + or "conda" in sys.version + or "Continuum" in sys.version + or sys.prefix == os.getenv("CONDA_PREFIX") + ) def guess_msgpackc(): for prefix in prefix_path: - for suffix in ['h', 'hpp']: - f = os.path.join(prefix, 'include', 'msgpack', f'version_master.{suffix}') + for suffix in ["h", "hpp"]: + f = os.path.join(prefix, "include", "msgpack", f"version_master.{suffix}") try: - m = re.search(r'MSGPACK_VERSION_MAJOR\s+(\d+)', open(f).read()) + m = re.search(r"MSGPACK_VERSION_MAJOR\s+(\d+)", open(f).read()) except EnvironmentError: continue if m is not None: major = int(m.group(1)) if major > 1: - return 'c++11' + return "c++11" - return 'no' + return "no" class CMakeExtension(Extension): - def __init__(self, - name, - sources, - include_dirs=[], - libraries=[], - library_dirs=[], - define_macros=[], - extra_link_args=[], - extra_compile_args=[]): + def __init__( + self, + name, + sources, + include_dirs=[], + libraries=[], + library_dirs=[], + define_macros=[], + extra_link_args=[], + extra_compile_args=[], + ): # don't invoke the original build_ext for this special extension super().__init__(name, sources=[]) self.sources = sources @@ -319,7 +340,7 @@ def build_cmake(self, ext): # these dirs will be created in build_py, so if you don't have # any python sources to bundle, the dirs will be missing - name_split = ext.name.split('.') + name_split = ext.name.split(".") target_name = name_split[-1] build_temp = pathlib.Path(self.build_temp) / target_name build_temp.mkdir(parents=True, exist_ok=True) @@ -329,22 +350,22 @@ def build_cmake(self, ext): extdir.parent.mkdir(parents=True, exist_ok=True) def concat_paths(paths): - return ''.join(path.replace('\\', '/') + ";" for path in paths) + return "".join(path.replace("\\", "/") + ";" for path in paths) - config = 'Debug' if DEBUG else 'Release' + config = "Debug" if DEBUG else "Release" lib_output_dir = str(extdir.parent.absolute()) all_files = ext.sources all_src = concat_paths(all_files) - all_defs = ''.join(mac[0] + ";" for mac in ext.define_macros) - all_libs = ''.join(f"{lib};" for lib in ext.libraries) - all_ext_link = ' '.join(ext.extra_link_args) - all_comp_args = ''.join(f"{arg};" for arg in ext.extra_compile_args) + all_defs = "".join(mac[0] + ";" for mac in ext.define_macros) + all_libs = "".join(f"{lib};" for lib in ext.libraries) + all_ext_link = " ".join(ext.extra_link_args) + all_comp_args = "".join(f"{arg};" for arg in ext.extra_compile_args) all_lib_dirs = concat_paths(ext.library_dirs) all_inc_dirs = concat_paths(ext.include_dirs) lib_mode = "RUNTIME" if WIN else "LIBRARY" - shared_suffix = sysconfig.get_config_var('EXT_SUFFIX') + shared_suffix = sysconfig.get_config_var("EXT_SUFFIX") cmake_args = [ f"-DTARGET_NAME={target_name}", @@ -357,23 +378,25 @@ def concat_paths(paths): f"-DALL_LIB={all_libs}", f"-DALL_COMP_ARGS={all_comp_args}", f"-DALL_EXT_LINK={all_ext_link}", - f"-DSHARED_SUFFIX={shared_suffix}" + f"-DSHARED_SUFFIX={shared_suffix}", ] # example of build args - build_args = ['--config', config] + build_args = ["--config", config] if not WIN: # Win /MP flag on compilation level cpu_count = os.cpu_count() or 1 - build_args += [f'-j{cpu_count}'] + build_args += [f"-j{cpu_count}"] os.chdir(str(build_temp)) - self.spawn(['cmake', str(cwd)] + cmake_args) + self.spawn(["cmake", str(cwd)] + cmake_args) if not self.dry_run: - self.spawn(['cmake', '--build', '.'] + build_args) + self.spawn(["cmake", "--build", "."] + build_args) if WIN: # Move up from VS release folder - cmake_lib_loc = pathlib.Path(lib_output_dir, "Release", f"{target_name}{shared_suffix}") + cmake_lib_loc = pathlib.Path( + lib_output_dir, "Release", f"{target_name}{shared_suffix}" + ) if cmake_lib_loc.exists(): shutil.move(cmake_lib_loc, extdirabs) @@ -393,9 +416,9 @@ class install_pymol(install): no_launcher = False user_options = install.user_options + [ - ('pymol-path=', None, 'PYMOL_PATH'), - ('bundled-pmw', None, 'install bundled Pmw module'), - ('no-launcher', None, 'skip installation of the pymol launcher'), + ("pymol-path=", None, "PYMOL_PATH"), + ("bundled-pmw", None, "install bundled Pmw module"), + ("no-launcher", None, "skip installation of the pymol launcher"), ] def finalize_options(self): @@ -404,11 +427,9 @@ def finalize_options(self): self.pymol_path_is_default = self.pymol_path is None if self.pymol_path is None: - self.pymol_path = os.path.join( - self.install_libbase, 'pymol', 'pymol_path') + self.pymol_path = os.path.join(self.install_libbase, "pymol", "pymol_path") elif self.root is not None: - self.pymol_path = install_pymol.change_root( - self.root, self.pymol_path) + self.pymol_path = install_pymol.change_root(self.root, self.pymol_path) def run(self): super().run() @@ -418,20 +439,23 @@ def run(self): self.make_launch_script() if self.bundled_pmw: - raise Exception('--bundled-pmw has been removed, please install Pmw from ' - 'https://github.com/schrodinger/pmw-patched') + raise Exception( + "--bundled-pmw has been removed, please install Pmw from " + "https://github.com/schrodinger/pmw-patched" + ) def unchroot(self, name): if self.root is not None and name.startswith(self.root): - return name[len(self.root):] + return name[len(self.root) :] return name def copy_tree_nosvn(self, src, dst): - def ignore(src, names): return set([ - ]).intersection(names) + def ignore(src, names): + return set([]).intersection(names) + if os.path.exists(dst): shutil.rmtree(dst) - print('copying %s -> %s' % (src, dst)) + print("copying %s -> %s" % (src, dst)) shutil.copytree(src, dst, ignore=ignore) def copy(self, src, dst): @@ -440,54 +464,63 @@ def copy(self, src, dst): def install_pymol_path(self): self.mkpath(self.pymol_path) - for name in ['LICENSE', 'data', 'test', 'examples', ]: + for name in [ + "LICENSE", + "data", + "test", + "examples", + ]: self.copy(name, os.path.join(self.pymol_path, name)) if options.openvr: - self.copy('contrib/vr/README.md', - os.path.join(self.pymol_path, 'README-VR.txt')) + self.copy( + "contrib/vr/README.md", os.path.join(self.pymol_path, "README-VR.txt") + ) def make_launch_script(self): - if sys.platform.startswith('win'): - launch_script = 'pymol.bat' + if sys.platform.startswith("win"): + launch_script = "pymol.bat" else: - launch_script = 'pymol' + launch_script = "pymol" self.mkpath(self.install_scripts) launch_script = os.path.join(self.install_scripts, launch_script) python_exe = os.path.abspath(sys.executable) - pymol_file = self.unchroot(os.path.join( - self.install_libbase, 'pymol', '__init__.py')) + pymol_file = self.unchroot( + os.path.join(self.install_libbase, "pymol", "__init__.py") + ) pymol_path = self.unchroot(self.pymol_path) - with open(launch_script, 'w') as out: + with open(launch_script, "w") as out: if WIN: # paths relative to launcher, if possible try: - python_exe = '%~dp0\\' + \ - os.path.relpath(python_exe, self.install_scripts) + python_exe = "%~dp0\\" + os.path.relpath( + python_exe, self.install_scripts + ) except ValueError: pass try: - pymol_file = '%~dp0\\' + \ - os.path.relpath(pymol_file, self.install_scripts) + pymol_file = "%~dp0\\" + os.path.relpath( + pymol_file, self.install_scripts + ) except ValueError: pymol_file = os.path.abspath(pymol_file) if not self.pymol_path_is_default: - out.write(f'set PYMOL_PATH={pymol_path}' + os.linesep) + out.write(f"set PYMOL_PATH={pymol_path}" + os.linesep) out.write('"%s" "%s"' % (python_exe, pymol_file)) - out.write(' %*' + os.linesep) + out.write(" %*" + os.linesep) else: - out.write('#!/bin/sh' + os.linesep) + out.write("#!/bin/sh" + os.linesep) if not self.pymol_path_is_default: out.write(f'export PYMOL_PATH="{pymol_path}"' + os.linesep) - out.write('exec "%s" "%s" "$@"' % - (python_exe, pymol_file) + os.linesep) + out.write('exec "%s" "%s" "$@"' % (python_exe, pymol_file) + os.linesep) os.chmod(launch_script, 0o755) + # ============================================================================ @@ -528,22 +561,26 @@ def make_launch_script(self): libs = ["png", "freetype"] lib_dirs = [] -ext_comp_args = [ - "-Werror=return-type", - "-Wunused-variable", - "-Wno-switch", - "-Wno-narrowing", - # legacy stuff - '-Wno-char-subscripts', - # optimizations - "-Og" if DEBUG else "-O3", -] if not WIN else ["/MP"] +ext_comp_args = ( + [ + "-Werror=return-type", + "-Wunused-variable", + "-Wno-switch", + "-Wno-narrowing", + # legacy stuff + "-Wno-char-subscripts", + # optimizations + "-Og" if DEBUG else "-O3", + ] + if not WIN + else ["/MP"] +) ext_link_args = [] ext_objects = [] data_files = [] ext_modules = [] -if options.use_openmp == 'yes': +if options.use_openmp == "yes": def_macros += [ ("PYMOL_OPENMP", None), ] @@ -559,10 +596,10 @@ def make_launch_script(self): if options.vmd_plugins: # VMD plugin support inc_dirs += [ - 'contrib/uiuc/plugins/include', + "contrib/uiuc/plugins/include", ] pymol_src_dirs += [ - 'contrib/uiuc/plugins/molfile_plugin/src', + "contrib/uiuc/plugins/molfile_plugin/src", ] def_macros += [ ("_PYMOL_VMD_PLUGINS", None), @@ -570,24 +607,22 @@ def make_launch_script(self): if not options.no_libxml: # COLLADA support - def_macros += [ - ("_HAVE_LIBXML", None) - ] + def_macros += [("_HAVE_LIBXML", None)] libs += ["xml2"] -if options.use_msgpackc == 'guess': +if options.use_msgpackc == "guess": options.use_msgpackc = guess_msgpackc() -if options.use_msgpackc == 'no': +if options.use_msgpackc == "no": def_macros += [("_PYMOL_NO_MSGPACKC", None)] else: - if options.use_msgpackc == 'c++11': + if options.use_msgpackc == "c++11": def_macros += [ ("MMTF_MSGPACK_USE_CPP11", None), ("MSGPACK_NO_BOOST", None), ] else: - libs += ['msgpackc'] + libs += ["msgpackc"] pymol_src_dirs += ["contrib/mmtf-c"] @@ -639,22 +674,28 @@ def make_launch_script(self): libs += [ "Advapi32", # Registry (RegCloseKey etc.) - "Ws2_32", # htonl + "Ws2_32", # htonl ] - libs += [ - "glew32", - "freetype", - "libpng", - ] + (not options.no_glut) * [ - "freeglut", - ] + (not options.no_libxml) * [ - "libxml2", - ] + libs += ( + [ + "glew32", + "freetype", + "libpng", + ] + + (not options.no_glut) + * [ + "freeglut", + ] + + (not options.no_libxml) + * [ + "libxml2", + ] + ) if DEBUG: - ext_comp_args += ['/Z7'] - ext_link_args += ['/DEBUG'] + ext_comp_args += ["/Z7"] + ext_link_args += ["/DEBUG"] libs += [ "opengl32", @@ -672,13 +713,13 @@ def make_launch_script(self): if options.use_vtkm != "no": for prefix in prefix_path: - vtkm_inc_dir = os.path.join( - prefix, "include", f"vtkm-{options.use_vtkm}") + vtkm_inc_dir = os.path.join(prefix, "include", f"vtkm-{options.use_vtkm}") if os.path.exists(vtkm_inc_dir): break else: - raise LookupError('VTK-m headers not found.' - f' PREFIX_PATH={":".join(prefix_path)}') + raise LookupError( + "VTK-m headers not found." f' PREFIX_PATH={":".join(prefix_path)}' + ) def_macros += [ ("_PYMOL_VTKM", None), ] @@ -692,8 +733,11 @@ def make_launch_script(self): ] libs += [ f"vtkm_cont-{options.use_vtkm}", - f"vtkm_filter-{options.use_vtkm}" if options.use_vtkm == "1.5" else - f"vtkm_filter_contour-{options.use_vtkm}", + ( + f"vtkm_filter-{options.use_vtkm}" + if options.use_vtkm == "1.5" + else f"vtkm_filter_contour-{options.use_vtkm}" + ), ] if options.vmd_plugins: @@ -715,12 +759,18 @@ def make_launch_script(self): for prefix in prefix_path: for dirs, suffixes in [ - [inc_dirs, [("include",), ("include", "freetype2"), - ("include", "libxml2"), ("include", "openvr")]], - [lib_dirs, [("lib64",), ("lib",)]], + [ + inc_dirs, + [ + ("include",), + ("include", "freetype2"), + ("include", "libxml2"), + ("include", "openvr"), + ], + ], + [lib_dirs, [("lib64",), ("lib",)]], ]: - dirs.extend( - filter(os.path.isdir, [os.path.join(prefix, *s) for s in suffixes])) + dirs.extend(filter(os.path.isdir, [os.path.join(prefix, *s) for s in suffixes])) # optimization currently causes a clang segfault on OS X 10.9 when # compiling layer2/RepCylBond.cpp @@ -729,40 +779,43 @@ def make_launch_script(self): def get_pymol_version(): - return re.findall(r'_PyMOL_VERSION "(.*)"', open('layer0/Version.h').read())[0] + return re.findall(r'_PyMOL_VERSION "(.*)"', open("layer0/Version.h").read())[0] -def get_sources(subdirs, suffixes=('.c', '.cpp')): - return sorted([f for d in subdirs for s in suffixes for f in glob.glob(d + '/*' + s)]) +def get_sources(subdirs, suffixes=(".c", ".cpp")): + return sorted( + [f for d in subdirs for s in suffixes for f in glob.glob(d + "/*" + s)] + ) + +def get_packages(base, parent="", r=None): + from os.path import exists, join -def get_packages(base, parent='', r=None): - from os.path import join, exists if r is None: r = [] if parent: r.append(parent) for name in os.listdir(join(base, parent)): - if '.' not in name and exists(join(base, parent, name, '__init__.py')): + if "." not in name and exists(join(base, parent, name, "__init__.py")): get_packages(base, join(parent, name), r) return r -package_dir = dict((x, os.path.join(base, x)) - for base in ['modules'] - for x in get_packages(base)) +package_dir = dict( + (x, os.path.join(base, x)) for base in ["modules"] for x in get_packages(base) +) # Python includes -inc_dirs.append(sysconfig.get_paths()['include']) -inc_dirs.append(sysconfig.get_paths()['platinclude']) +inc_dirs.append(sysconfig.get_paths()["include"]) +inc_dirs.append(sysconfig.get_paths()["platinclude"]) -champ_inc_dirs = ['contrib/champ'] -champ_inc_dirs.append(sysconfig.get_paths()['include']) -champ_inc_dirs.append(sysconfig.get_paths()['platinclude']) +champ_inc_dirs = ["contrib/champ"] +champ_inc_dirs.append(sysconfig.get_paths()["include"]) +champ_inc_dirs.append(sysconfig.get_paths()["platinclude"]) if WIN: # pyconfig.py forces linking against pythonXY.lib on MSVC - py_lib = pathlib.Path(sysconfig.get_paths()['stdlib']).parent / 'libs' + py_lib = pathlib.Path(sysconfig.get_paths()["stdlib"]).parent / "libs" lib_dirs.append(str(py_lib)) ext_modules += [ @@ -776,10 +829,9 @@ def get_packages(base, parent='', r=None): extra_link_args=ext_link_args, extra_compile_args=ext_comp_args, ), - CMakeExtension( name="chempy.champ._champ", - sources=get_sources(['contrib/champ']), + sources=get_sources(["contrib/champ"]), include_dirs=champ_inc_dirs, library_dirs=lib_dirs, ), @@ -787,11 +839,10 @@ def get_packages(base, parent='', r=None): setup( cmdclass={ - 'build_ext': build_ext_pymol, - 'build_py': build_py_pymol, - 'install': install_pymol, + "build_ext": build_ext_pymol, + "build_py": build_py_pymol, + "install": install_pymol, }, version=get_pymol_version(), ext_modules=ext_modules, ) -