Module continuous_delivery_scripts.spdx_report.spdx_package

Definition of an SPDX Package.

Classes

class PackageInfo (metadata: PackageMetadata,
root_dir: pathlib.Path,
source_dir: pathlib.Path,
uuid: str)
Expand source code
@dataclass(frozen=True, order=True)
class PackageInfo:
    """Definition of a project or dependency package.

    Attributes:
        metadata: metadata about an installed package.
        root_dir: project root directory.
        source_dir: directory where package's sources are.
        uuid: unique identifier of the package.
    """

    metadata: PackageMetadata
    root_dir: Path
    source_dir: Path
    uuid: str

Definition of a project or dependency package.

Attributes
-----=
metadata
metadata about an installed package.
root_dir
project root directory.
source_dir
directory where package's sources are.
uuid
unique identifier of the package.

Instance variables

var metadata : PackageMetadata

The type of the None singleton.

var root_dir : pathlib.Path

The type of the None singleton.

var source_dir : pathlib.Path

The type of the None singleton.

var uuid : str

The type of the None singleton.

class SpdxPackage (package_info: PackageInfo,
is_dependency: bool = False)
Expand source code
class SpdxPackage:
    """SPDX package.

    See https://spdx.org/spdx-specification-21-web-version#h.4i7ojhp
    """

    def __init__(self, package_info: PackageInfo, is_dependency: bool = False) -> None:
        """Constructor."""
        self._is_dependency = is_dependency
        self._package_info = package_info
        self._file_list: Optional[List[Path]] = None
        self._actual_licence: Optional[str] = None
        self._main_licence: Optional[str] = None

    @property
    def metadata(self) -> PackageMetadata:
        """Gets the original package metadata and licence evidence."""
        return self._package_info.metadata

    @property
    def files(self) -> Optional[List[Path]]:
        """Gets package's files.

        Returns:
            list of file path or None if a dependency.
        """
        if self._is_dependency:
            return None
        if not self._file_list:
            self._file_list = [p for p in list_project_files_for_licensing(self._package_info.source_dir)]
        return self._file_list

    @property
    def id(self) -> str:
        """Gets Package's identifier.

        Returns:
            An ID
        """
        if not self._is_dependency:
            return self._package_info.uuid
        return self.name if re.fullmatch(r"[A-Za-z0-9.-]+", self.name) else str(generate_uuid_based_on_str(self.name))

    @property
    def is_dependency(self) -> bool:
        """States whether the package is a dependency or not."""
        return self._is_dependency

    @property
    def name(self) -> str:
        """Gets Package's name.

        See https://spdx.org/spdx-specification-21-web-version#h.2xcytpi

        Returns:
            corresponding string
        """
        return str(self._package_info.metadata.name)

    @property
    def version(self) -> str:
        """Gets package's version.

        Returns:
            package version
        """
        return str(self._package_info.metadata.version)

    @property
    def main_licence(self) -> str:
        """Gets the package's official licence.

        Returns:
            project's licence
        """
        if not self._main_licence:
            package_licence = self._package_info.metadata.licence
            try:
                self._main_licence = (
                    cleanse_licence_expression(package_licence) if package_licence else UNKNOWN_LICENCE.identifier
                )
            except ExpressionError:
                self._main_licence = UNKNOWN_LICENCE.identifier
        return self._main_licence

    @property
    def is_main_licence_accepted(self) -> bool:
        """States whether the main licence of the package is part of the accepted licence list."""
        return bool(is_licence_accepted(self.main_licence, self._project_licence_refs))

    @property
    def _project_licence_refs(self) -> List[str]:
        """Allow the project's own proprietary licence without permitting it for dependencies."""
        if not self._is_dependency and LICENSE_REF_PROPRIETARY in self.main_licence:
            return [LICENSE_REF_PROPRIETARY]
        return []

    @property
    def licence(self) -> str:
        """Gets the actual package's licence based on the files it contains.

        Returns:
            project's licence
        """
        if not self._actual_licence:
            files = self.get_spdx_files()
            self._actual_licence = (
                determine_licence_compound(self.main_licence, [f.licence for f in files])
                if files
                else self.main_licence
            )
        return self._actual_licence

    @property
    def is_licence_accepted(self) -> bool:
        """States whether the actual package's licence of the package is part of the accepted licence list."""
        return bool(is_licence_accepted(self.licence, self._project_licence_refs))

    @property
    def author(self) -> str:
        """Gets the document's author.

        Returns:
            document's author
        """
        return str(self._package_info.metadata.author)

    @property
    def author_email(self) -> str:
        """Gets the document author's email.

        Returns:
            document author's email
        """
        return str(self._package_info.metadata.author_email)

    @property
    def url(self) -> str:
        """Gets the package source URL.

        Returns:
            the package homepage
        """
        return str(self._package_info.metadata.url)

    @property
    def description(self) -> str:
        """Gets the package description.

        Returns:
            some description
        """
        return str(self._package_info.metadata.description)

    def get_spdx_files(self) -> Optional[List[SpdxFile]]:
        """Gets package's files SPDX description.

        Returns:
            list of file descriptions or None if a dependency.
        """
        if not self.files:
            return None
        return [SpdxFile(p, self._package_info.root_dir, self.main_licence) for p in self.files]

    def generate_spdx_package(self) -> "Package":
        """Generates the SPDX package.

        Example of a SPDX package:
        PackageName: eduVPN
        DataFormat: SPDXRef-1
        PackageSupplier: Organization: The Commons Conservancy eduVPN Programme
        PackageHomePage: https://eduvpn.org
        PackageLicenseDeclared: GPL-3.0+
        PackageCopyrightText: 2017, The Commons Conservancy eduVPN Programme
        PackageSummary: <text>EduVPN is designed to allow users to connect
        securely and encrypted to the Internet from any standard device.
                        </text>
        PackageComment: <text>The package includes the following libraries; see
        Relationship information.
                        </text>
        Created: 2017-06-06T09:00:00Z
        PackageDownloadLocation: git://github.com/eduVPN/reponame
        PackageDownloadLocation: git+https://github.com/eduVPN/reponame.git
        PackageDownloadLocation: git+ssh://github.com/eduVPN/reponame.git
        Creator: Person: Jane Doe

        Returns:
            the corresponding package
        """
        from spdx_tools.spdx.model.actor import Actor, ActorType
        from spdx_tools.spdx.model.package import Package
        from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion
        from spdx_tools.spdx import spdx_element_utils

        source_files = self.get_spdx_files() or []
        files = [file.generate_spdx_file() for file in source_files]

        package = Package(
            name=self.name,
            spdx_id=f"SPDXRef-{self.id}",
            download_location=SpdxNoAssertion(),
            version=self.version if self.version != UNKNOWN else None,
            file_name=self.name,
            originator=Actor(
                ActorType.PERSON, self.author, self.author_email if self.author_email != UNKNOWN else None
            ),
            files_analyzed=bool(files),
            verification_code=spdx_element_utils.calculate_package_verification_code(files) if files else None,
            copyright_text=SpdxNoAssertion(),
            homepage=self.url if self.url != UNKNOWN else None,
            license_declared=parse_spdx_licence(self.main_licence),
            license_concluded=parse_spdx_licence(self.licence),
            license_info_from_files=[file.license_concluded for file in files],
            summary=self.description if self.description != UNKNOWN else None,
        )
        if files:
            for file in source_files:
                _set_package_copyright(file, package)
        return package

