From 598b2cf65ba2507dfdfa9fc2361d547f3664c64d Mon Sep 17 00:00:00 2001 From: Ben Greiner Date: Sat, 9 Jul 2022 14:21:42 +0200 Subject: [PATCH 1/5] use setuptools_scm --- .coveragerc | 1 - CMakeLists.txt | 3 +- MANIFEST.in | 1 - conda-recipe/meta.yaml | 4 +- pyproject.toml | 7 ++ setup.cfg.in | 10 --- setup.py | 152 +++-------------------------------------- slycot/CMakeLists.txt | 4 +- slycot/__init__.py | 7 +- slycot/version.py.in | 10 --- 10 files changed, 25 insertions(+), 174 deletions(-) delete mode 100644 setup.cfg.in delete mode 100644 slycot/version.py.in diff --git a/.coveragerc b/.coveragerc index 7f5d53d6..97122d29 100644 --- a/.coveragerc +++ b/.coveragerc @@ -2,7 +2,6 @@ source = slycot omit = */tests/* - */version.py # please do not add any sections after this block diff --git a/CMakeLists.txt b/CMakeLists.txt index b018ff83..8ebbcd69 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ if (CMAKE_VERSION VERSION_GREATER "3.11.99") cmake_policy(SET CMP0074 NEW) endif() -project(slycot VERSION ${SLYCOT_VERSION} LANGUAGES NONE) +project(slycot LANGUAGES NONE) enable_language(C) enable_language(Fortran) @@ -22,6 +22,5 @@ message(STATUS "NumPy included from: ${NumPy_INCLUDE_DIR}") message(STATUS "F2PY included from: ${F2PY_INCLUDE_DIR}") message(STATUS "LAPACK: ${LAPACK_LIBRARIES}") message(STATUS "BLAS: ${BLAS_LIBRARIES}") -message(STATUS "Slycot version: ${SLYCOT_VERSION}") add_subdirectory(slycot) diff --git a/MANIFEST.in b/MANIFEST.in index 8fecc477..b8c04e7c 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -9,7 +9,6 @@ include conda-recipe/* include slycot/CMakeLists.txt include slycot/tests/CMakeLists.txt include slycot/*.py -include slycot/version.py.in include slycot/src/*.f include slycot/tests/*.py graft slycot/src/SLICOT-Reference diff --git a/conda-recipe/meta.yaml b/conda-recipe/meta.yaml index b3e846db..05f59a05 100644 --- a/conda-recipe/meta.yaml +++ b/conda-recipe/meta.yaml @@ -27,14 +27,16 @@ requirements: - libcblas * *netlib - liblapack * *netlib - python - - numpy!=1.23.0 + - numpy !=1.23.0 - pip - scikit-build >=0.14.1 + - setuptools_scm >=6.3 run: - python {{ PY_VER }} - {{ pin_compatible('numpy') }} - libflang # [win] + - importlib_metadata # [py<38] test: requires: diff --git a/pyproject.toml b/pyproject.toml index e55372af..640b2115 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,8 +1,15 @@ [build-system] requires = [ "setuptools", + "setuptools_scm>=6.3", "wheel", "scikit-build>=0.14.1", "cmake", "numpy!=1.23.0"] build-backend = "setuptools.build_meta" + +[tool.setuptools_scm] + +[tool.pytest.ini_options] +# run the tests with compiled and installed package +addopts = "--pyargs slycot" diff --git a/setup.cfg.in b/setup.cfg.in deleted file mode 100644 index 6473f3df..00000000 --- a/setup.cfg.in +++ /dev/null @@ -1,10 +0,0 @@ -[metadata] - -name = slycot -version = @version@ -gitrevision = @gitrevision@ -release = @release@ - -[tool:pytest] -# run the tests with compiled and installed package -addopts = --pyargs slycot diff --git a/setup.py b/setup.py index 1f7f6707..bab8c695 100644 --- a/setup.py +++ b/setup.py @@ -12,10 +12,6 @@ import subprocess import re import platform -try: - import configparser -except ImportError: - import ConfigParser as configparser try: from skbuild import setup @@ -23,6 +19,11 @@ except ImportError: raise ImportError('scikit-build must be installed before running setup.py') +try: + from setuptools_scm import get_version +except ImportError: + raise ImportError('setuptools_scm must be installed before running setup.py') + DOCLINES = __doc__.split("\n") CLASSIFIERS = """\ @@ -46,74 +47,6 @@ Operating System :: MacOS """ -# defaults -ISRELEASED = True -# assume a version set by conda, next update with git, -# otherwise count on default -VERSION = 'Unknown' - - -class GitError(RuntimeError): - """Exception for git errors occuring in in git_version""" - pass - - -def git_version(srcdir=None): - """Return the git version, revision and cycle - - Uses rev-parse to get the revision tag to get the version number from the - latest tag and detects (approximate) revision cycles - - """ - def _minimal_ext_cmd(cmd, srcdir): - # construct minimal environment - env = {} - for k in ['SYSTEMROOT', 'PATH']: - v = os.environ.get(k) - if v is not None: - env[k] = v - # LANGUAGE is used on win32 - env['LANGUAGE'] = 'C' - env['LANG'] = 'C' - env['LC_ALL'] = 'C' - proc = subprocess.Popen( - cmd, - cwd=srcdir, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - env=env) - out, err = proc.communicate() - if proc.returncode: - errmsg = err.decode('ascii', errors='ignore').strip() - raise GitError("git err; return code %d, error message:\n '%s'" - % (proc.returncode, errmsg)) - return out - - try: - GIT_VERSION = VERSION - GIT_REVISION = 'Unknown' - GIT_CYCLE = 0 - out = _minimal_ext_cmd(['git', 'rev-parse', 'HEAD'], srcdir) - GIT_REVISION = out.strip().decode('ascii') - out = _minimal_ext_cmd(['git', 'tag'], srcdir) - GIT_VERSION = out.strip().decode('ascii').split('\n')[-1][1:] - out = _minimal_ext_cmd(['git', 'describe', '--tags', - '--long', '--always'], srcdir) - try: - # don't get a good description with shallow clones - GIT_CYCLE = out.strip().decode('ascii').split('-')[1] - except IndexError: - pass - except OSError: - pass - - return GIT_VERSION, GIT_REVISION, GIT_CYCLE - -# BEFORE importing distutils, remove MANIFEST. distutils doesn't properly -# update it when the contents of directories change. -if os.path.exists('MANIFEST'): - os.remove('MANIFEST') - # This is a bit hackish: we are setting a global variable so that the main # slycot __init__ can detect if it is being loaded by the setup routine, to # avoid attempting to load components that aren't built yet. While ugly, it's @@ -121,69 +54,6 @@ def _minimal_ext_cmd(cmd, srcdir): builtins.__SLYCOT_SETUP__ = True -def rewrite_setup_cfg(version, gitrevision, release): - toreplace = dict(locals()) - data = ''.join(open('setup.cfg.in', 'r').readlines()).split('@') - for k, v in toreplace.items(): - idx = data.index(k) - data[idx] = v - cfg = open('setup.cfg', 'w') - cfg.write(''.join(data)) - cfg.close() - - -def get_version_info(srcdir=None): - global ISRELEASED - GIT_CYCLE = 0 - - # Adding the git rev number needs to be done inside write_version_py(), - # otherwise the import of slycot.version messes up - # the build under Python 3. - if os.environ.get('CONDA_BUILD', False): - FULLVERSION = os.environ.get('PKG_VERSION', '???') - GIT_REVISION = os.environ.get('GIT_DESCRIBE_HASH', '') - ISRELEASED = True - rewrite_setup_cfg(FULLVERSION, GIT_REVISION, 'yes') - elif os.path.exists('.git'): - FULLVERSION, GIT_REVISION, GIT_CYCLE = git_version(srcdir) - ISRELEASED = (GIT_CYCLE == 0) - rewrite_setup_cfg(FULLVERSION, GIT_REVISION, - (ISRELEASED and 'yes') or 'no') - elif os.path.exists('setup.cfg'): - # valid distribution - setupcfg = configparser.ConfigParser(allow_no_value=True) - setupcfg.read('setup.cfg') - - FULLVERSION = setupcfg.get(section='metadata', option='version') - - if FULLVERSION is None: - FULLVERSION = "Unknown" - - GIT_REVISION = setupcfg.get(section='metadata', option='gitrevision') - - if GIT_REVISION is None: - GIT_REVISION = "" - - return FULLVERSION, GIT_REVISION - else: - - # try to find a version number from the dir name - dname = os.getcwd().split(os.sep)[-1] - - m = re.search(r'[0-9.]+', dname) - if m: - FULLVERSION = m.group() - GIT_REVISION = '' - - else: - FULLVERSION = VERSION - GIT_REVISION = "Unknown" - - if not ISRELEASED: - FULLVERSION += '.' + str(GIT_CYCLE) - - return FULLVERSION, GIT_REVISION - def check_submodules(): """ verify that the submodules are checked out and clean use `git submodule update --init`; on failure @@ -216,14 +86,12 @@ def setup_package(): src_path = os.path.dirname(os.path.abspath(__file__)) sys.path.insert(0, src_path) - # Rewrite the version file everytime - VERSION, gitrevision = get_version_info(src_path) metadata = dict( name='slycot', packages=['slycot', 'slycot.tests'], cmake_languages=('C', 'Fortran'), - version=VERSION, + use_scm_version=True, maintainer="Slycot developers", maintainer_email="python-control-discuss@lists.sourceforge.net", description=DOCLINES[0], @@ -234,12 +102,9 @@ def setup_package(): classifiers=[_f for _f in CLASSIFIERS.split('\n') if _f], platforms=["Windows", "Linux", "Solaris", "Mac OS-X", "Unix"], cmdclass={"sdist": sdist_checked}, - cmake_args=['-DSLYCOT_VERSION:STRING=' + VERSION, - '-DGIT_REVISION:STRING=' + gitrevision, - '-DISRELEASE:STRING=' + str(ISRELEASED), - '-DFULL_VERSION=' + VERSION + '.git' + gitrevision[:7]], zip_safe=False, - install_requires=['numpy'], + install_requires=["numpy", + "importlib-metadata; python_version < '3.8'"], python_requires=">=3.7" ) @@ -247,7 +112,6 @@ def setup_package(): setup(**metadata) finally: del sys.path[0] - return if __name__ == '__main__': diff --git a/slycot/CMakeLists.txt b/slycot/CMakeLists.txt index f656c326..a079bf98 100644 --- a/slycot/CMakeLists.txt +++ b/slycot/CMakeLists.txt @@ -630,13 +630,11 @@ set(F2PYSOURCE_DEPS src/transform.pyf src/synthesis.pyf src/_helper.pyf) -configure_file(version.py.in version.py @ONLY) - set(PYSOURCE __init__.py examples.py exceptions.py analysis.py math.py synthesis.py transform.py - ${CMAKE_CURRENT_BINARY_DIR}/version.py) +) set(SLYCOT_MODULE "_wrapper") diff --git a/slycot/__init__.py b/slycot/__init__.py index 836c8a51..53fbf4c3 100644 --- a/slycot/__init__.py +++ b/slycot/__init__.py @@ -45,8 +45,11 @@ from .transform import tf01md, tf01rd from .transform import td04ad, tb01pd - # Version information - from .version import version as __version__ + try: + from importlib.metadata import version + except ImportError: + from importlib_metadata import version + __version__ = version("slycot") def test(): diff --git a/slycot/version.py.in b/slycot/version.py.in deleted file mode 100644 index 0843bf15..00000000 --- a/slycot/version.py.in +++ /dev/null @@ -1,10 +0,0 @@ - -# THIS FILE IS GENERATED FROM SLYCOT SETUP.PY -short_version = '@SLYCOT_VERSION@' -version = '@SLYCOT_VERSION@' -full_version = '@FULL_VERSION@' -git_revision = '@GIT_REVISION@' -release = @ISRELEASE@ - -if not release: - version = full_version From c0563fb2e6d73759d5482bc9f87bf164560c3763 Mon Sep 17 00:00:00 2001 From: Ben Greiner Date: Sun, 10 Jul 2022 12:24:23 +0200 Subject: [PATCH 2/5] avoid slycot.version being the version function --- slycot/__init__.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/slycot/__init__.py b/slycot/__init__.py index 53fbf4c3..3e57bf95 100644 --- a/slycot/__init__.py +++ b/slycot/__init__.py @@ -46,10 +46,11 @@ from .transform import td04ad, tb01pd try: - from importlib.metadata import version + from importlib.metadata import version as imv except ImportError: - from importlib_metadata import version - __version__ = version("slycot") + from importlib_metadata import version as imv + __version__ = imv(__package__) + def test(): From d51cbcfd02752fd56627a7ff0f9f08db0145cf37 Mon Sep 17 00:00:00 2001 From: Ben Greiner Date: Sat, 16 Jul 2022 12:25:11 +0200 Subject: [PATCH 3/5] Apply suggestions from code review --- conda-recipe/meta.yaml | 3 ++- pyproject.toml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/conda-recipe/meta.yaml b/conda-recipe/meta.yaml index 05f59a05..f3b32d8b 100644 --- a/conda-recipe/meta.yaml +++ b/conda-recipe/meta.yaml @@ -30,7 +30,8 @@ requirements: - numpy !=1.23.0 - pip - scikit-build >=0.14.1 - - setuptools_scm >=6.3 + - setuptools >=45 + - setuptools_scm >=6.3 run: - python {{ PY_VER }} diff --git a/pyproject.toml b/pyproject.toml index 640b2115..26e13998 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [build-system] requires = [ - "setuptools", + "setuptools>=45", "setuptools_scm>=6.3", "wheel", "scikit-build>=0.14.1", From 1da4cb8a40c70f4e60f57670f38db00b03c761b3 Mon Sep 17 00:00:00 2001 From: Ben Greiner Date: Sat, 16 Jul 2022 12:56:02 +0200 Subject: [PATCH 4/5] setuptools_scm writes slycot/version.py --- .coveragerc | 1 + conda-recipe/meta.yaml | 1 - pyproject.toml | 1 + setup.py | 3 +-- slycot/__init__.py | 7 +------ 5 files changed, 4 insertions(+), 9 deletions(-) diff --git a/.coveragerc b/.coveragerc index 97122d29..7f5d53d6 100644 --- a/.coveragerc +++ b/.coveragerc @@ -2,6 +2,7 @@ source = slycot omit = */tests/* + */version.py # please do not add any sections after this block diff --git a/conda-recipe/meta.yaml b/conda-recipe/meta.yaml index f3b32d8b..f2f128b0 100644 --- a/conda-recipe/meta.yaml +++ b/conda-recipe/meta.yaml @@ -37,7 +37,6 @@ requirements: - python {{ PY_VER }} - {{ pin_compatible('numpy') }} - libflang # [win] - - importlib_metadata # [py<38] test: requires: diff --git a/pyproject.toml b/pyproject.toml index 26e13998..2ad51c36 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,6 +9,7 @@ requires = [ build-backend = "setuptools.build_meta" [tool.setuptools_scm] +write_to = "slycot/version.py" [tool.pytest.ini_options] # run the tests with compiled and installed package diff --git a/setup.py b/setup.py index bab8c695..10c04a1e 100644 --- a/setup.py +++ b/setup.py @@ -103,8 +103,7 @@ def setup_package(): platforms=["Windows", "Linux", "Solaris", "Mac OS-X", "Unix"], cmdclass={"sdist": sdist_checked}, zip_safe=False, - install_requires=["numpy", - "importlib-metadata; python_version < '3.8'"], + install_requires=["numpy"], python_requires=">=3.7" ) diff --git a/slycot/__init__.py b/slycot/__init__.py index 3e57bf95..6bd59014 100644 --- a/slycot/__init__.py +++ b/slycot/__init__.py @@ -45,12 +45,7 @@ from .transform import tf01md, tf01rd from .transform import td04ad, tb01pd - try: - from importlib.metadata import version as imv - except ImportError: - from importlib_metadata import version as imv - __version__ = imv(__package__) - + from .version import __version__ def test(): From c7852683d3af5149ac067548aa8ce5bd2960b4fb Mon Sep 17 00:00:00 2001 From: Ben Greiner Date: Sat, 16 Jul 2022 13:52:17 +0200 Subject: [PATCH 5/5] move metadata to pyproject.toml --- pyproject.toml | 38 ++++++++++++++++++++++++++++ setup.py | 67 ++++++-------------------------------------------- 2 files changed, 46 insertions(+), 59 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 2ad51c36..5b39b4da 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,6 +8,44 @@ requires = [ "numpy!=1.23.0"] build-backend = "setuptools.build_meta" +[project] +name = "slycot" +description = "A wrapper for the SLICOT control and systems library" +readme = "README.rst" +authors = [{ name = "Enrico Avventi et al." }] +maintainers = [{ name = "Slycot developers", email = "python-control-discuss@lists.sourceforge.net"}] +license = {text = "GPL-2.0 AND BSD-3-Clause"} +classifiers = [ + "Development Status :: 4 - Beta", + "Intended Audience :: Science/Research", + "Intended Audience :: Developers", + "License :: OSI Approved", + "License :: OSI Approved :: GNU General Public License v2 (GPLv2)", + "License :: OSI Approved :: BSD License", + "Programming Language :: C", + "Programming Language :: Fortran", + "Programming Language :: Python", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Topic :: Software Development", + "Topic :: Scientific/Engineering", + "Operating System :: Microsoft :: Windows", + "Operating System :: POSIX", + "Operating System :: Unix", + "Operating System :: MacOS", +] +requires-python = ">=3.7" +dependencies = [ + "numpy", +] +dynamic = ["version"] + +[project.urls] +homepage = "https://github.com/python-control/Slycot" + + [tool.setuptools_scm] write_to = "slycot/version.py" diff --git a/setup.py b/setup.py index 10c04a1e..5ee3cb4f 100644 --- a/setup.py +++ b/setup.py @@ -8,10 +8,7 @@ import builtins import os -import sys import subprocess -import re -import platform try: from skbuild import setup @@ -24,29 +21,6 @@ except ImportError: raise ImportError('setuptools_scm must be installed before running setup.py') -DOCLINES = __doc__.split("\n") - -CLASSIFIERS = """\ -Development Status :: 4 - Beta -Intended Audience :: Science/Research -Intended Audience :: Developers -License :: OSI Approved -License :: OSI Approved :: GNU General Public License v2 (GPLv2) -Programming Language :: C -Programming Language :: Fortran -Programming Language :: Python -Programming Language :: Python :: 3.7 -Programming Language :: Python :: 3.8 -Programming Language :: Python :: 3.9 -Programming Language :: Python :: 3.10 -Topic :: Software Development -Topic :: Scientific/Engineering -Operating System :: Microsoft :: Windows -Operating System :: POSIX -Operating System :: Unix -Operating System :: MacOS -""" - # This is a bit hackish: we are setting a global variable so that the main # slycot __init__ can detect if it is being loaded by the setup routine, to # avoid attempting to load components that aren't built yet. While ugly, it's @@ -82,36 +56,11 @@ def run(self): check_submodules() sdist.run(self) -def setup_package(): - src_path = os.path.dirname(os.path.abspath(__file__)) - sys.path.insert(0, src_path) - - - metadata = dict( - name='slycot', - packages=['slycot', 'slycot.tests'], - cmake_languages=('C', 'Fortran'), - use_scm_version=True, - maintainer="Slycot developers", - maintainer_email="python-control-discuss@lists.sourceforge.net", - description=DOCLINES[0], - long_description=open('README.rst').read(), - url='https://github.com/python-control/Slycot', - author='Enrico Avventi et al.', - license='GPL-2.0', - classifiers=[_f for _f in CLASSIFIERS.split('\n') if _f], - platforms=["Windows", "Linux", "Solaris", "Mac OS-X", "Unix"], - cmdclass={"sdist": sdist_checked}, - zip_safe=False, - install_requires=["numpy"], - python_requires=">=3.7" - ) - - try: - setup(**metadata) - finally: - del sys.path[0] - - -if __name__ == '__main__': - setup_package() +# These need to stay in setup.py +# https://scikit-build.readthedocs.io/en/latest/usage.html#setuptools-options +setup( + packages=['slycot', 'slycot.tests'], + cmdclass={'sdist': sdist_checked}, + cmake_languages=('C', 'Fortran'), + use_scm_version = True, +)