Merge pull request #60 from Dunedan/graphviz
Add different output options for dependency graph
This commit is contained in:
commit
6e095e658f
14
README.rst
14
README.rst
|
@ -201,6 +201,16 @@ tools.
|
||||||
|
|
||||||
$ python pipdeptree.py --json
|
$ python pipdeptree.py --json
|
||||||
|
|
||||||
|
The dependency graph can be layed out as any of the formats supported by
|
||||||
|
GraphViz`GraphViz<http://www.graphviz.org/>`_:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ pipdeptree --graph-output dot > dependencies.dot
|
||||||
|
$ pipdeptree --graph-output pdf > dependencies.pdf
|
||||||
|
$ pipdeptree --graph-output png > dependencies.png
|
||||||
|
$ pipdeptree --graph-output svg > dependencies.svg
|
||||||
|
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
-----
|
-----
|
||||||
|
@ -233,6 +243,10 @@ Usage
|
||||||
-j, --json Display dependency tree as json. This will yield "raw"
|
-j, --json Display dependency tree as json. This will yield "raw"
|
||||||
output that may be used by external tools. This option
|
output that may be used by external tools. This option
|
||||||
overrides all other options.
|
overrides all other options.
|
||||||
|
--graph-output OUTPUT_FORMAT
|
||||||
|
Print a dependency graph in the specified output
|
||||||
|
format. Available are all formats supported by
|
||||||
|
GraphViz, e.g.: dot, jpeg, pdf, png, svg
|
||||||
|
|
||||||
|
|
||||||
Known Issues
|
Known Issues
|
||||||
|
|
|
@ -14,6 +14,8 @@ except ImportError:
|
||||||
|
|
||||||
import pip
|
import pip
|
||||||
import pkg_resources
|
import pkg_resources
|
||||||
|
# inline:
|
||||||
|
# from graphviz import backend, Digraph
|
||||||
|
|
||||||
|
|
||||||
__version__ = '0.8.0'
|
__version__ = '0.8.0'
|
||||||
|
@ -339,6 +341,52 @@ def jsonify_tree(tree, indent):
|
||||||
indent=indent)
|
indent=indent)
|
||||||
|
|
||||||
|
|
||||||
|
def dump_graphviz(tree, output_format='dot'):
|
||||||
|
"""Output dependency graph as one of the supported GraphViz output formats.
|
||||||
|
|
||||||
|
:param dict tree: dependency graph
|
||||||
|
:param string output_format: output format
|
||||||
|
:returns: representation of tree in the specified output format
|
||||||
|
:rtype: str or binary representation depending on the output format
|
||||||
|
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
from graphviz import backend, Digraph
|
||||||
|
except ImportError:
|
||||||
|
print('graphviz is not available, but necessary for the output '
|
||||||
|
'option. Please install it.', file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if output_format not in backend.FORMATS:
|
||||||
|
print('{} is no supported output format.'.format(output_format),
|
||||||
|
file=sys.stderr)
|
||||||
|
print('Supported formats are: {}'.format(
|
||||||
|
', '.join(sorted(backend.FORMATS))), file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
graph = Digraph(format=output_format)
|
||||||
|
for package, deps in tree.items():
|
||||||
|
project_name = package.project_name
|
||||||
|
label = '{}\n{}'.format(project_name, package.version)
|
||||||
|
graph.node(project_name, label=label)
|
||||||
|
for dep in deps:
|
||||||
|
label = dep.version_spec
|
||||||
|
if not label:
|
||||||
|
label = 'any'
|
||||||
|
graph.edge(project_name, dep.project_name, label=label)
|
||||||
|
|
||||||
|
# Allow output of dot format, even if GraphViz isn't installed.
|
||||||
|
if output_format == 'dot':
|
||||||
|
return graph.source
|
||||||
|
|
||||||
|
# As it's unknown if the selected output format is binary or not, try to
|
||||||
|
# decode it as UTF8 and only print it out in binary if that's not possible.
|
||||||
|
try:
|
||||||
|
return graph.pipe().decode('utf-8')
|
||||||
|
except UnicodeDecodeError:
|
||||||
|
return graph.pipe()
|
||||||
|
|
||||||
|
|
||||||
def conflicting_deps(tree):
|
def conflicting_deps(tree):
|
||||||
"""Returns dependencies which are not present or conflict with the
|
"""Returns dependencies which are not present or conflict with the
|
||||||
requirements of other packages.
|
requirements of other packages.
|
||||||
|
@ -418,6 +466,12 @@ def main():
|
||||||
'"raw" output that may be used by external tools. '
|
'"raw" output that may be used by external tools. '
|
||||||
'This option overrides all other options.'
|
'This option overrides all other options.'
|
||||||
))
|
))
|
||||||
|
parser.add_argument('--graph-output', dest='output_format',
|
||||||
|
help=(
|
||||||
|
'Print a dependency graph in the specified output '
|
||||||
|
'format. Available are all formats supported by '
|
||||||
|
'GraphViz, e.g.: dot, jpeg, pdf, png, svg'
|
||||||
|
))
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
pkgs = pip.get_installed_distributions(local_only=args.local_only)
|
pkgs = pip.get_installed_distributions(local_only=args.local_only)
|
||||||
|
@ -428,6 +482,9 @@ def main():
|
||||||
if args.json:
|
if args.json:
|
||||||
print(jsonify_tree(tree, indent=4))
|
print(jsonify_tree(tree, indent=4))
|
||||||
return 0
|
return 0
|
||||||
|
elif args.output_format:
|
||||||
|
print(dump_graphviz(tree, output_format=args.output_format))
|
||||||
|
return 0
|
||||||
|
|
||||||
return_code = 0
|
return_code = 0
|
||||||
|
|
||||||
|
@ -440,10 +497,10 @@ def main():
|
||||||
file=sys.stderr)
|
file=sys.stderr)
|
||||||
for p, reqs in conflicting.items():
|
for p, reqs in conflicting.items():
|
||||||
pkg = p.render_as_root(False)
|
pkg = p.render_as_root(False)
|
||||||
print('* %s' % pkg, file=sys.stderr)
|
print('* {}'.format(pkg), file=sys.stderr)
|
||||||
for req in reqs:
|
for req in reqs:
|
||||||
req_str = req.render_as_branch(False)
|
req_str = req.render_as_branch(False)
|
||||||
print(' - %s' % req_str, file=sys.stderr)
|
print(' - {}'.format(req_str), file=sys.stderr)
|
||||||
print('-'*72, file=sys.stderr)
|
print('-'*72, file=sys.stderr)
|
||||||
|
|
||||||
cyclic = cyclic_deps(tree)
|
cyclic = cyclic_deps(tree)
|
||||||
|
|
1
setup.py
1
setup.py
|
@ -33,6 +33,7 @@ setup(
|
||||||
description='Command line utility to show dependency tree of packages',
|
description='Command line utility to show dependency tree of packages',
|
||||||
long_description=long_desc,
|
long_description=long_desc,
|
||||||
install_requires=install_requires,
|
install_requires=install_requires,
|
||||||
|
extras_require={'graphviz': ['graphviz']},
|
||||||
py_modules=['pipdeptree'],
|
py_modules=['pipdeptree'],
|
||||||
entry_points={
|
entry_points={
|
||||||
'console_scripts': [
|
'console_scripts': [
|
||||||
|
|
Loading…
Reference in New Issue