From 227c1b61bf5870d46100668d3f14b7e9f1e87b78 Mon Sep 17 00:00:00 2001
From: Tobias Winchen <tobias.winchen@rwth-aachen.de>
Date: Thu, 20 Oct 2022 19:57:41 +0200
Subject: [PATCH] Use setuptools_scm vor versioning, adapt to PEP 621

---
 mpikat/core/version.py     | 63 ++++++----------------------
 pyproject.toml             | 36 ++++++++++++++++
 setup.cfg                  | 21 ----------
 setup.py                   |  1 -
 tests/test_core_manager.py | 86 ++++++++++++++++++++++++--------------
 5 files changed, 103 insertions(+), 104 deletions(-)
 create mode 100644 pyproject.toml
 delete mode 100644 setup.cfg
 delete mode 100644 setup.py

diff --git a/mpikat/core/version.py b/mpikat/core/version.py
index 50bc939a..0dc153ca 100644
--- a/mpikat/core/version.py
+++ b/mpikat/core/version.py
@@ -1,64 +1,27 @@
 """
 Determine the version of the code. If no version number is given, the version is deduced from git
 """
+import setuptools_scm
+from importlib.metadata import version, PackageNotFoundError
 
-# if hard coded version from setup.py use this
-# ToDo, not implemented as no setup.py here
-import os
-import subprocess
-import sys
+import mpikat.core.logger
 
-from mpikat.core import logger
+_log = mpikat.core.logger.getLogger("mpikat.core.version")
 
-_log = logger.getLogger("mpikat.core.version")
 
-VERSION = '0.0.1+UNKNOWN'
 try:
-    _log.debug("Determine version from git repository")
-    import git
-
-    path = os.path.dirname(os.path.realpath(__file__))
-    _log.debug("code file located in {}".format(path))
-    rroot = os.path.join(path, "../..")
-    _log.debug("repository root {}".format(rroot))
-
-    repo = git.Repo(rroot)
-
-    # Check if current version is a tag, use shaidx otherwise
-    _log.debug("Get latest tag")
-    if sys.version_info >= (3, 6):
-        LATEST_TAG = subprocess.check_output('git describe --abbrev=0 --tags'.split(), cwd=rroot, encoding='utf-8').strip()
-    else:
-        LATEST_TAG = subprocess.check_output('git describe --abbrev=0 --tags'.split(), cwd=rroot).strip()
-
-    _log.debug(" LATEST TAG: %s", LATEST_TAG)
-
-    if repo.tags[LATEST_TAG].commit == repo.head.commit:
-        VERSION = "{}".format(LATEST_TAG)
-        if repo.is_dirty():
-            VERSION += "+withMODIFICATIONS"
-    else:
-        # This date format is not well readable, but does not violate
-        # PEP440 local version definition. Adhering to PEP440 is necessary
-        # for installation with pip / setuptools in new versions
-        VERSION = "{}+{}.{}".format(LATEST_TAG, repo.head.object.hexsha, repo.head.object.authored_datetime.strftime("%Y%m%dT%H%M%S"))
-        if repo.is_dirty():
-            VERSION += ".withMODIFICATIONS"
-
-except Exception as E:
-    _log.debug("Error determining version from git:\n{}".format(E))
+    VERSION = setuptools_scm.get_version(version_scheme="release-branch-semver",
+            root='../..', relative_to=__file__)
+except LookupError:
+    _log.debug("Cannot retrieve version from git, possibly because package was installed")
     try:
-        version_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'version.txt')
-        with open(version_file, "r") as f:
-            VERSION = f.read().strip()
-        if not VERSION.endswith(".fromFILE"):
-            VERSION += ".fromFILE"
+        VERSION = version("mpikat")
+    except PackageNotFoundError:
+        _log.warning("Cannot determine version")
+        VERSION = '0.0.1+UNKNOWN'
 
-    except Exception as E:
-        _log.debug("Cannot read version file: {}".format(E))
-        _log.error("Cannot determin verion!")
 
-_log.debug("VERSION: {}".format(VERSION))
+_log.debug("VERSION: %s", VERSION)
 
 if __name__ == "__main__":
     print(VERSION)
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 00000000..5c9ef89d
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,36 @@
+[project]
+name = "mpikat"
+authors = [
+	{name="Ewan Barr", email="ebarr@mpifr.de"},
+	{name="Niclas Esser", email="nesser@mpifr.de"},
+	{name="Tobias Winchen", email="twinchen@mpifr.de"},
+	{name="Jason Wu", email="jwu@mpifr.de"}
+]
+
+description = "Control layer for the EDD backend."
+license = {file="LICENSE"}
+readme = "README.md"
+requires-python= ">=3.6"
+
+dynamic = ["version"]
+
+classifiers = [
+    "Programming Language :: Python :: 3",
+		"License :: OSI Approved :: MIT License",
+    "Operating System :: OS Independent",
+]
+
+dependencies = [
+  'coloredlogs',
+  'aiokatcp',
+]
+
+[project.urls]
+"Homepage" = "https://gitlab.mpcdf.mpg.de/mpifr-bdg/mpikat"
+
+[build-system]
+requires = ["setuptools>=45", "setuptools_scm[toml]>=6.2"]
+build-backend = "setuptools.build_meta"
+
+# empty section required
+[tool.setuptools_scm]
diff --git a/setup.cfg b/setup.cfg
deleted file mode 100644
index 549c4bc5..00000000
--- a/setup.cfg
+++ /dev/null
@@ -1,21 +0,0 @@
-[metadata]
-name = mpikat
-version = file: mpikat/core/version.txt
-author = Ewan Barr, Tobias Winchen, Jason Wu
-author_email = ebarr@mpifr-bonn.mpg.de
-description= Control software for the EDD
-long_description = file: README.md
-long_description_content_type = text/markdown
-url=https://gitlab.mpcdf.mpg.de/mpifr-bdg/mpikat.git
-classifiers =
-    Programming Language :: Python :: 3
-    License :: OSI Approved :: MIT
-    Operating System :: Linux
-
-[options]
-packages = find:
-python_requires = >=2.7
-include_package_data = True
-
-[options.package_data]
-* = core/version.txt,
diff --git a/setup.py b/setup.py
deleted file mode 100644
index acca8ee2..00000000
--- a/setup.py
+++ /dev/null
@@ -1 +0,0 @@
-from setuptools import setup; setup()
diff --git a/tests/test_core_manager.py b/tests/test_core_manager.py
index c0891fb7..f90b0862 100644
--- a/tests/test_core_manager.py
+++ b/tests/test_core_manager.py
@@ -1,54 +1,76 @@
-from __future__ import print_function, division, unicode_literals
+# pylint: disable=protected-access,missing-function-docstring,too-few-public-methods,missing-class-docstring
 import unittest