Instance variables

prop author : str
Expand source code
@property
def author(self) -> str:
    """Gets the document's author.

    Returns:
        document's author
    """
    return str(self._package_info.metadata.author)

Gets the document's author.

Returns -----= document's author

prop author_email : str
Expand source code
@property
def author_email(self) -> str:
    """Gets the document author's email.

    Returns:
        document author's email
    """
    return str(self._package_info.metadata.author_email)

Gets the document author's email.

Returns -----= document author's email

prop description : str
Expand source code
@property
def description(self) -> str:
    """Gets the package description.

    Returns:
        some description
    """
    return str(self._package_info.metadata.description)

Gets the package description.

Returns -----= some description

prop files : List[pathlib.Path] | None
Expand source code
@property
def files(self) -> Optional[List[Path]]:
    """Gets package's files.

    Returns:
        list of file path or None if a dependency.
    """
    if self._is_dependency:
        return None
    if not self._file_list:
        self._file_list = [p for p in list_project_files_for_licensing(self._package_info.source_dir)]
    return self._file_list

Gets package's files.

Returns -----= list of file path or None if a dependency.

prop id : str
Expand source code
@property
def id(self) -> str:
    """Gets Package's identifier.

    Returns:
        An ID
    """
    if not self._is_dependency:
        return self._package_info.uuid
    return self.name if re.fullmatch(r"[A-Za-z0-9.-]+", self.name) else str(generate_uuid_based_on_str(self.name))

