"""Assemble THIRD_PARTY_LICENSES.txt for a build: every bundled component, its version, license, source URL and full license text. Texts come from the installed wheels or from tools/licenses/ (copies of the texts at the URLs listed in tools/licenses/SOURCES.txt, so the build needs no network). python tools/collect_licenses.py OUT_FILE """ import importlib.metadata as md import os import sys ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) LICENSES = os.path.join(ROOT, "tools", "licenses") def license_text(name): return open(os.path.join(LICENSES, name), encoding="utf-8", errors="replace").read() def dist_file(dist, *names): try: files = md.distribution(dist).files or [] except md.PackageNotFoundError: return "" for f in files: if os.path.basename(str(f)) in names: return open(f.locate(), encoding="utf-8", errors="replace").read() return "" def ver(dist): try: return md.version(dist) except md.PackageNotFoundError: return "?" def site_file(*parts): import soundfile p = os.path.join(os.path.dirname(soundfile.__file__), *parts) return open(p, encoding="utf-8", errors="replace").read() if os.path.exists(p) else "" def components(): import soundfile py_lic = os.path.join(sys.base_prefix, "LICENSE.txt") return [ ("Python", sys.version.split()[0], "PSF-2.0", "https://www.python.org/downloads/source/", open(py_lic, encoding="utf-8", errors="replace").read() if os.path.exists(py_lic) else ""), ("Qt for Python (PySide6, Shiboken6) and the Qt libraries it bundles", ver("PySide6-Essentials"), "LGPL-3.0-only (used under LGPL: dynamically linked, unmodified shared libraries)", "https://code.qt.io/cgit/pyside/pyside-setup.git/ ; Qt sources: https://download.qt.io/official_releases/qt/", license_text("lgpl-3.0.txt") + "\n\n" + license_text("gpl-3.0.txt")), ("FFmpeg libraries bundled inside Qt Multimedia (PySide6-Addons)", ver("PySide6-Addons"), "LGPL-2.1-or-later", "https://download.qt.io/official_releases/qt/ (qtmultimedia FFmpeg build), https://ffmpeg.org/download.html", site_file("_soundfile_data", "COPYING")), ("libsndfile (in soundfile, %s)" % soundfile.__libsndfile_version__, soundfile.__libsndfile_version__, "LGPL-2.1-or-later", "https://github.com/libsndfile/libsndfile", site_file("_soundfile_data", "COPYING")), ("mpg123 (MP3 decoding, statically in libsndfile)", "bundled", "LGPL-2.1", "https://www.mpg123.de/download.shtml", "(see the LGPL-2.1 text of libsndfile above)"), ("LAME (MP3 encoding, statically in libsndfile; not used by this app)", "bundled", "LGPL-2.0", "https://lame.sourceforge.io/download.php", license_text("lgpl-2.0.txt")), ("libvorbis (statically in libsndfile)", "1.3.7", "BSD-3-Clause", "https://github.com/xiph/vorbis", license_text("libvorbis-COPYING")), ("libogg (statically in libsndfile)", "1.3.5", "BSD-3-Clause", "https://github.com/xiph/ogg", license_text("libogg-COPYING")), ("FLAC (statically in libsndfile)", "1.4.x", "BSD-3-Clause", "https://github.com/xiph/flac", license_text("flac-COPYING.Xiph")), ("Opus (statically in libsndfile)", "1.4", "BSD-3-Clause", "https://github.com/xiph/opus", license_text("opus-COPYING")), ("python-soundfile", ver("soundfile"), "BSD-3-Clause", "https://github.com/bastibe/python-soundfile", dist_file("soundfile", "LICENSE")), ("python-soxr and libsoxr", ver("soxr"), "LGPL-2.1-or-later", "https://github.com/dofuuz/python-soxr", dist_file("soxr", "COPYING.LGPL") + "\n\n" + dist_file("soxr", "LICENSE-libsoxr.txt") + "\n\n" + dist_file("soxr", "LICENSE-PFFFT.txt")), ("NumPy (incl. bundled OpenBLAS / runtime libraries)", ver("numpy"), "BSD-3-Clause and others (see text)", "https://github.com/numpy/numpy", dist_file("numpy", "LICENSE.txt")), ("cffi", ver("cffi"), "MIT-0", "https://github.com/python-cffi/cffi", dist_file("cffi", "LICENSE")), ("pycparser", ver("pycparser"), "BSD-3-Clause", "https://github.com/eliben/pycparser", dist_file("pycparser", "LICENSE")), ("PyInstaller bootloader", ver("pyinstaller"), "GPL-2.0-or-later with bootloader exception", "https://github.com/pyinstaller/pyinstaller", dist_file("pyinstaller", "COPYING.txt")), ("Wwise codebook data (ackit/data/game_codebooks.bin)", "-", "derived from libvorbis codebooks (BSD-3-Clause)", "https://github.com/xiph/vorbis", "(see libvorbis above)"), ("Community hash list (ackit/data/hashlist.txt)", "-", "no license stated (list of Wwise ID -> name pairs)", "from the 'Batman_bnk' tool shipped with AbdAshes' Batman Arkham Audio Guide", ""), ] def main(out): parts = ["THIRD-PARTY SOFTWARE in Unheard City\n" + "=" * 60 + "\n" "This program bundles the components below. LGPL components are dynamically linked shared libraries\n" "that you may replace; their source code is available at the URLs given.\n"] comps = components() for name, v, lic, url, _ in comps: parts.append("- %s %s\n License: %s\n Source: %s" % (name, v, lic, url)) for name, v, lic, url, text in comps: if text.strip(): parts.append("\n\n" + "=" * 78 + "\n%s %s (%s)\n" % (name, v, lic) + "=" * 78 + "\n" + text) open(out, "w", encoding="utf-8").write("\n".join(parts)) print("wrote %s (%d components)" % (out, len(comps))) if __name__ == "__main__": main(sys.argv[1] if len(sys.argv) > 1 else "THIRD_PARTY_LICENSES.txt")