list all licenses used by project splitted by development vs production dependencies
See original GitHub issueIs your feature request related to a problem? Please describe. I was asked by the legal department to get a list of all dependencies i am using in software. There is already a SO post but it does not differentiate between development and production dependencies which are handled legally different.
Describe the solution you’d like I would like pipenv to handle this in conjunction with pipenv graph. It has already the powers to do this because of pipenv graph. I would like to get a list of all the dependencies, including the transitive and get a list of their licenses split by production and development dependencies.
Describe alternatives you’ve considered In the meantime i hacked a script together based on the SO and pipenv graph to get the production dependencies:
'''
module calculating the licenses of the dependencies
'''
import subprocess
import json
import logging
from itertools import dropwhile, takewhile
from functools import reduce
from typing import Set, List, Dict
import pkg_resources
def _get_dependencies_from_pipfile() -> Set[str]:
with open('Pipfile') as pip_file:
start_gen = dropwhile(lambda x: x.strip() != '[packages]', pip_file)
next(start_gen)
interesting_gen = takewhile(lambda x: not x.startswith('['), start_gen)
return {interesting.split()[0] for interesting in interesting_gen}
def _get_package_dependencies(dependencies: List[Dict[str, str]]) -> Set[str]:
return {dependency['key'] for dependency in dependencies}
def _get_recursive_dependencies_for(direct_dependencies: Set[str]) -> Set[str]:
result = subprocess.run(
['pipenv', 'graph', '--json'], stdout=subprocess.PIPE)
dependencies_dict = {
k['package']['key']: k
for k in json.loads(result.stdout)
}
universe = set(dependencies_dict)
res = direct_dependencies
set_to_check = direct_dependencies
while set_to_check:
deps = universe & reduce(
lambda x, y: x | _get_package_dependencies(dependencies_dict[y]['dependencies']),
set_to_check, set())
set_to_check = deps - res
res = res | deps
return {dependencies_dict[r]['package']['package_name'] for r in res}
def get_pkg_license(pkgname: str) -> str:
"""
Given a package reference (as from requirements.txt),
return license listed in package metadata.
NOTE: This function does no error checking and is for
demonstration purposes only.
"""
pkgs = pkg_resources.require(pkgname)
pkg = pkgs[0]
for line in pkg.get_metadata_lines('METADATA'):
(key, value) = line.split(': ', 1)
if key == "License":
return value
return 'Undefined'
def _main() -> None:
direct_dependencies = _get_dependencies_from_pipfile()
all_deps = _get_recursive_dependencies_for(direct_dependencies)
for dep in all_deps:
try:
print(dep, get_pkg_license(dep))
except FileNotFoundError:
logging.exception("could not retrieve dependencies of %s", dep)
if __name__ == '__main__':
_main()
Additional context In maven issues like this are done through a plugin system. Do you think it would be good to create a plugin system or is this an overkilll?
Issue Analytics
- State:
- Created 5 years ago
- Reactions:1
- Comments:5 (4 by maintainers)
Top GitHub Comments
liccheck may be a good tool to build upon. I don’t know how good it is though. Anyone please do give this a shot if you’re interested in this topic. https://github.com/dhatim/python-license-check
+1