#!/usr/bin/python3
# This is a helper script that does 2 things:
# 1. It goes through the list of bundled modules and copies their licenses to a
# specified directory. This then allows you to compare the licenses of the
# previous pipenv version with a new one to see any changes.
# 2. It looks for all other *LICENSE* and *COPYING* files and warns you about
# any have not been declared.
from pathlib import Path
import argparse
import os
import shutil
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Process pipenv bundled license files')
parser.add_argument('--bundled-modules', action='store', required=True,
help='Path of a file listing the bundled modules and their licenses')
parser.add_argument('--sources', action='store', required=True,
help='Path of the unpacked (and prepared) sources')
parser.add_argument('--list-license-files', action='store_true',
help='Print a list of all license files for declared bundled modules')
parser.add_argument('--license-diff-dir', action='store',
help='Path of an empty directory where to copy licenses for diffing')
args = parser.parse_args()
licenses_correct = True
SOURCES_DIR = Path(args.sources)
if args.license_diff_dir:
LICENSE_DIFF_DIR = Path(args.license_diff_dir)
all_declared_license_files = set()
with open(args.bundled_modules) as f:
# Ignore non-machine readable preface
for line in f:
if "BEGIN_MACHINE_READABLE_DATA" in line:
break
for line in f:
# Ignore empty lines
lineparts = line.strip().split(' ')
if len(lineparts) < 2:
continue
# Find all the license files for this bundled module
module = SOURCES_DIR / lineparts[1]
if module.suffix:
licenses = list(module.parent.glob(module.stem + "*LICENSE*"))
licenses.extend(module.parent.glob(module.stem + "*COPYING*"))
else:
licenses = list(module.glob("LICENSE*"))
licenses.extend(module.glob("COPYING*"))
if len(licenses) == 0:
print(f"WARNING: License file for `{module}` not found.")
licenses_correct = False
continue
all_declared_license_files.update(licenses)
if args.license_diff_dir:
# Copy all the license files to the license diff dir
module_dir = licenses[0].parent
copy_to_dir = LICENSE_DIFF_DIR / module_dir.relative_to(SOURCES_DIR)
os.makedirs(copy_to_dir, exist_ok=True)
for license in licenses:
shutil.copyfile(license, copy_to_dir / license.name)
if args.license_diff_dir:
print(f"Copied {len(all_declared_license_files)} license files of listed bundled modules to directory `{LICENSE_DIFF_DIR}`.")
else:
print(f"Found {len(all_declared_license_files)} license files of listed bundled modules.")
if args.list_license_files:
print(f"List of all license files for declared bundled modules:")
for l in sorted(all_declared_license_files):
print(f" {l}")
# Look for all license files in the source dir
all_licenses = set(SOURCES_DIR.rglob("*LICENSE*"))
all_licenses.update(SOURCES_DIR.rglob("*COPYING*"))
undeclared_licenses = all_licenses - all_declared_license_files
# Exclude the main pipenv LICENSE file and license files in tests which we don't ship
undeclared_licenses = [p for p in undeclared_licenses if p.parent != SOURCES_DIR
and "tests" not in p.parts]
# Print license files that are not declared
if undeclared_licenses:
licenses_correct = False
print(f"WARNING:")
print(f" {len(undeclared_licenses)} bundled license files that were *NOT* declared in `{args.bundled_modules}` were found:")
for l in sorted(undeclared_licenses):
print(f" {l}")
if not args.list_license_files and licenses_correct:
print(f"SUCCESS:")
print(f" The `{args.bundled_modules}` file declares all the bundled modules with licenses correctly.")