# SPDX-FileCopyrightText: 2019 Free Software Foundation Europe e.V. <https://fsfe.org># SPDX-FileCopyrightText: 2023 Nico Rikken <nico.rikken@fsfe.org>## SPDX-License-Identifier: GPL-3.0-or-later"""Functions for downloading license files from spdx/license-list-data."""importerrnoimportloggingimportosimportshutilimporturllib.requestfrompathlibimportPathfromtypingimportOptionalfromurllib.errorimportURLErrorfromurllib.parseimporturljoinfrom._utilimportfind_licenses_directoryfrom.extractimport_LICENSEREF_PATTERNfrom.projectimportProjectfrom.typesimportStrPathfrom.vcsimportVCSStrategyNone_LOGGER=logging.getLogger(__name__)# All raw text files are available as files underneath this path._SPDX_REPOSITORY_BASE_URL=("https://raw.githubusercontent.com/spdx/license-list-data/master/text/")
[docs]defdownload_license(spdx_identifier:str)->str:"""Download the license text from the SPDX repository. Args: spdx_identifier: SPDX identifier of the license. Raises: URLError: if the license could not be downloaded. Returns: The license text. """# This is fairly naive, but I can't see anything wrong with it.url=urljoin(_SPDX_REPOSITORY_BASE_URL,"".join((spdx_identifier,".txt")))_LOGGER.debug("downloading license from '%s'",url)# TODO: Cache result?withurllib.request.urlopen(url)asresponse:ifresponse.getcode()==200:returnresponse.read().decode("utf-8")raiseURLError("Status code was not 200")
[docs]defput_license_in_file(spdx_identifier:str,destination:StrPath,source:Optional[StrPath]=None,)->None:"""Download a license and put it in the destination file. This function exists solely for convenience. Args: spdx_identifier: SPDX License Identifier of the license. destination: Where to put the license. source: Path to file or directory containing the text for LicenseRef licenses. Raises: URLError: if the license could not be downloaded. FileExistsError: if the license file already exists. FileNotFoundError: if the source could not be found in the directory. """header=""destination=Path(destination)destination.parent.mkdir(exist_ok=True)ifdestination.exists():raiseFileExistsError(errno.EEXIST,os.strerror(errno.EEXIST),str(destination))# LicenseRef- license; don't download anything.if_LICENSEREF_PATTERN.match(spdx_identifier):ifsource:source=Path(source)ifsource.is_dir():source=source/f"{spdx_identifier}.txt"ifnotsource.exists():raiseFileNotFoundError(errno.ENOENT,os.strerror(errno.ENOENT),str(source))shutil.copyfile(source,destination)else:destination.touch()else:text=download_license(spdx_identifier)withdestination.open("w",encoding="utf-8")asfp:fp.write(header)fp.write(text)