Module continuous_delivery_scripts.utils.third_party_licences
Third party licences.
Functions
def cleanse_licence_descriptor(licence_descriptor: str) ‑> str-
Expand source code
def cleanse_licence_descriptor(licence_descriptor: str) -> str: """Cleanses the licence descriptor to only keep words describing the licence.""" cleansed_descriptor = licence_descriptor.strip() cleansed_descriptor = re.sub(r"OSI\s?[Aa]pproved[\:]*", "", cleansed_descriptor) cleansed_descriptor = re.sub(r"[pP]ublic [dD]omain", "", cleansed_descriptor) cleansed_descriptor = re.sub(r"BSD[-\s][Ll]ike", "BSD", cleansed_descriptor) cleansed_descriptor = re.sub(r"BSD [lL]icen[sc]e", "BSD", cleansed_descriptor) cleansed_descriptor = re.sub(r"MIT [lL]icen[sc]e", "MIT", cleansed_descriptor) cleansed_descriptor = _handle_special_licence_entries(cleansed_descriptor.strip()) if cleansed_descriptor.lower().startswith("the"): cleansed_descriptor = cleansed_descriptor[3:].strip() return cleansed_descriptorCleanses the licence descriptor to only keep words describing the licence.
def cleanse_licence_expression(licence_expression: str) ‑> str-
Expand source code
def cleanse_licence_expression(licence_expression: str) -> str: """Cleanses a licence expression by using SPDX identifiers when possible. A licence expression can be a combination of licences and in a lot of cases is free-form text. The idea is to return an equivalent expression but using SPDX identifiers when possible. """ simplified_expression = _parse_licence_expression( Licensing(), normalise_proprietary_licence(licence_expression) ).simplify() for s in simplified_expression.symbols: if isinstance(s, LicenseWithExceptionSymbol): # An exception changes the obligations: do not treat it as the base licence. continue if s.key.startswith("LicenseRef-"): continue corresponding_licence = OPENSOURCE_LICENCES.get_licence(s.key) if corresponding_licence: s.key = corresponding_licence.identifier return simplify_licence_expression(str(simplified_expression))Cleanses a licence expression by using SPDX identifiers when possible.
A licence expression can be a combination of licences and in a lot of cases is free-form text. The idea is to return an equivalent expression but using SPDX identifiers when possible.
def determine_allowed_opensource_licences_from_string(allowed_licences: Any) ‑> Iterable[Licence]-
Expand source code
def determine_allowed_opensource_licences_from_string( allowed_licences: Any, ) -> Iterable[Licence]: """Determines all the third party licences allowed as set in the input parameter.""" if isinstance(allowed_licences, str): allowed_licences = allowed_licences.split(", ") if isinstance(allowed_licences, (list, dict, tuple, set)): yield from _retrieve_licences_from_identifier_list(allowed_licences)Determines all the third party licences allowed as set in the input parameter.
def determine_licence_compound(main_licence: str, additional_licences: List[str]) ‑> str-
Expand source code
def determine_licence_compound(main_licence: str, additional_licences: List[str]) -> str: """Determines the overall licence based on main licence and additional licences.""" overall_licence = f"({main_licence}) AND ({') AND ('.join(additional_licences)})" return str(_parse_licence_expression(Licensing(), overall_licence).simplify())Determines the overall licence based on main licence and additional licences.
def determine_licences_not_in_list(licence_expression: str, licence_list: Iterator[str]) ‑> Iterator[str]-
Expand source code
def determine_licences_not_in_list(licence_expression: str, licence_list: Iterator[str]) -> Iterator[str]: """Determines all the licences in an expression which are not in list.""" licensing_util = Licensing() licence_keys = licensing_util.license_keys(_parse_licence_expression(licensing_util, licence_expression)) for licence in licence_keys: if licence not in licence_list: yield licenceDetermines all the licences in an expression which are not in list.
def determine_whether_licence_expression_is_compliant(licence_expression: str, licence_list: list) ‑> bool-
Expand source code
def determine_whether_licence_expression_is_compliant(licence_expression: str, licence_list: list) -> bool: """Checks whether an expression is compliant with a list of licences.""" licensing_util = Licensing() for licence in licence_list: if licensing_util.contains(licence_expression, licence): return True return FalseChecks whether an expression is compliant with a list of licences.
def get_allowed_opensource_licences() ‑> Iterable[Licence]-
Expand source code
def get_allowed_opensource_licences() -> Iterable[Licence]: """Determines all the third party licences allowed for a given project.""" yield from determine_allowed_opensource_licences_from_string( configuration.get_value(ConfigurationVariable.ACCEPTED_THIRD_PARTY_LICENCES) )Determines all the third party licences allowed for a given project.
def is_licence_accepted(licence_expression: str, additional_identifiers: Iterable[str] = ()) ‑> bool-
Expand source code
def is_licence_accepted(licence_expression: str, additional_identifiers: Iterable[str] = ()) -> bool: """Determines whether the licence expressed is valid with regards to project's accepted licences.""" authorised_licences = [licence.identifier for licence in get_allowed_opensource_licences()] authorised_licences.extend(additional_identifiers) is_or = _is_expression_or(licence_expression) if bool([licence for licence in determine_licences_not_in_list(licence_expression, iter(authorised_licences))]): return ( determine_whether_licence_expression_is_compliant(licence_expression, authorised_licences) if is_or else False ) return TrueDetermines whether the licence expressed is valid with regards to project's accepted licences.
def is_proprietary_licence(licence_expression: str) ‑> bool-
Expand source code
def is_proprietary_licence(licence_expression: str) -> bool: """Return whether a licence declaration resolves to the proprietary SPDX reference.""" return normalise_proprietary_licence(licence_expression.strip()) == LICENSE_REF_PROPRIETARYReturn whether a licence declaration resolves to the proprietary SPDX reference.
def iter_licenses(licence_info: dict) ‑> Iterable[Licence]-
Expand source code
def iter_licenses(licence_info: dict) -> Iterable[Licence]: """Gets a generator over all the licences present in licenses.json.""" licences = cast(Iterable[dict], licence_info.get("licenses", [])) for licence_info in licences: yield parse_licence(licence_info)Gets a generator over all the licences present in licenses.json.
def normalise_proprietary_licence(licence_expression: str) ‑> str-
Expand source code
def normalise_proprietary_licence(licence_expression: str) -> str: """Use a stable SPDX licence reference for proprietary declarations.""" return re.sub( r"(?<![\w-])(?:LicenseRef-)?Proprietary(?:\s+Licen[cs]e)?(?![\w-])", LICENSE_REF_PROPRIETARY, licence_expression, flags=re.IGNORECASE, )Use a stable SPDX licence reference for proprietary declarations.
def parse_licence(licence_info: dict) ‑> Licence-
Expand source code
def parse_licence(licence_info: dict) -> Licence: """Parses a licence entry in the Json file and translates it into a licence object.""" return Licence( reference_number=licence_info.get("referenceNumber", ""), identifier=licence_info.get("licenseId", ""), name=licence_info.get("name", ""), url=licence_info.get("detailsUrl", ""), reference=licence_info.get("reference", ""), is_deprecated=bool(licence_info.get("isDeprecatedLicenseId", False)), is_osi_approved=bool(licence_info.get("isOsiApproved", True)), )Parses a licence entry in the Json file and translates it into a licence object.
def simplify_licence_expression(licence_expression: str) ‑> str-
Expand source code
def simplify_licence_expression(licence_expression: str) -> str: """Simplifies a licence expression.""" return str(_parse_licence_expression(Licensing(), normalise_proprietary_licence(licence_expression)).simplify())Simplifies a licence expression.
Classes
class Licence (reference_number: str,
identifier: str,
name: str,
is_deprecated: bool,
is_osi_approved: bool,
url: str,
reference: str)-
Expand source code
@dataclass(order=True, frozen=True) class Licence: """Licence descriptor. Maps to what is defined in licenses.json in https://github.com/spdx/license-list-data/blob/master/json/licenses.json """ reference_number: str identifier: str name: str is_deprecated: bool is_osi_approved: bool url: str reference: strLicence descriptor.
Maps to what is defined in licenses.json in https://github.com/spdx/license-list-data/blob/master/json/licenses.json
Instance variables
var identifier : str-
The type of the None singleton.
var is_deprecated : bool-
The type of the None singleton.
var is_osi_approved : bool-
The type of the None singleton.
var name : str-
The type of the None singleton.
var reference : str-
The type of the None singleton.
var reference_number : str-
The type of the None singleton.
var url : str-
The type of the None singleton.
class OpenSourceLicences-
Expand source code
class OpenSourceLicences: """All the opensource licences known.""" def __init__(self) -> None: """Initialiser.""" self._licence_store: Optional[dict] = None self._licence_list: Optional[list] = None def _store_licence(self, licence: Licence, aliases: Iterable[str] = ()) -> None: if not self._licence_store or self._licence_list is None: return entries = [licence.identifier, licence.name, *aliases] for entry in entries: if not entry: continue self._licence_store[entry] = licence self._licence_list.append(entry) def load(self) -> None: """Loads licence data from internal Json file.""" if self._licence_list and self._licence_store: return self._licence_store = {UNKNOWN_LICENCE.identifier: UNKNOWN_LICENCE} self._licence_list = [UNKNOWN_LICENCE.identifier] try: with open(_get_spdx_licenses_path(), "r", encoding="utf8") as f: for licence in iter_licenses(json.load(f)): self._store_licence(licence) return except (FileNotFoundError, ModuleNotFoundError): pass for licence, aliases in _iter_fallback_licences(): self._store_licence(licence, aliases) def get_licences_from_pattern(self, licence_descriptor_pattern: Pattern) -> Optional[List[Licence]]: """Determines all the licences following a certain pattern.""" self.load() if not self._licence_store or not self._licence_list: return None matching_licences = [licence for licence in self._licence_list if licence_descriptor_pattern.match(licence)] return ( [cast(Licence, self._licence_store.get(licence)) for licence in matching_licences] if matching_licences else None ) def get_licence(self, licence_descriptor: Optional[str], allow_fuzzy: bool = True) -> Optional[Licence]: """Determines a licence from its identifier or name, optionally without approximate matching.""" if licence_descriptor and normalise_proprietary_licence(licence_descriptor) == LICENSE_REF_PROPRIETARY: return PROPRIETARY_LICENCE if licence_descriptor and licence_descriptor.lower().startswith("licenseref-"): return None self.load() if not self._licence_store or not self._licence_list or not licence_descriptor: return None cleansed_descriptor = cleanse_licence_descriptor(licence_descriptor) exact_match = self._licence_store.get(cleansed_descriptor) if exact_match: return cast(Licence, exact_match) normalised_map: Dict[str, Licence] = {} for name in self._licence_list: licence = cast(Licence, self._licence_store.get(name)) if licence: normalised_map[_normalise_licence_text(name)] = licence normalised_descriptor = _normalise_licence_text(cleansed_descriptor) normalised_exact_match = normalised_map.get(normalised_descriptor) if normalised_exact_match: return normalised_exact_match if not allow_fuzzy: return None likelihood, matched_key = determine_similar_string_from_list(normalised_descriptor, normalised_map.keys()) return normalised_map.get(matched_key) if likelihood > LICENCE_LIKELIHOOD_THRESHOLD else NoneAll the opensource licences known.
Initialiser.
Methods
def get_licence(self, licence_descriptor: str | None, allow_fuzzy: bool = True) ‑> Licence | None-
Expand source code
def get_licence(self, licence_descriptor: Optional[str], allow_fuzzy: bool = True) -> Optional[Licence]: """Determines a licence from its identifier or name, optionally without approximate matching.""" if licence_descriptor and normalise_proprietary_licence(licence_descriptor) == LICENSE_REF_PROPRIETARY: return PROPRIETARY_LICENCE if licence_descriptor and licence_descriptor.lower().startswith("licenseref-"): return None self.load() if not self._licence_store or not self._licence_list or not licence_descriptor: return None cleansed_descriptor = cleanse_licence_descriptor(licence_descriptor) exact_match = self._licence_store.get(cleansed_descriptor) if exact_match: return cast(Licence, exact_match) normalised_map: Dict[str, Licence] = {} for name in self._licence_list: licence = cast(Licence, self._licence_store.get(name)) if licence: normalised_map[_normalise_licence_text(name)] = licence normalised_descriptor = _normalise_licence_text(cleansed_descriptor) normalised_exact_match = normalised_map.get(normalised_descriptor) if normalised_exact_match: return normalised_exact_match if not allow_fuzzy: return None likelihood, matched_key = determine_similar_string_from_list(normalised_descriptor, normalised_map.keys()) return normalised_map.get(matched_key) if likelihood > LICENCE_LIKELIHOOD_THRESHOLD else NoneDetermines a licence from its identifier or name, optionally without approximate matching.
def get_licences_from_pattern(self, licence_descriptor_pattern: Pattern) ‑> List[Licence] | None-
Expand source code
def get_licences_from_pattern(self, licence_descriptor_pattern: Pattern) -> Optional[List[Licence]]: """Determines all the licences following a certain pattern.""" self.load() if not self._licence_store or not self._licence_list: return None matching_licences = [licence for licence in self._licence_list if licence_descriptor_pattern.match(licence)] return ( [cast(Licence, self._licence_store.get(licence)) for licence in matching_licences] if matching_licences else None )Determines all the licences following a certain pattern.
def load(self) ‑> None-
Expand source code
def load(self) -> None: """Loads licence data from internal Json file.""" if self._licence_list and self._licence_store: return self._licence_store = {UNKNOWN_LICENCE.identifier: UNKNOWN_LICENCE} self._licence_list = [UNKNOWN_LICENCE.identifier] try: with open(_get_spdx_licenses_path(), "r", encoding="utf8") as f: for licence in iter_licenses(json.load(f)): self._store_licence(licence) return except (FileNotFoundError, ModuleNotFoundError): pass for licence, aliases in _iter_fallback_licences(): self._store_licence(licence, aliases)Loads licence data from internal Json file.