-import logging
 
 from mpikat.utils.core_manager import CoreManager
-import mpikat.utils.numa as numa
+from mpikat.utils import numa
+
 
 class Test_core_manager(unittest.TestCase):
     def setUp(self):
-        self.cm = CoreManager('0')
+        self.cm = CoreManager("0")
 
     def test_too_many_cores(self):
-        self.cm.add_task('T1', len(numa.getInfo()['0']['cores']) + len(numa.getInfo()['0']['isolated_cores'])+ 1 )
+        self.cm.add_task(
+            "T1",
+            len(numa.getInfo()["0"]["cores"])
+            + len(numa.getInfo()["0"]["isolated_cores"])
+            + 1,
+        )
 
-        self.assertEqual(len(self.cm.get_cores('T1')), len(numa.getInfo()['0']['cores']))
+        self.assertEqual(
+            len(self.cm.get_cores("T1")), len(numa.getInfo()["0"]["cores"])
+        )
 
     def test_too_many_isolated_cores(self):
-        self.cm.add_task('T1', len(numa.getInfo()['0']['isolated_cores']) + 1, require_isolated=True)
-        with self.assertRaises(Exception) as context:
-            self.cm.get_cores('T1')
- 
+        self.cm.add_task(
+            "T1", len(numa.getInfo()["0"]["isolated_cores"]) + 1, require_isolated=True
+        )
+        with self.assertRaises(Exception):
+            self.cm.get_cores("T1")
+
     def test_use_non_isolated_cores(self):
-        self.cm.add_task('T1', len(numa.getInfo()['0']['isolated_cores']) + 1, prefere_isolated=True)
-        self.cm.get_cores('T1')
+        self.cm.add_task(
+            "T1", len(numa.getInfo()["0"]["isolated_cores"]) + 1, prefere_isolated=True
+        )
+        self.cm.get_cores("T1")
 
     def test_list_return(self):
-        self.cm.add_task('T1', 1)
-        self.cm.add_task('T2', 2)
+        self.cm.add_task("T1", 1)
+        self.cm.add_task("T2", 2)
 
-        self.assertTrue(isinstance(self.cm.get_cores('T1'), list))
-        self.assertTrue(isinstance(self.cm.get_cores('T2'), list))
-
-        self.assertEqual(len(self.cm.get_cores('T1')), 1)
-        self.assertEqual(len(self.cm.get_cores('T2')), 2)
+        self.assertTrue(isinstance(self.cm.get_cores("T1"), list))
+        self.assertTrue(isinstance(self.cm.get_cores("T2"), list))
 
+        self.assertEqual(len(self.cm.get_cores("T1")), 1)
+        self.assertEqual(len(self.cm.get_cores("T2")), 2)
 
     def test_list_str_equivalence(self):
-        self.cm.add_task('T1', 3)
-
-        self.assertEqual(self.cm.get_cores('T1'), self.cm.get_coresstr("T1").split(','))
+        self.cm.add_task("T1", 3)
 
+        self.assertEqual(self.cm.get_cores("T1"), self.cm.get_coresstr("T1").split(","))
 
     def test_non_ovverlap(self):
-        self.cm.add_task('T1', len(numa.getInfo()['0']['cores']) // 2)
-        self.cm.add_task('T2', len(numa.getInfo()['0']['cores']) // 2)
-        T1 = self.cm.get_cores('T1')
-        T2 = self.cm.get_cores('T2')
-        #print("XXX", T1, type(T1))
-        self.assertEqual(len(T1), len(set(T1)), "Cores associated to task multiple times: {}".format(T1))
-        self.assertEqual(len(T2), len(set(T2)), "Cores associated to task multiple times: {}".format(T2))
-        self.assertEqual(len(T2 + T1), len(set(T2 + T1)), "Cores not unique: T1={}, T2={}".format(T1, T2))
-
-if __name__ == '__main__':
+        self.cm.add_task("T1", len(numa.getInfo()["0"]["cores"]) // 2)
+        self.cm.add_task("T2", len(numa.getInfo()["0"]["cores"]) // 2)
+        T1 = self.cm.get_cores("T1")
+        T2 = self.cm.get_cores("T2")
+
+        self.assertEqual(
+            len(T1),
+            len(set(T1)),
+            "Cores associated to task multiple times: {}".format(T1),
+        )
+        self.assertEqual(
+            len(T2),
+            len(set(T2)),
+            "Cores associated to task multiple times: {}".format(T2),
+        )
+        self.assertEqual(
+            len(T2 + T1),
+            len(set(T2 + T1)),
+            "Cores not unique: T1={}, T2={}".format(T1, T2),
+        )
+
+
+if __name__ == "__main__":
     unittest.main()
-- 
GitLab