Gets Package's identifier.

Returns -----= An ID

prop is_dependency : bool
Expand source code
@property
def is_dependency(self) -> bool:
    """States whether the package is a dependency or not."""
    return self._is_dependency

States whether the package is a dependency or not.

prop is_licence_accepted : bool
Expand source code
@property
def is_licence_accepted(self) -> bool:
    """States whether the actual package's licence of the package is part of the accepted licence list."""
    return bool(is_licence_accepted(self.licence, self._project_licence_refs))

States whether the actual package's licence of the package is part of the accepted licence list.

prop is_main_licence_accepted : bool
Expand source code
@property
def is_main_licence_accepted(self) -> bool:
    """States whether the main licence of the package is part of the accepted licence list."""
    return bool(is_licence_accepted(self.main_licence, self._project_licence_refs))

States whether the main licence of the package is part of the accepted licence list.

prop licence : str
Expand source code
@property
def licence(self) -> str:
    """Gets the actual package's licence based on the files it contains.

    Returns:
        project's licence
    """
    if not self._actual_licence:
        files = self.get_spdx_files()
        self._actual_licence = (
            determine_licence_compound(self.main_licence, [f.licence for f in files])
            if files
            else self.main_licence
        )
    return self._actual_licence

Gets the actual package's licence based on the files it contains.

Returns -----= project's licence

prop main_licence : str
Expand source code
@property
def main_licence(self) -> str:
    """Gets the package's official licence.

    Returns:
        project's licence
    """
    if not self._main_licence:
        package_licence = self._package_info.metadata.licence
        try:
            self._main_licence = (
                cleanse_licence_expression(package_licence) if package_licence else UNKNOWN_LICENCE.identifier
            )
        except ExpressionError:
            self._main_licence = UNKNOWN_LICENCE.identifier
    return self._main_licence

Gets the package's official licence.

Returns -----= project's licence

prop metadata : PackageMetadata
Expand source code
@property
def metadata(self) -> PackageMetadata:
    """Gets the original package metadata and licence evidence."""
    return self._package_info.metadata

Gets the original package metadata and licence evidence.

prop name : str
Expand source code
@property
def name(self) -> str:
    """Gets Package's name.

    See https://spdx.org/spdx-specification-21-web-version#h.2xcytpi

    Returns:
        corresponding string
    """
    return str(self._package_info.metadata.name)

Gets Package's name.

See https://spdx.org/spdx-specification-21-web-version#h.2xcytpi

Returns -----= corresponding string

prop url : str
Expand source code
@property
def url(self) -> str:
    """Gets the package source URL.

    Returns:
        the package homepage
    """
    return str(self._package_info.metadata.url)

Gets the package source URL.

