diff --git a/bin/CMakeLists.txt b/bin/CMakeLists.txt index 5a086bfd2d2aad611d411a2c15767c5951f050af..04ab0d0fd6544b37902e922385ebe26f7cb488e9 100644 --- a/bin/CMakeLists.txt +++ b/bin/CMakeLists.txt @@ -2,6 +2,7 @@ install(PROGRAMS dune-ctest duneproject dunecontrol + dunepackaging.py dune-git-whitespace-hook rmgenerated.py setup-dunepy.py diff --git a/bin/dunepackaging.py b/bin/dunepackaging.py new file mode 100755 index 0000000000000000000000000000000000000000..ac038c4494b7a635dea3db9a9fe862f28f93c916 --- /dev/null +++ b/bin/dunepackaging.py @@ -0,0 +1,207 @@ +#!/usr/bin/env python3 + +import sys, os, io, getopt, re +import importlib, subprocess +import email.utils +import pkg_resources +from datetime import date + +from dune.common.module import Version, VersionRequirement, Description +class Data: + def __init__(self): + description = Description('dune.module') + self.name = description.name + self.version = str(description.version) + self.author_email = description.maintainer[1] + self.author = description.author or self.author_email + self.description = description.description + self.url = description.url + self.dune_dependencies = [ + (dep[0]+str(dep[1])).replace("("," ").replace(")","") + for dep in description.depends + ] + + self.install_requires = [] + try: + with open('python/setup.py.in', 'r') as setuppyinfile: + content = setuppyinfile.read() + if content.find('install_requires'): + bracket = content.split('install_requires')[1].split('[')[1].split(']')[0] + self.install_requires = [r.strip('\'"') for r in bracket.split(',')] + except FileNotFoundError: + pass + +def main(argv): + + repositories = ["gitlab", "testpypi", "pypi"] + def usage(): + return 'usage: dunepackaging.py [--upload <'+"|".join(repositories)+'> | -c | --clean | --version 1.0.DATE>]' + + try: + opts, args = getopt.getopt(argv, "hc", ["upload=", "clean", "version="]) + except getopt.GetoptError: + print(usage()) + sys.exit(2) + + sdist = True + upload = False + repository = "gitlab" + clean = False + version = None + for opt, arg in opts: + if opt == '-h': + print(usage()) + sys.exit(2) + elif opt in ("--upload"): + upload = True + if arg != '': + repository = arg + if repository not in repositories: + print("Specified repository must be one of: " + " ".join(repositories)) + sys.exit(2) + elif opt in ("-c", "--clean"): + clean = True + elif opt in ("--version"): + version = arg + + # Remove generated files + def removeFiles(): + import glob + files = ['setup.py', 'MANIFEST', 'pyproject.toml', 'dist', '_skbuild', '__pycache__'] + print("Remove generated files: " + ", ".join(files)) + remove = ['rm', '-rf'] + files + subprocess.call(remove) + + if clean: + removeFiles() + if not upload: + sys.exit(2) + + data = Data() + + # defaults + if not hasattr(data, 'dune_dependencies'): + data.dune_dependencies = [] + + if not hasattr(data, 'install_requires'): + data.install_requires = [] + + # if no version parameter specified, append DATE to version number in package.py + if version is None: + if not hasattr(data, 'version'): + print("No version number specified!") + sys.exit(2) + version = data.version + '.devDATE' + + # version - replacing "DATE" with yearmonthday string + t = date.today() + today = t.strftime('%Y%m%d') + data.version = version.replace("DATE",today) + + # Generate setup.py + print("Generate setup.py") + setuppy = '''\ +import sys, os +from setuptools import find_packages +from skbuild import setup + +with open("README.md", "r") as fh: + long_description = fh.read() +''' + setuppy += ''' +setup( +''' + setuppy += ' name="'+data.name+'",\n' + setuppy += ' version="'+data.version+'",\n' + setuppy += ' author="'+data.author+'",\n' + setuppy += ' author_email="'+data.author_email+'",\n' + setuppy += ' description="'+data.description+'",\n' + setuppy += ' long_description=long_description,\n' + setuppy += ' long_description_content_type="text/markdown",\n' + if data.url is not None: + setuppy += ' url="'+data.url+'",\n' + setuppy += ' packages=find_packages(where="python"),\n' + setuppy += ' package_dir={"": "python"},\n' + setuppy += ' install_requires='+(data.install_requires+data.dune_dependencies).__str__()+',' + setuppy += ''' + classifiers=[ + "Programming Language :: C++", + "Programming Language :: Python :: 3", + "License :: OSI Approved :: GNU General Public License (GPL)", + ], + python_requires='>=3.4', + cmake_args=[ + '-DBUILD_SHARED_LIBS=TRUE', + '-DDUNE_ENABLE_PYTHONBINDINGS=TRUE', + '-DDUNE_PYTHON_INSTALL_LOCATION=none', + '-DDUNE_GRID_GRIDTYPE_SELECTOR=ON', + '-DALLOW_CXXFLAGS_OVERWRITE=ON', + '-DUSE_PTHREADS=ON', + '-DCMAKE_BUILD_TYPE=Release', + '-DCMAKE_DISABLE_FIND_PACKAGE_LATEX=TRUE', + '-DCMAKE_DISABLE_DOCUMENTATION=TRUE', + '-DINKSCAPE=FALSE', + '-DCMAKE_INSTALL_RPATH='+sys.prefix+'/lib/', + '-DCMAKE_MACOSX_RPATH=TRUE', + ] +) +''' + f = open("setup.py", "w") + f.write(setuppy) + f.close() + + # Generate pyproject.toml + print("Generate pyproject.toml") + f = open("pyproject.toml", "w") + requires = ["setuptools", "wheel", "scikit-build", "cmake", "ninja"] + requires += data.dune_dependencies + f.write("[build-system]\n") + f.write("requires = "+requires.__str__()+"\n") + f.write("build-backend = 'setuptools.build_meta'\n") + f.close() + + # Generate MANIFEST + with open('MANIFEST', 'wb') as manifest_file: + manifest_file.write("setup.py\n".encode()) + manifest_file.write("pyproject.toml\n".encode()) + manifest_file.write( + subprocess.check_output(['git', 'ls-files']) + ) + + # Create source distribution + python = sys.executable + if sdist: + print("Remove dist") + remove = ['rm', '-rf', 'dist'] + subprocess.call(remove) + + # check if we have scikit-build + import pkg_resources + installed = {pkg.key for pkg in pkg_resources.working_set} + if not 'scikit-build' in installed: + print("Please install the pip package 'scikit-build' to build the source distribution.") + sys.exit(2) + + print("Create source distribution") + build = [python, 'setup.py', 'sdist'] + subprocess.call(build, stdout=subprocess.DEVNULL) + + # Upload to repository + if upload: + # check if we have twine + import pkg_resources + installed = {pkg.key for pkg in pkg_resources.working_set} + if not 'twine' in installed: + print("Please install the pip package 'twine' to upload the source distribution.") + sys.exit(2) + + twine = [python, '-m', 'twine', 'upload'] + twine += ['--repository', repository] + twine += ['dist/*'] + subprocess.call(twine) + + removeFiles() + + +if __name__ == "__main__": + main(sys.argv[1:]) diff --git a/dune-common.pc.in b/dune-common.pc.in index 5965364236baa4a5bc05d5a7a0a15c0b69f62cf4..d78094be3c36a05d3809dda5283774503a429ec5 100644 --- a/dune-common.pc.in +++ b/dune-common.pc.in @@ -8,8 +8,8 @@ DEPENDENCIES=@REQUIRES@ Name: @PACKAGE_NAME@ Version: @VERSION@ -Description: Dune (Distributed and Unified Numerics Environment) common module -URL: http://dune-project.org/ +Description: @DESCRIPTION@ +URL: @URL@ Requires: ${DEPENDENCIES} Libs: -L${libdir} -ldunecommon Cflags: -I${includedir} diff --git a/dune.module b/dune.module index f3123c523ae793361f029feba369e7ec2ae2dcdd..e5e93cdb608fa74da1141b6ad749d196bcf89c34 100644 --- a/dune.module +++ b/dune.module @@ -1,4 +1,7 @@ Module: dune-common Version: 2.8-git +Author: The Dune Core developers Maintainer: dune-devel@lists.dune-project.org +Description: Basis infrastructure for all Dune modules +URL: https://gitlab.dune-project.org/core/dune-common Whitespace-Hook: Yes diff --git a/pyproject.toml b/pyproject.toml deleted file mode 100644 index c7e614dd0b6af764bbf6eb57b125b00269216068..0000000000000000000000000000000000000000 --- a/pyproject.toml +++ /dev/null @@ -1,3 +0,0 @@ -[build-system] -requires = ["setuptools", "wheel", "scikit-build", "cmake"] -build-backend = "setuptools.build_meta" diff --git a/python/dune/common/module.py b/python/dune/common/module.py index 8ea0730dc83c1f12ec6af0822ac99c96c170534b..7dfce77beab7e1d5a59f6843bdbebfbe9fcdac59 100644 --- a/python/dune/common/module.py +++ b/python/dune/common/module.py @@ -144,6 +144,21 @@ class Description: except KeyError: self.maintainer = None + try: + self.author = data['author'] + except KeyError: + self.author = None + + try: + self.description = data['description'] + except KeyError: + self.description = '' + + try: + self.url = data['url'] + except KeyError: + self.url = None + try: wshook = data['whitespace-hook'].lower() if wshook == 'yes': @@ -180,6 +195,12 @@ class Description: s += 'Version: ' + str(self.version) + '\n' if self.maintainer is not None: s += 'Maintainer: ' + email.utils.formataddr(self.maintainer) + '\n' + if self.author is not None: + s += 'Author: ' + self.author + '\n' + if self.description is not '': + s += 'Description: ' + self.description + '\n' + if self.url is not None: + s += 'URL: ' + self.url + '\n' if self.whitespace_hook is not None: s += 'Whitespace-Hook: ' + ('Yes' if self.whitespace_hook else 'No') + '\n' diff --git a/python/setup.py.in b/python/setup.py.in index e52ec0c261d4f644687a3922fd73777020a7c20b..6d5d6f1e6e6eaec3b458795db9c4f3782c17c2c3 100644 --- a/python/setup.py.in +++ b/python/setup.py.in @@ -1,6 +1,6 @@ from setuptools import setup, find_packages -setup(name="dune.common", +setup(name="dune-common", namespace_packages=['dune'], description="Python lib for dune", version="${DUNE_COMMON_VERSION}", diff --git a/setup.py b/setup.py deleted file mode 100644 index c2dfb392b60f1f422671357f62b7e0b55c178166..0000000000000000000000000000000000000000 --- a/setup.py +++ /dev/null @@ -1,36 +0,0 @@ -import sys, os -from setuptools import find_packages - -try: - from skbuild import setup -except ImportError: - print('Please update pip, you need pip 10 or greater,\n' - ' or you need to install the PEP 518 requirements in pyproject.toml yourself', file=sys.stderr) - raise - -with open("README.md", "r") as fh: - long_description = fh.read() - -setup( - name="dune-common", - version="2.8.20201123", - author="The Dune Core developers", - author_email="dune@lists.dune-project.org", - description="""Basis infrastructure classes for all Dune modules""", - long_description=long_description, - long_description_content_type="text/markdown", - url="https://gitlab.dune-project.org/core/dune-common", - packages=find_packages(where="python"), - package_dir={"": "python"}, - install_requires=['numpy', 'mpi4py'], - cmake_args=['-DBUILD_SHARED_LIBS=TRUE', - '-DDUNE_ENABLE_PYTHONBINDINGS=TRUE', - '-DDUNE_PYTHON_INSTALL_LOCATION=none', - '-DDUNE_GRID_GRIDTYPE_SELECTOR=ON', - '-DALLOW_CXXFLAGS_OVERWRITE=ON', - '-DUSE_PTHREADS=ON', - '-DCMAKE_BUILD_TYPE=Release', - '-DCMAKE_DISABLE_FIND_PACKAGE_LATEX=TRUE', - '-DCMAKE_DISABLE_DOCUMENTATION=TRUE', - '-DCMAKE_INSTALL_RPATH='+sys.prefix+'/lib/'] -)