Source code for varats.provider.release.release_provider
"""Module for the :class:`ReleaseProvider`."""
import typing as tp
from enum import Enum
from benchbuild.project import Project
from packaging.version import Version
from packaging.version import parse as parse_version
from varats.project.project_util import get_tagged_commits
from varats.provider.provider import Provider
from varats.utils.git_util import FullCommitHash
[docs]
class ReleaseType(Enum):
"""
A ReleaseType referes to one of the three parts of the semantic versioning
specification.
It is assumed that a major release is also a minor release and that a minor
release is also a patch release.
"""
value: int # pylint: disable=invalid-name
MAJOR = 1
MINOR = 2
PATCH = 3
[docs]
def merge(self, other: tp.Optional["ReleaseType"]) -> "ReleaseType":
"""
Merges two release type. It is assumed that minor releases include major
releases and patch releases include minor releases.
>>> ReleaseType.MINOR.merge(ReleaseType.MAJOR)
<ReleaseType.MINOR: 2>
>>> ReleaseType.MAJOR.merge(ReleaseType.PATCH)
<ReleaseType.PATCH: 3>
"""
if other is None:
return self
# Pylint incorrectly issues a warning here.
# pylint: disable=W0143
return self if self.value >= other.value else other
[docs]
class ReleaseProviderHook():
"""
Gives the :class:`ReleaseProvider` the necessary information how to find the
releases for a project.
This class should be inherited by projects.
"""
[docs]
@classmethod
def get_release_revisions(
cls, release_type: ReleaseType
) -> tp.List[tp.Tuple[FullCommitHash, str]]:
"""
Get a set of all release revisions for a project.
Returns:
a list of tuples of hashes and version strings of release commits
"""
raise NotImplementedError("Must be overridden by the project.")
[docs]
class ReleaseProvider(Provider):
"""Provides access to release revisions of a project."""
def __init__(self, project: tp.Type[Project]) -> None:
super().__init__(project)
if hasattr(project, "get_release_revisions"):
self.hook = tp.cast(ReleaseProviderHook, project)
else:
raise ValueError(
f"Project {project} does not implement "
f"ReleaseProviderHook."
)
[docs]
@classmethod
def create_provider_for_project(
cls, project: tp.Type[Project]
) -> tp.Optional['ReleaseProvider']:
if hasattr(project, "get_release_revisions"):
return ReleaseProvider(project)
return None
[docs]
@classmethod
def create_default_provider(
cls, project: tp.Type[Project]
) -> 'ReleaseProvider':
return ReleaseDefaultProvider(project)
[docs]
def get_release_revisions(
self, release_type: ReleaseType
) -> tp.List[tp.Tuple[FullCommitHash, str]]:
"""
Get all release revisions of this provider's project along with their
version strings.
Args:
release_type: the type of releases to return
Return:
a list of tuples of hashes and version strings of release commits
"""
return self.hook.get_release_revisions(release_type)
[docs]
class ReleaseDefaultProvider(ReleaseProvider):
"""
Default implementation of the :class:`ReleaseProvider` for projects that do
not need or support their own implementation.
This implementation looks for commits with tags that are
`PEP 440 <https://www.python.org/dev/peps/pep-0440/>`_
versions.
"""
def __init__(self, project: tp.Type[Project]) -> None:
# pylint: disable=E1003
super(ReleaseProvider, self).__init__(project)
tagged_commits = get_tagged_commits(self.project.NAME)
releases = [(FullCommitHash(commit), tag, parse_version(tag))
for commit, tag in tagged_commits]
self.releases = [(commit, tag, version)
for commit, tag, version in releases
if isinstance(version, Version)]
[docs]
def get_release_revisions(
self, release_type: ReleaseType
) -> tp.List[tp.Tuple[FullCommitHash, str]]:
def get_patch_releases() -> tp.List[tp.Tuple[FullCommitHash, str]]:
return [(commit, tag)
for commit, tag, version in self.releases
if not version.is_prerelease]
def get_minor_releases() -> tp.List[tp.Tuple[FullCommitHash, str]]:
return [(commit, tag)
for commit, tag, version in self.releases
if version.micro == 0]
def get_major_releases() -> tp.List[tp.Tuple[FullCommitHash, str]]:
return [(commit, tag)
for commit, tag, version in self.releases
if version.minor == 0]
return {
ReleaseType.PATCH: get_patch_releases,
ReleaseType.MINOR: get_minor_releases,
ReleaseType.MAJOR: get_major_releases
}[release_type]()