Source code for pkgcheck.checks.header

"""Various file-based header checks."""

import re

from .. import results, sources
from . import GentooRepoCheck

copyright_regex = re.compile(r"^# Copyright (?P<begin>\d{4}-)?(?P<end>\d{4}) (?P<holder>.+)$")


class _FileHeaderResult(results.Result):
    """Generic file header result."""

    def __init__(self, line, **kwargs):
        super().__init__(**kwargs)
        self.line = line


[docs] class InvalidCopyright(_FileHeaderResult, results.AliasResult, results.Error): """File with invalid copyright. The file does not start with a valid copyright line. Each ebuild or eclass file must start with a copyright line of the form:: # Copyright YEARS MAIN-CONTRIBUTOR [OTHER-CONTRIBUTOR]... [and others] Files in the Gentoo repository must use:: # Copyright YEARS Gentoo Authors """ _name = "InvalidCopyright" @property def desc(self): return f"invalid copyright: {self.line!r}"
[docs] class OldGentooCopyright(_FileHeaderResult, results.AliasResult, results.Warning): """File with old Gentoo Foundation copyright. The file still assigns copyright to the Gentoo Foundation even though it has been committed after the new copyright policy was approved (2018-10-21). Ebuilds and eclasses in Gentoo repository must use 'Gentoo Authors' instead. Files in other repositories may specify an explicit copyright holder instead. """ _name = "OldGentooCopyright" @property def desc(self): return f'old copyright, update to "Gentoo Authors": {self.line!r}'
[docs] class NonGentooAuthorsCopyright(_FileHeaderResult, results.AliasResult, results.Error): """File with copyright stating owner other than "Gentoo Authors". The file specifies explicit copyright owner, while the Gentoo repository policy specifies that all ebuilds and eclasses must use "Gentoo Authors". If the owner is not listed in metadata/AUTHORS, addition can be requested via bugs.gentoo.org. """ _name = "NonGentooAuthorsCopyright" @property def desc(self): return f'copyright line must state "Gentoo Authors": {self.line!r}'
[docs] class InvalidLicenseHeader(_FileHeaderResult, results.AliasResult, results.Error): """File with invalid license header. The file does not have with a valid license header. Ebuilds and eclasses in the Gentoo repository must use:: # Distributed under the terms of the GNU General Public License v2 """ _name = "InvalidLicenseHeader" @property def desc(self): if self.line: return f"invalid license header: {self.line!r}" return "missing license header"
class _HeaderCheck(GentooRepoCheck): """Scan files for incorrect copyright/license headers.""" _invalid_copyright = InvalidCopyright _old_copyright = OldGentooCopyright _non_gentoo_authors = NonGentooAuthorsCopyright _invalid_license = InvalidLicenseHeader known_results = frozenset( [ _invalid_copyright, _old_copyright, _non_gentoo_authors, _invalid_license, ] ) _item_attr = "pkg" license_header = "# Distributed under the terms of the GNU General Public License v2" def args(self, item): return {self._item_attr: item} def feed(self, item): if item.lines: line = item.lines[0].strip() if mo := copyright_regex.match(line): # Copyright policy is active since 2018-10-21, so it applies # to all ebuilds committed in 2019 and later if int(mo.group("end")) >= 2019: if mo.group("holder") == "Gentoo Foundation": yield self._old_copyright(line, **self.args(item)) # Gentoo policy requires 'Gentoo Authors' elif mo.group("holder") != "Gentoo Authors": yield self._non_gentoo_authors(line, **self.args(item)) else: yield self._invalid_copyright(line, **self.args(item)) try: line = item.lines[1].strip("\n") except IndexError: line = "" if line != self.license_header: yield self._invalid_license(line, **self.args(item))
[docs] class EbuildInvalidCopyright(InvalidCopyright, results.VersionResult): __doc__ = InvalidCopyright.__doc__
[docs] class EbuildOldGentooCopyright(OldGentooCopyright, results.VersionResult): __doc__ = OldGentooCopyright.__doc__
[docs] class EbuildNonGentooAuthorsCopyright(NonGentooAuthorsCopyright, results.VersionResult): __doc__ = NonGentooAuthorsCopyright.__doc__
[docs] class EbuildInvalidLicenseHeader(InvalidLicenseHeader, results.VersionResult): __doc__ = InvalidLicenseHeader.__doc__
[docs] class EbuildHeaderCheck(_HeaderCheck): """Scan ebuild for incorrect copyright/license headers.""" _source = sources.EbuildFileRepoSource _invalid_copyright = EbuildInvalidCopyright _old_copyright = EbuildOldGentooCopyright _non_gentoo_authors = EbuildNonGentooAuthorsCopyright _invalid_license = EbuildInvalidLicenseHeader known_results = frozenset( [ _invalid_copyright, _old_copyright, _non_gentoo_authors, _invalid_license, ] ) _item_attr = "pkg"
[docs] class EclassInvalidCopyright(InvalidCopyright, results.EclassResult): __doc__ = InvalidCopyright.__doc__ @property def desc(self): return f"{self.eclass}: {super().desc}"
[docs] class EclassOldGentooCopyright(OldGentooCopyright, results.EclassResult): __doc__ = OldGentooCopyright.__doc__ @property def desc(self): return f"{self.eclass}: {super().desc}"
[docs] class EclassNonGentooAuthorsCopyright(NonGentooAuthorsCopyright, results.EclassResult): __doc__ = NonGentooAuthorsCopyright.__doc__ @property def desc(self): return f"{self.eclass}: {super().desc}"
[docs] class EclassInvalidLicenseHeader(InvalidLicenseHeader, results.EclassResult): __doc__ = InvalidLicenseHeader.__doc__ @property def desc(self): return f"{self.eclass}: {super().desc}"
[docs] class EclassHeaderCheck(_HeaderCheck): """Scan eclasses for incorrect copyright/license headers.""" _source = sources.EclassRepoSource _invalid_copyright = EclassInvalidCopyright _old_copyright = EclassOldGentooCopyright _non_gentoo_authors = EclassNonGentooAuthorsCopyright _invalid_license = EclassInvalidLicenseHeader known_results = frozenset( [ _invalid_copyright, _old_copyright, _non_gentoo_authors, _invalid_license, ] ) _item_attr = "eclass"