Source code for crl.devutils.packagehandler
from contextlib import contextmanager
from crl.devutils.tmpdir import TmpDir
__copyright__ = 'Copyright (C) 2019, Nokia'
[docs]class MismatchOfTagAndVersionfileVersion(Exception):
pass
[docs]class MismatchOfTagAndSetupVersion(Exception):
pass
[docs]class VersionTagInWrongBranch(Exception):
pass
[docs]class PackageHandler(object):
"""
A handler for handling operations on a package.
Args:
versionhandler: An instance of VersionHandler.
setuphandler: An instance of SetupHandler.
changehandler: An instance of ChnageHandler.
githandler: An instance of GitHandler.
novirtualenv: If or not virtualenv must be used.
"""
def __init__(self,
versionhandler,
setuphandler,
changehandler,
githandler,
novirtualenv=False):
self.versionhandler = versionhandler
self.setuphandler = setuphandler
self.changehandler = changehandler
self.githandler = githandler
self.devpihandler = None
self._novirtualenv = novirtualenv
def set_devpihandler(self, devpihandler):
self.devpihandler = devpihandler
[docs] def verify_clean(self):
"""
Verifies the cleanliness/readyness of the package before any
actions are performed on the package. Following are checked
1. Version file consistency.
2. Change file consistency.
3. Clean working directory.
4. Tag existence and its branch.
Raises:
VersionTagInWrongBranch: Tag found in wrong branch.
MismatchOfTagAndSetupVersion: Tag and setup version are different.
InvalidVersionValue: Version in incorrect format.
ChangeFileNotFound: Change file doesn't exist.
MultipleChangeFilesFound: More than one change files are found.
ChangeFileVersionCheckFailed: Change file's latest version
is not same as package's setup version.
UncleanGitRepository: Working directory is unclean.
"""
self.versionhandler.validate_version(self.version)
self.changehandler.verify(self.version)
self.githandler.verify_clean()
self._verify_git_versus_setup()
def _verify_git_versus_setup(self):
if self.githandler.tag != self.setuphandler.version:
raise MismatchOfTagAndSetupVersion(
'Tag in git ({tag}) differs'
' from setup version ({version})'.format(
tag=self.githandler.tag,
version=self.setuphandler.version))
def _prepare_package(self):
self.versionhandler.set_githash(self.githandler.hash)
def _finalize_package(self):
self.githandler.checkout(self.versionhandler.version_file)
def _is_version_in_index(self, index):
pypiver = self.devpihandler.latest_pypi_version(
pkg_name=self.name, pypi_index=index)
if self.version == pypiver:
return True
return False
[docs] def tag_release(self, version, push):
"""
Updates the version file and tags with the specified version
and optionally pushes to the remote git repository.
Args:
version: Version with which the version file must be updated
and remote git tag must be created.
push: If TRUE, commits version file and pushes the tag to git.
Raises:
ChangeFileVersionCheckFailed: Change file version doesn't
match with the package version.
"""
self.changehandler.verify(version)
self.update_version(version, push)
self.githandler.tag_release(self.versionhandler.version,
push=push)
[docs] def tag_setup_version(self):
"""Tags with the version in setup if needed.
"""
self.githandler.tag_release(self.version, push=True)
[docs] def update_version(self, version, push):
"""
Updates the version file with the specified version and optionally
commits and pushes the file to the remote git repository.
Args:
version: Version with which the version file must be updated.
push: If TRUE, commits and pushes the version file to git.
"""
self.versionhandler.set_version(version)
self.githandler.update_version(self.versionhandler.version,
self.versionhandler.version_file,
push=push)
@property
def version(self):
return self.setuphandler.version
@property
def name(self):
return self.setuphandler.name
@property
def novirtualenv(self):
return self._novirtualenv
@contextmanager
def _prepared_package(self):
try:
self._prepare_package()
yield None
finally:
self._finalize_package()
[docs] def test(self,
base_index,
test_index=None,
credentials_file=None,
save_tests_to=None):
"""
Runs tests and uploads the results and docs to a given index.
If no index is given, a temporary index which is created for
running tests is later deleted.
Args:
base_index: Index to be used as a base for the test index,
specified as http[s]://host/user/index.
test_index: Name of the index created for testing,
specified as NAME.
credentials_file: User credentials to use.
save_tests_to: If given, copies the temporary files
generated during testing to this path.
Raises:
ChangeFileVersionCheckFailed: Change file version doesn't
match with the package version.
"""
self.changehandler.verify(self.version)
with TmpDir(copytree_to=save_tests_to):
self.devpihandler.set_index(base_index)
if credentials_file:
self.devpihandler.set_credentials_file(credentials_file)
with self._prepared_package():
self.devpihandler.test(test_index)
[docs] def publish(self,
srcindex,
destindex,
credentials_file=None,
tag_if_needed=False,
tag_branch='master'):
"""
Performs pre-checks and prepares for package version to be published
from a given index to another.
Args:
srcindex: Index from where to find the package version.
destindex: Index to publish the package version.
credentials_file: User credentials to use.
tag_if_needed: If or not to tag the version, if not tagged already.
tag_branch: Alternative git branch where the tag must be found.
Return:
bool: True, if publish was successful and False if publish was
skipped as package version was already published to destindex.
Raises:
VersionTagInWrongBranch: Tag was found in a different branch.
ChangeFileVersionCheckFailed: Change file version doesn't
match with the package version.
UncleanGitRepository: If the working directory is found unclean.
MismatchOfTagAndSetupVersion: If there is a mismatch in
tag and setup versions.
"""
self.devpihandler.set_index(srcindex)
if credentials_file:
self.devpihandler.set_credentials_file(credentials_file)
if not self._is_version_in_index(destindex):
if tag_if_needed:
self.githandler.tag_release(self.version, push=True)
self._verify_tag_branch(tag_branch)
self.verify_clean()
self.devpihandler.publish(destindex)
return True
return False
def _verify_tag_branch(self, tag_branch):
git_branch = self.githandler.get_branch_of_tag(self.version)
if git_branch != tag_branch:
raise VersionTagInWrongBranch(
"Version tag ({version}) is in branch '{git_branch}'"
" but should be in '{tag_branch}'".format(
version=self.version,
git_branch=git_branch,
tag_branch=tag_branch))