Source code for interactions.ext.version

from enum import Enum
from hashlib import md5
from string import ascii_lowercase
from typing import List, Optional, Union

from .error import IncorrectAlphanumeric, TooManyAuthors

__all__ = (
    "VersionAuthor",
    "VersionAlphanumericType",
    "Version",
)


[docs]class VersionAlphanumericType(str, Enum): ALPHA = "alpha" BETA = "beta" RELEASE_CANDIDATE = "rc" LETTER = ascii_lowercase
[docs]class VersionAuthor: """ A class representing the author involved in a version. :ivar MD5Hash _hash: The hashed representation of the class. :ivar bool _co_author: Whether this is a co-author or not. :ivar bool active: Whether the author is active or not. :ivar str email: The email of the author. :ivar str name: The name of the author. """ __slots__ = ("_hash", "_co_author", "active", "email", "name") def __init__( self, name, *, shared: Optional[bool] = False, active: Optional[bool] = True, email: Optional[str] = None, ) -> None: """ :param name: The name of the author. :type name: str :param shared?: The author's relationship as the main or co-author. Defaults to ``False``. :type shared?: Optional[bool] :param active?: The author's state of activity. Defaults to ``True``. :type active?: Optional[bool] :param email?: The author's email address or point of contact. Defaults to ``None``. :type email?: Optional[str] """ self.name = name self._co_author = shared self.active = active self.email = email self._hash = md5(self.__str__().encode()) def __hash__(self): return self._hash def __str__(self) -> str: return f'{self.name}{f" <{self.email}>" if self.email else ""}' @property def is_co_author(self) -> bool: """Returns whether the author is a co-author or not.""" return self._co_author @property def signature(self) -> str: return f"{'Co-authored by: ' if self._co_author else ''}{self.__str__()}"
[docs]class Version: """ A class representing how a version is structured for a 3rd party library. .. note:: This class respects the design and application of Semantic Versioning 2.0.0, (SemVer) a widely accepted standardisation of version control for modules and projects. :ivar int _major: The major version. :ivar int _minor: The minor version. :ivar int _patch: The patch version. :ivar List[VersionAuthor] _authors: The authors tied to the version release. :ivar str __version: The representation of the version. :ivar Optional[Dict[str, Union[int, VersionAlphanumericType]]] __alphanum: The alphanumeric typing of the version. """ __slots__ = ("_major", "_minor", "_patch", "_authors", "__version", "__alphanum") def __init__(self, **kwargs) -> None: """ :param major?: The major version. If not specified, ``version`` will be read from. :type major?: Optional[Union[str, int]] :param minor?: The minor version. If not specified, ``version`` will be read from. :type minor?: Optional[Union[str, int]] :param patch?: The patch version. If not specified, ``version`` will be read from. :type patch?: Optional[Union[str, int]] :param version?: The overall version. Must be used if ``major``, ``minor`` or ``patch`` are not. :type version?: Optional[str] """ self._major = int(kwargs.get("major") or kwargs.get("version", "0.0.0").split(".")[0]) self._minor = int(kwargs.get("minor") or kwargs.get("version", "0.0.0").split(".")[1]) self._patch = int(kwargs.get("patch") or kwargs.get("version", "0.0.0").split(".")[2]) self._authors = kwargs.get("authors", []) or kwargs.get("author", []) self.__version = f"{self._major}.{self._minor}.{self._patch}" self.__alphanum = None def __repr__(self) -> str: return self.__version def __str__(self) -> str: return self.__repr__() @property def major(self) -> int: """Returns the major version.""" return self._major @property def minor(self) -> int: """Returns the minor version.""" return self._minor @property def patch(self) -> int: """Returns the patch version.""" return self._patch @property def author(self) -> Optional[Union[Exception, VersionAuthor]]: """ Returns the author of the version. If multiple authors exist, it will choose the only one that is not a co-author. :return: The author of the version, if one exists. :rtype: Optional[VersionAuthor] :raises TooManyAuthors: Too many main authors were found. """ _author: str = "" if len(self._authors) == 1: return self._authors elif len(self._authors) > 1: amount: int = 0 for author in self._authors: if author.co_author: amount += 1 elif amount > 1: raise TooManyAuthors else: _author = author continue return _author else: return None @property def authors(self) -> Optional[List[VersionAuthor]]: """ Returns the list of authors under the version. :return: The authors of the version, if any exist. :rtype: Optional[List[VersionAuthor]] """ if len(self._authors) > 1: return self._authors elif not len(self._authors): return None @property def is_alphanumeric(self) -> bool: """Returns whether the version is alphanumeric or not.""" return bool(self.__alphanum)
[docs] @classmethod def extend_version(cls, **kwargs) -> Union[Exception, str]: r""" Allows the version to be extended upon with an alphanumeric format. :param \**kwargs: Key-word arguments to be supplied as ``alpha``, ``beta`` or ``rc`` respectively. :type \**kwargs: Dict[VersionAlphanumericType, int] :return: The new version with the alphanumeric. :rtype: str :raises IncorrectAlphanumeric: The alphanumeric version was incorrectly formatted. """ if "-" not in cls.__version: identifiers: tuple = ( VersionAlphanumericType.ALPHA, VersionAlphanumericType.BETA, VersionAlphanumericType.RELEASE_CANDIDATE, ) amount: int = 0 for key, value in kwargs.items(): if key in identifiers and len(value) == 1: amount += 1 cls.__version = f"{cls.__version}-{key}.{value}" cls.__alphanum = {"type": key, "identifier": int(value)} elif key in identifiers or amount > 1: raise IncorrectAlphanumeric else: continue return cls.__version