diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e36dc33d..3de145a7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,11 +13,19 @@ jobs: strategy: matrix: python-version: ['3.13'] + omc-version: ['stable'] steps: - name: Checkout code uses: actions/checkout@v4 + - name: "Set up OpenModelica Compiler" + uses: OpenModelica/setup-openmodelica@v1.0 + with: + version: ${{ matrix.omc-version }} + packages: | + omc + - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: diff --git a/.gitignore b/.gitignore index e1d99916..c868039b 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,6 @@ __pycache__ *.pyc /.venv/ /.vscode/ -cache +/cache/ index.json +tests/tmp-cache/ diff --git a/ompackagemanager/updateinfo.py b/ompackagemanager/updateinfo.py index 30bc24b5..7191d373 100755 --- a/ompackagemanager/updateinfo.py +++ b/ompackagemanager/updateinfo.py @@ -73,9 +73,9 @@ def collect_branches_tags(entry: dict, key: str, repopath: str, if "github" in entry: try: - r = github_api.get_repo(entry["github"]) - branches = list(Branch(b.name, b.commit.sha) for b in r.get_branches()) - tags = list(Tag(b.name, b.commit.sha) for b in r.get_tags()) + repo = github_api.get_repo(entry["github"]) + branches = list(Branch(b.name, b.commit.sha) for b in repo.get_branches()) + tags = list(Tag(b.name, b.commit.sha) for b in repo.get_tags()) giturl = "https://github.com/%s.git" % entry["github"] except BaseException: print("Failed to get github entry: %s" % entry["github"]) @@ -104,7 +104,7 @@ def collect_branches_tags(entry: dict, key: str, repopath: str, return branches, tags, giturl -def normalize_version(version: str, tagName: str, entry) -> str: +def normalize_version(version: str, tagName: str, entry: dict) -> str: """Use tag name to normalize version string""" if version == "": @@ -112,14 +112,17 @@ def normalize_version(version: str, tagName: str, entry) -> str: else: v1 = common.VersionNumber(version) v2 = common.VersionNumber(tagName) - if len(v2.prerelease) == 0 and entry.get("semverTagOverridesAnnotation") and ( - v2 > v1 or entry["semverTagOverridesAnnotation"] == "alsoNewerVersions"): + + tagOverride = entry.get("semverTagOverridesAnnotation", False) + if len(v2.prerelease) == 0 and tagOverride and (v2 > v1 or tagOverride == "alsoNewerVersions"): v1 = v2 - if len(v2.prerelease) > 0 and (len(v1.prerelease) == 0 or entry.get( - "semverPrereleaseOverridesAnnotation") or tagName in ["master", "main", "trunk"]): + + prereleaseOverride = entry.get("semverPrereleaseOverridesAnnotation") + if len(v2.prerelease) > 0 and (len(v1.prerelease) == 0 or prereleaseOverride): v1.prerelease = v2.prerelease if tagName in ["master", "main", "trunk"] and len(v2.build) == 0: v1.build = [] + if v1.major == v2.major and v1.minor == v2.minor and v1.patch == v2.patch and len( v1.prerelease) == 0 and len(v1.build) == 0: version = str(v2) @@ -140,8 +143,7 @@ def new_libentry(libname: str, entry, hits: list[str], repopath: str, - omc: OMPython.OMCSessionZMQ) -> dict[str, - str]: + omc: OMPython.OMCSessionZMQ) -> dict[str, str]: """Create new entry for Modelica library. Args: diff --git a/rawdata.json b/rawdata.json index 2605a382..f6dc8212 100644 --- a/rawdata.json +++ b/rawdata.json @@ -6878,7 +6878,7 @@ "4.0.0", "4.1.0" ], - "version": "4.2.0-master" + "version": "4.2.0-dev" }, "Modelica": { "convertFromVersion": [ @@ -6899,11 +6899,11 @@ "Complex": "4.2.0-dev", "ModelicaServices": "4.2.0-dev" }, - "version": "4.2.0-master" + "version": "4.2.0-dev" }, "ModelicaReference": { "path": "ModelicaReference", - "version": "4.2.0-master" + "version": "4.2.0-dev" }, "ModelicaServices": { "path": "ModelicaServices", @@ -6917,28 +6917,28 @@ "4.0.0", "4.1.0" ], - "version": "4.2.0-master" + "version": "4.2.0-dev" }, "ModelicaTest": { "path": "ModelicaTest", "uses": { "Modelica": "4.2.0-dev" }, - "version": "4.2.0-master" + "version": "4.2.0-dev" }, "ModelicaTestOverdetermined": { "path": "ModelicaTestOverdetermined.mo", "uses": { "Modelica": "4.2.0-dev" }, - "version": "4.2.0-master" + "version": "4.2.0-dev" }, "ObsoleteModelica4": { "path": "ObsoleteModelica4.mo", "uses": { "Modelica": "4.2.0-dev" }, - "version": "4.2.0-master" + "version": "4.2.0-dev" } }, "sha": "0f27e460c7639c3e138766572f30842142367379" @@ -6981,7 +6981,7 @@ }, "ModelicaReference": { "path": "ModelicaReference", - "version": "4.2.0-trunk" + "version": "4.2.0-dev" }, "ModelicaServices": { "path": "ModelicaServices", @@ -7012,14 +7012,14 @@ "uses": { "Modelica": "4.2.0-dev" }, - "version": "4.2.0-trunk" + "version": "4.2.0-dev" }, "ObsoleteModelica4": { "path": "ObsoleteModelica4.mo", "uses": { "Modelica": "4.2.0-dev" }, - "version": "4.2.0-trunk" + "version": "4.2.0-dev" } }, "sha": "be25335e6d72e4ffab8c8cb70fb591aa703763bf" @@ -8970,7 +8970,7 @@ "uses": { "Modelica": "3.2.1" }, - "version": "1.0.0-master" + "version": "1.0.0-Beta.1" } }, "sha": "5fbae4513fa03d8937c27d4047670a146041c2d6" @@ -9732,7 +9732,7 @@ "Complex": "4.0.0", "Modelica": "4.0.0" }, - "version": "3.1.0-master" + "version": "3.1.0-dev" } }, "sha": "fe8aa5ceae90d123cc5b0f87be6362f6723cb116" @@ -10974,7 +10974,7 @@ "Complex": "4.0.0", "Modelica": "4.0.0" }, - "version": "3.1.0-master" + "version": "3.1.0-alpha" } }, "sha": "d4f7db61f1e179a2dd0388541d1ea8f26953fd5f" @@ -11261,7 +11261,7 @@ "uses": { "Modelica": "4.0.0" }, - "version": "2.0.0-master" + "version": "2.0.0-dev" } }, "sha": "22c7999846dd84964bbe174b3ec93d9c9a11d077" @@ -13012,7 +13012,7 @@ "uses": { "Modelica": "4.0.0" }, - "version": "1.9.0-main" + "version": "1.9.0-ClaRa" } }, "sha": "1845376fb70a32e51c8bbf75ae999c27662b376e" @@ -14227,4 +14227,4 @@ } } } -} \ No newline at end of file +} diff --git a/tests/test_libentry.py b/tests/test_libentry.py new file mode 100644 index 00000000..1c62746e --- /dev/null +++ b/tests/test_libentry.py @@ -0,0 +1,169 @@ +import unittest +import json +import os +from pathlib import Path +import shutil +import pygit2 +import OMPython + +from ompackagemanager.updateinfo import new_libentry, getgitrepo + + +class TestNewLibentry(unittest.TestCase): + @classmethod + def setUpClass(cls): + """Clone git repositories, start OMC session.""" + + def checkout_repo(github_repo: str, refname: str) -> str: + """Clone and checkout a git repository from GitHub""" + giturl = "https://github.com/%s.git" % github_repo + repopath = os.path.join(cls.cache_dir, github_repo.split("/")[-1]) + + if not os.path.exists(repopath): + pygit2.clone_repository(giturl, repopath) + gitrepo = pygit2.Repository(repopath) + + if refname.startswith("refs/"): + gitrepo.checkout( + gitrepo.lookup_reference(refname), + strategy=pygit2.GIT_CHECKOUT_FORCE | pygit2.GIT_CHECKOUT_RECREATE_MISSING) + else: + gitrepo.checkout_tree( + gitrepo.get(refname), + strategy=pygit2.GIT_CHECKOUT_FORCE | pygit2.GIT_CHECKOUT_RECREATE_MISSING) + + return os.path.normpath(os.path.join(gitrepo.path, os.pardir)) + + cls.cache_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "tmp-cache") + os.makedirs(cls.cache_dir, exist_ok=True) + + cls.omc = OMPython.OMCSessionZMQ() + cls.omc.sendExpression('setCommandLineOptions("--std=latest")') + + cls.aixlib_path = checkout_repo("RWTH-EBC/AixLib", "refs/tags/v2.1.1") + cls.msl_path = checkout_repo("modelica/ModelicaStandardLibrary", "478538e43d3c9f682b2a6fb667783e2b3760f9f3") + + @classmethod + def tearDownClass(cls): + """Remove git repositories, stop OMC session.""" + cls.omc.sendExpression("exit") + shutil.rmtree(cls.cache_dir) + + def tearDown(self): + """Clear omc session""" + self.omc.sendExpression('clear()') + + def test_aixlib_tag_version(self): + """Test libentry for AixLib v2.1.1""" + + libname = "AixLib" + tagName = "v2.1.1" + entry = json.loads( + """ + { + "names": ["AixLib"], + "github": "RWTH-EBC/AixLib", + "branches": {"development": "development", "main": "main"}, + "ignore-tags": ["v0.7.2", "v0.7.1", "v0.7.0", "v0.1.0"], + "support": [ + ["prerelease", "noSupport"], + [">=1.3.1", "support"], + [">=0.9.1", "experimental"], + ["*", "obsolete"] + ] + } + """) + + # Load package.mo + repopath = self.aixlib_path + hits = [os.path.join(repopath, "AixLib", "package.mo")] + self.omc.sendExpression('loadFile("%s", uses=false)' % hits[0]) + + libentry = new_libentry( + libname=libname, + tagName=tagName, + entry=entry, + hits=hits, + repopath=repopath, + omc=self.omc + ) + + expected_libentry = { + "version": "2.1.1", + "path": "AixLib", + "uses": { + "Modelica": "4.0.0", + "Modelica_DeviceDrivers": "2.1.1", + "SDF": "0.4.2" + }, + "convertFromVersion": [ + "2.1.0" + ], + } + self.assertDictEqual(libentry, expected_libentry) + + def test_modelica_master_version(self): + """Test libentry for Modelica master""" + + libname = "Modelica" + branch = "master" + entry = json.loads( + """ + { + "names": ["Modelica","ModelicaReference","ModelicaServices","ModelicaTest","ModelicaTestOverdetermined","Complex","ObsoleteModelica3","ObsoleteModelica4"], + "github": "modelica/ModelicaStandardLibrary", + "branches": { + "master": "master" + }, + "standard": [ + [">=3.4.0", "latest"], + ["*", "latest"] + ], + "support": [ + [">=3.2.3", "fullSupport"], + ["*", "obsolete"] + ] + } + """) + + # Load package.mo + repopath = self.msl_path + hits = [os.path.join(repopath, "Modelica", "package.mo")] + self.omc.sendExpression('clear()') + self.omc.sendExpression('loadFile("%s", uses=false)' % hits[0]) + + libentry = new_libentry( + libname=libname, + tagName=branch, + entry=entry, + hits=hits, + repopath=repopath, + omc=self.omc + ) + + expected_libentry = { + "version": "4.2.0-dev", + "path": "Modelica", + "uses": { + "Complex": "4.2.0-dev", + "ModelicaServices": "4.2.0-dev" + }, + "provides": [ + "4.0.0", + "4.1.0" + ], + "convertFromVersion": [ + "3.0.0", + "3.0.1", + "3.1.0", + "3.2.0", + "3.2.1", + "3.2.2", + "3.2.3" + ] + } + self.assertDictEqual(libentry, expected_libentry) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_normalize_version.py b/tests/test_normalize_version.py index 9e619e8a..c702442d 100644 --- a/tests/test_normalize_version.py +++ b/tests/test_normalize_version.py @@ -3,6 +3,7 @@ class TestVersionNormalization(unittest.TestCase): + """Test function normalize_version""" def test_master_dev_version(self): """Test version on master branch""" @@ -10,29 +11,34 @@ def test_master_dev_version(self): tagName = "master" entry = dict() - normalized_version = normalize_version( - version=version, tagName=tagName, entry=entry) + normalized_version = normalize_version(version=version, tagName=tagName, entry=entry) self.assertEqual(normalized_version, "1.2.3-master") - @unittest.expectedFailure def test_master_w_build_dev_version(self): """Test version with build on master branch""" version = "1.2.3 build" tagName = "master" entry = dict() - normalized_version = normalize_version( - version=version, tagName=tagName, entry=entry) + normalized_version = normalize_version(version=version, tagName=tagName, entry=entry) self.assertEqual(normalized_version, "1.2.3-build") + def test_master_w_prerelease_dev_version(self): + """Test version with prerelease on master branch""" + version = "1.2.3-prerelease" + tagName = "master" + entry = dict() + + normalized_version = normalize_version(version=version, tagName=tagName, entry=entry) + self.assertEqual(normalized_version, "1.2.3-prerelease") + def test_empty_tag(self): """Test version with build without tag name""" version = "1.2.3 build" tagName = "" entry = dict() - normalized_version = normalize_version( - version=version, tagName=tagName, entry=entry) + normalized_version = normalize_version(version=version, tagName=tagName, entry=entry) self.assertEqual(normalized_version, "1.2.3-build")