Skip to content

Commit

Permalink
Moving singularity version string parsing into its own method. (#328)
Browse files Browse the repository at this point in the history
- New `Version.from_version_string` method that parses version strings printed by `singulairty --version` commands.
- Adding unit tests for this method.
  • Loading branch information
sergey-serebryakov authored Aug 2, 2023
1 parent c5f1193 commit 8bc7f13
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 24 deletions.
64 changes: 40 additions & 24 deletions runners/mlcube_singularity/mlcube_singularity/singularity_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,18 @@ class Runtime(Enum):
UNKNOWN = 0
APPTAINER = 1
SINGULARITY = 2
"""Singularity / SingularityCE
SingularityCE
https://github.com/sylabs/singularity/releases/tag/v3.8.0
This is the first release of SingularityCE 3.8.0, the Community Edition of the Singularity container runtime.
The package name for this release is now `singularity-ce`.
Singularity
https://github.com/sylabs/singularity/releases/tag/v3.7.4
Singularity 3.7.4 is the most recent stable release of Singularity prior to Sylabs' fork from
`github.com/hpcng/singularity`.
"""


class Version:
Expand All @@ -32,6 +44,33 @@ def __init__(self, runtime: Runtime, version: semver.VersionInfo) -> None:
def __str__(self) -> str:
return f"Version(runtime={self.runtime.name}, version={self.version})"

@classmethod
def from_version_string(cls, version_string: str) -> "Version":
version_string = version_string.strip()
if version_string.startswith("singularity version "):
runtime, version_string = (
Runtime.SINGULARITY,
version_string[20:].strip(),
)
elif version_string.startswith("singularity-ce version "):
runtime, version_string = (
Runtime.SINGULARITY,
version_string[23:].strip(),
)
elif version_string.startswith("apptainer version "):
runtime, version_string = Runtime.APPTAINER, version_string[18:].strip()
elif "/" in version_string: # Handle old stuff like "x.y.z-pull/123-0a5d"
runtime, version_string = Runtime.SINGULARITY, version_string.replace(
"/", "+", 1
)
else:
logger.warning(
"Version.from_version_string unrecognized container runtime (version_string: %s)",
version_string,
)
runtime = Runtime.UNKNOWN
return Version(runtime, semver.VersionInfo.parse(version_string))


class ImageSpec(Enum):
"""Build specification format for building singularity images.
Expand Down Expand Up @@ -138,30 +177,7 @@ def init(self, force: bool = False) -> None:
"version_cmd": version_cmd,
},
)

if version_string.startswith("singularity version "):
runtime, version_string = (
Runtime.SINGULARITY,
version_string[20:].strip(),
)
elif version_string.startswith("singularity-ce version "):
runtime, version_string = (
Runtime.SINGULARITY,
version_string[23:].strip(),
)
elif version_string.startswith("apptainer version "):
runtime, version_string = Runtime.APPTAINER, version_string[18:].strip()
elif "/" in version_string: # Handle old stuff like "x.y.z-pull/123-0a5d"
runtime, version_string = Runtime.SINGULARITY, version_string.replace(
"/", "+", 1
)
else:
logger.warning(
"Client.init unrecognized container runtime (version_string: %s)",
version_string,
)
runtime = Runtime.UNKNOWN
self.version = Version(runtime, semver.VersionInfo.parse(version_string))
self.version = Version.from_version_string(version_string)
logger.debug("Client.init version=%s", self.version)

def build(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,59 @@ def test_supports_fakeroot(self) -> None:
Version(Runtime.SINGULARITY, semver.VersionInfo(3, 4, 9)),
)
self.assertFalse(client.supports_fakeroot())

def inspect_version(self, version: Version, expected: Version) -> None:
self.assertIsInstance(version, Version)

self.assertIsInstance(version.runtime, Runtime)
self.assertEqual(version.runtime, expected.runtime)

self.assertIsInstance(version.version, semver.VersionInfo)
self.assertEqual(version.version, expected.version)

def test_version__init__(self) -> None:
version = Version(Runtime.APPTAINER, semver.VersionInfo(3, 7, 5))

self.assertIsInstance(version.runtime, Runtime)
self.assertEqual(version.runtime, Runtime.APPTAINER)

self.assertIsInstance(version.version, semver.VersionInfo)
self.assertEqual(version.version, semver.VersionInfo(3, 7, 5))

def test_version_from_version_string(self) -> None:
self.inspect_version(
Version.from_version_string("singularity version 3.7.4"),
Version(Runtime.SINGULARITY, semver.VersionInfo(3, 7, 4)),
)
self.inspect_version(
Version.from_version_string("singularity-ce version 3.5.4"),
Version(Runtime.SINGULARITY, semver.VersionInfo(3, 5, 4)),
)
self.inspect_version(
Version.from_version_string("singularity-ce version 3.11.0-rc.2"),
Version(
Runtime.SINGULARITY,
semver.VersionInfo(3, 11, 0, prerelease="rc.2", build=None),
),
)
self.inspect_version(
Version.from_version_string("apptainer version 1.1.9-1.el9"),
Version(
Runtime.APPTAINER,
semver.VersionInfo(1, 1, 9, prerelease="1.el9", build=None),
),
)
self.inspect_version(
Version.from_version_string("0.1.3-pull/123-0a5d"),
Version(
Runtime.SINGULARITY,
semver.VersionInfo(0, 1, 3, prerelease="pull", build="123-0a5d"),
),
)
self.inspect_version(
Version.from_version_string("1.0.32"),
Version(
Runtime.UNKNOWN,
semver.VersionInfo(1, 0, 32),
),
)

0 comments on commit 8bc7f13

Please sign in to comment.