Returns -----= the package homepage

prop version : str
Expand source code
@property
def version(self) -> str:
    """Gets package's version.

    Returns:
        package version
    """
    return str(self._package_info.metadata.version)

Gets package's version.

Returns -----= package version

Methods

def generate_spdx_package(self) ‑> Package
Expand source code
def generate_spdx_package(self) -> "Package":
    """Generates the SPDX package.

    Example of a SPDX package:
    PackageName: eduVPN
    DataFormat: SPDXRef-1
    PackageSupplier: Organization: The Commons Conservancy eduVPN Programme
    PackageHomePage: https://eduvpn.org
    PackageLicenseDeclared: GPL-3.0+
    PackageCopyrightText: 2017, The Commons Conservancy eduVPN Programme
    PackageSummary: <text>EduVPN is designed to allow users to connect
    securely and encrypted to the Internet from any standard device.
                    </text>
    PackageComment: <text>The package includes the following libraries; see
    Relationship information.
                    </text>
    Created: 2017-06-06T09:00:00Z
    PackageDownloadLocation: git://github.com/eduVPN/reponame
    PackageDownloadLocation: git+https://github.com/eduVPN/reponame.git
    PackageDownloadLocation: git+ssh://github.com/eduVPN/reponame.git
    Creator: Person: Jane Doe

    Returns:
        the corresponding package
    """
    from spdx_tools.spdx.model.actor import Actor, ActorType
    from spdx_tools.spdx.model.package import Package
    from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion
    from spdx_tools.spdx import spdx_element_utils

    source_files = self.get_spdx_files() or []
    files = [file.generate_spdx_file() for file in source_files]

    package = Package(
        name=self.name,
        spdx_id=f"SPDXRef-{self.id}",
        download_location=SpdxNoAssertion(),
        version=self.version if self.version != UNKNOWN else None,
        file_name=self.name,
        originator=Actor(
            ActorType.PERSON, self.author, self.author_email if self.author_email != UNKNOWN else None
        ),
        files_analyzed=bool(files),
        verification_code=spdx_element_utils.calculate_package_verification_code(files) if files else None,
        copyright_text=SpdxNoAssertion(),
        homepage=self.url if self.url != UNKNOWN else None,
        license_declared=parse_spdx_licence(self.main_licence),
        license_concluded=parse_spdx_licence(self.licence),
        license_info_from_files=[file.license_concluded for file in files],
        summary=self.description if self.description != UNKNOWN else None,
    )
    if files:
        for file in source_files:
            _set_package_copyright(file, package)
    return package

Generates the SPDX package.

Example of a SPDX package: PackageName: eduVPN DataFormat: SPDXRef-1 PackageSupplier: Organization: The Commons Conservancy eduVPN Programme PackageHomePage: https://eduvpn.org PackageLicenseDeclared: GPL-3.0+ PackageCopyrightText: 2017, The Commons Conservancy eduVPN Programme PackageSummary: EduVPN is designed to allow users to connect securely and encrypted to the Internet from any standard device. PackageComment: The package includes the following libraries; see Relationship information. Created: 2017-06-06T09:00:00Z PackageDownloadLocation: git://github.com/eduVPN/reponame PackageDownloadLocation: git+https://github.com/eduVPN/reponame.git PackageDownloadLocation: git+ssh://github.com/eduVPN/reponame.git Creator: Person: Jane Doe

Returns -----= the corresponding package

def get_spdx_files(self) ‑> List[SpdxFile] | None
Expand source code
def get_spdx_files(self) -> Optional[List[SpdxFile]]:
    """Gets package's files SPDX description.

    Returns:
        list of file descriptions or None if a dependency.
    """
    if not self.files:
        return None
    return [SpdxFile(p, self._package_info.root_dir, self.main_licence) for p in self.files]

Gets package's files SPDX description.

Returns -----= list of file descriptions or None if a dependency.