Module continuous_delivery_scripts.spdx_report.spdx_helpers
Facilities regarding SPDX.
SPDX file (i.e. tag-value format) https://github.com/OpenChain-Project/curriculum/blob/master/guides/including_license_info.rst https://github.com/david-a-wheeler/spdx-tutorial#spdx-files https://github.com/OpenChain-Project/curriculum/blob/master/guides/reusing_software.md https://github.com/vmware/tern/blob/c9a0c83369b92df58f7f80842aa15da5f63ed983/docs/spdx-tag-value-overview.md
Examples -----= - https://spdx.org/spdx-tagvalue-example - https://github.com/spdx/tools/blob/master/Examples/SPDXTagExample-v2.1.spdx
Functions
def determine_checked_packages_from_configuration_entry(checked_packages: Any) ‑> dict-
Expand source code
def determine_checked_packages_from_configuration_entry(checked_packages: Any) -> dict: """Determines the list of packages for which the licence has been manually checked.""" if isinstance(checked_packages, str): checked_packages = checked_packages.split(", ") if isinstance(checked_packages, (list, tuple, set)): return _convert_list_into_dict(checked_packages) if isinstance(checked_packages, dict): return checked_packages return dict()Determines the list of packages for which the licence has been manually checked.
def determine_file_copyright_text(path: pathlib.Path) ‑> str | None-
Expand source code
def determine_file_copyright_text(path: Path) -> Optional[str]: """Determines the copyright text of a file.""" match = scan_file_for_pattern(path, COPYRIGHT_REGEX_PATTERN) if not match: return None return str(match.group(0).strip())Determines the copyright text of a file.
def determine_file_licence(path: pathlib.Path) ‑> str | None-
Expand source code
def determine_file_licence(path: Path) -> Optional[str]: """Determines the licence of a file based on the SPDX identifier.""" licence = None try: match = scan_file_for_pattern(path, SPDX_IDENTIFIER_REGEX_PATTERN) if not match: return None licence = match.group(1).strip() return str(simplify_licence_expression(licence)) except UnicodeDecodeError as e: logger.warning( "Could not screen file [%s] for an embedded SPDX licence identifier because it appears to be binary. " "Binary files cannot be screened for inline licence metadata.", path, ) logger.info("Binary screening failure for [%s]: %s", path, e) return None except Exception as e: logger.error(f"Could not determine the licence of file [{path}] from identifier '{licence}'. Reason: {e}.") return NoneDetermines the licence of a file based on the SPDX identifier.
def determine_spdx_value(value: str | None) ‑> str | UnKnown | SPDXNone-
Expand source code
def determine_spdx_value(value: Optional[str]) -> Union[str, UnKnown, SPDXNone]: """Determines the correct SPDX value. Args: value: a value Returns: correct SPDX value a string, UnKnown or SPDXNone """ if not value: return SPDXNone() if value == UNKNOWN: return UnKnown() return valueDetermines the correct SPDX value.
- Args
- -----=
value- a value
Returns -----= correct SPDX value a string, UnKnown or SPDXNone
def get_package_manual_check(package_name: str) ‑> Tuple[bool, str | None]-
Expand source code
def get_package_manual_check(package_name: str) -> Tuple[bool, Optional[str]]: """Return whether a licence was checked and the recorded explanation.""" record = get_package_manual_record(package_name) return record.checked, record.reasonReturn whether a licence was checked and the recorded explanation.
def get_package_manual_licence(package_name: str) ‑> str | None-
Expand source code
def get_package_manual_licence(package_name: str) -> Optional[str]: """Return the manually verified licence candidate, distinct from prose.""" return get_package_manual_record(package_name).licenceReturn the manually verified licence candidate, distinct from prose.
def get_package_manual_record(package_name: str) ‑> ManualLicenceCheck-
Expand source code
def get_package_manual_record(package_name: str) -> ManualLicenceCheck: """Parse a flat or structured manual licence entry once into a model.""" checked_packages = get_packages_with_checked_licence() name = package_name.strip() if name not in checked_packages: name = name.replace(".", "-") checked = name in checked_packages entry = checked_packages.get(name) record = ManualLicenceCheck(checked=checked) if isinstance(entry, dict): record.licence = entry.get("licence") record.reason = entry.get("reason") or record.licence elif isinstance(entry, str): record.licence = entry record.reason = entry return recordParse a flat or structured manual licence entry once into a model.
def get_packages_with_checked_licence() ‑> dict-
Expand source code
def get_packages_with_checked_licence() -> dict: """Determines the list of packages for which the licence has been checked from configuration.""" return determine_checked_packages_from_configuration_entry( configuration.get_value(ConfigurationVariable.PACKAGES_WITH_CHECKED_LICENCE) )Determines the list of packages for which the licence has been checked from configuration.
def get_project_namespace(project_config_path: pathlib.Path, document_name: str) ‑> str-
Expand source code
def get_project_namespace(project_config_path: Path, document_name: str) -> str: """Determines the project namespace from configuration.""" with open(str(project_config_path), "r", encoding="utf8") as f: config = toml.load(f).get(THIRD_PARTY_CONFIG_NAMESPACE, dict()) protocol = "http://" path_part = f"{config.get('CreatorWebsite')}/{config.get('PathToSpdx')}" name_part = f"{document_name}-{config.get('UUID')}" return f"{protocol}{path_part}/{name_part}"Determines the project namespace from configuration.
def is_package_licence_manually_checked(package_name: str) ‑> bool-
Expand source code
def is_package_licence_manually_checked(package_name: str) -> bool: """States whether the licence of a package has been manually checked and hence, that its licence is compliant.""" checked, _ = get_package_manual_check(package_name) if not checked: checked, _ = get_package_manual_check(package_name.replace(".", "-")) return checkedStates whether the licence of a package has been manually checked and hence, that its licence is compliant.
def list_project_files_for_licensing(project_root: pathlib.Path) ‑> Iterator[pathlib.Path]-
Expand source code
def list_project_files_for_licensing(project_root: Path) -> Iterator[Path]: """Gets a generator over all the project's files needing licensing.""" def ignore_path(p: Path) -> bool: return True if p.name.startswith(".") else should_exclude_path(p, PATHS_TO_EXCLUDE) for path in list_all_files(project_root, ignore_path): yield pathGets a generator over all the project's files needing licensing.
def parse_spdx_licence(licence: str) ‑> Expression | SpdxNoAssertion | ModelSpdxNone-
Expand source code
def parse_spdx_licence(licence: str) -> Union["Expression", "SpdxNoAssertion", "ModelSpdxNone"]: """Convert a project licence expression to the SPDX SDK's model. An unknown licence in the audit is not an SPDX licence identifier. It is represented as NOASSERTION in the SPDX document instead. """ from license_expression import get_spdx_licensing from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion from spdx_tools.spdx.model.spdx_none import SpdxNone if not licence or licence.upper() in ("UNKNOWN", "NOASSERTION"): return SpdxNoAssertion() if licence.upper() == "NONE": return SpdxNone() return cast("Expression", get_spdx_licensing().parse(licence))Convert a project licence expression to the SPDX SDK's model.
An unknown licence in the audit is not an SPDX licence identifier. It is represented as NOASSERTION in the SPDX document instead.
Classes
class ManualLicenceCheck (checked: bool = False)-
Expand source code
@dataclass class ManualLicenceCheck: """A project's manually checked licence and its separate explanation.""" checked: bool = False _licence: Optional[str] = None _reason: Optional[str] = None @property def licence(self) -> Optional[str]: """Get the licence proposed for assessment, if supplied.""" return self._licence @licence.setter def licence(self, value: Optional[str]) -> None: """Set the manually verified licence candidate.""" if value is not None and not isinstance(value, str): raise ValueError("A manually checked licence must be text") self._licence = value @property def reason(self) -> Optional[str]: """Get the recorded explanation for the licence-policy check.""" return self._reason @reason.setter def reason(self, value: Optional[str]) -> None: """Set the manually recorded review explanation.""" if value is not None and not isinstance(value, str): raise ValueError("A manual licence review reason must be text") self._reason = valueA project's manually checked licence and its separate explanation.
Instance variables
var checked : bool-
The type of the None singleton.
prop licence : str | None-
Expand source code
@property def licence(self) -> Optional[str]: """Get the licence proposed for assessment, if supplied.""" return self._licenceGet the licence proposed for assessment, if supplied.
prop reason : str | None-
Expand source code
@property def reason(self) -> Optional[str]: """Get the recorded explanation for the licence-policy check.""" return self._reasonGet the recorded explanation for the licence-policy check.
class SPDXNone-
Expand source code
class SPDXNone(object): """Represent SPDX NONE value without importing spdx-tools.""" def to_value(self) -> str: """Return the SPDX serialised value.""" return "NONE" def __str__(self) -> str: """Return the SPDX serialised value as text.""" return self.to_value()Represent SPDX NONE value without importing spdx-tools.
Methods
def to_value(self) ‑> str-
Expand source code
def to_value(self) -> str: """Return the SPDX serialised value.""" return "NONE"Return the SPDX serialised value.
class UnKnown-
Expand source code
class UnKnown(object): """Represent SPDX UNKNOWN value without importing spdx-tools.""" def to_value(self) -> str: """Return the SPDX serialised value.""" return "UNKNOWN" def __str__(self) -> str: """Return the SPDX serialised value as text.""" return self.to_value()Represent SPDX UNKNOWN value without importing spdx-tools.
Methods
def to_value(self) ‑> str-
Expand source code
def to_value(self) -> str: """Return the SPDX serialised value.""" return "UNKNOWN"Return the SPDX serialised value.