Source code for crl.devutils.changehandler

import glob
import xml.etree.ElementTree as etree
from docutils.core import publish_doctree


__copyright__ = 'Copyright (C) 2019, Nokia'


[docs]class ChangeFileNotFound(Exception): pass
[docs]class MultipleChangeFilesFound(Exception): pass
[docs]class ChangeFileVersionCheckFailed(Exception): pass
[docs]class ChangeHandler(object): """ Validates the given change file's syntax and parses the change file to get the latest documented version. If the change file isn't specified, it looks for a file named 'CHANGES' on the package's root directory and uses it. Valid file extensions for change file are '.rst' and '.md'. Args: run: Reference to a function capable of running shell commands. pathtochangefile: Relative path to change file. """ def __init__(self, run, pathtochangefile=None): self.run = run self.pathtochangefile = pathtochangefile self.allowed_extensions = ['.rst', '.md'] @property def latest_version(self): """ The latest version as in Change file. """ return self._latest_version() @property def change_file(self): """ Name/Relative path of change file in use. """ if self.pathtochangefile: return self.pathtochangefile return self._get_default_change_file() def _available_rst_md_files(self): for f in glob.glob('CHANGES.*'): if f.endswith(tuple(self.allowed_extensions)): yield f def _get_default_change_file(self): filesgen = self._available_rst_md_files() for f in filesgen: try: next(filesgen) raise MultipleChangeFilesFound() except StopIteration: return f raise ChangeFileNotFound() def _verify_syntax(self): return self.run('rstcheck {changefile}'.format( changefile=self.change_file)) @staticmethod def _read(filename): with open(filename) as f: return f.read() def _latest_version(self): contents = self._read(self.change_file) doctree = etree.fromstring((publish_doctree(contents).asdom()).toxml()) titles = [title for section in doctree.findall( 'section') for title in section.findall('title')] versions = [title.text for title in titles] or [ subtitle.text for subtitle in doctree.findall('subtitle')] return versions[0] if versions else '' def _verify_latest(self, version): if self.latest_version != version: raise ChangeFileVersionCheckFailed( 'Latest version in %s is %s and not %s' % ( self.change_file, self.latest_version, version))
[docs] def verify(self, version): """ Verify if the given version is the newest version listed in ChangeFile. Args: version: version to check. Raises: Failure: Raised if the Change file syntax is incorrect. ChangeFileNotFound: Raised if the Change file is not found. MultipleChangeFilesFound: Raised if more than one changefile found. ChangeFileVersionCheckFailed: Raises if the given version is not the newest version listed in the Changefile. """ self._verify_syntax() self._verify_latest(version)