diff --git a/pipenv/cli.py b/pipenv/cli.py index 40cd55aaee..8a12f3b01a 100644 --- a/pipenv/cli.py +++ b/pipenv/cli.py @@ -841,13 +841,14 @@ def update( ) @option('--bare', is_flag=True, default=False, help="Minimal output.") @option('--json', is_flag=True, default=False, help="Output JSON.") +@option('--json-tree', is_flag=True, default=False, help="Output JSON in nested tree.") @option( '--reverse', is_flag=True, default=False, help="Reversed dependency graph." ) -def graph(bare=False, json=False, reverse=False): +def graph(bare=False, json=False, json_tree=False, reverse=False): from .core import do_graph - do_graph(bare=bare, json=json, reverse=reverse) + do_graph(bare=bare, json=json, json_tree=json_tree, reverse=reverse) @command(short_help="View a given module in your editor.", name="open") diff --git a/pipenv/core.py b/pipenv/core.py index 92ae32931f..9ed3dabad0 100644 --- a/pipenv/core.py +++ b/pipenv/core.py @@ -2409,7 +2409,7 @@ def do_check(three=None, python=False, system=False, unused=False, args=None): sys.exit(1) -def do_graph(bare=False, json=False, reverse=False): +def do_graph(bare=False, json=False, json_tree=False, reverse=False): import pipdeptree try: python_path = which('python') @@ -2433,9 +2433,31 @@ def do_graph(bare=False, json=False, reverse=False): err=True, ) sys.exit(1) + if reverse and json_tree: + click.echo( + u'{0}: {1}'.format( + crayons.red('Warning', bold=True), + u'Using both --reverse and --json-tree together is not supported. ' + u'Please select one of the two options.', + ), + err=True, + ) + sys.exit(1) + if json and json_tree: + click.echo( + u'{0}: {1}'.format( + crayons.red('Warning', bold=True), + u'Using both --json and --json-tree together is not supported. ' + u'Please select one of the two options.', + ), + err=True, + ) + sys.exit(1) flag = '' if json: flag = '--json' + if json_tree: + flag = '--json-tree' if reverse: flag = '--reverse' if not project.virtualenv_exists: @@ -2465,6 +2487,16 @@ def do_graph(bare=False, json=False, reverse=False): data.append(d) click.echo(simplejson.dumps(data, indent=4)) sys.exit(0) + elif json_tree: + def traverse(obj): + if isinstance(obj, list): + return [traverse(package) for package in obj if package['key'] not in BAD_PACKAGES] + else: + obj['dependencies'] = traverse(obj['dependencies']) + return obj + data = traverse(simplejson.loads(c.out)) + click.echo(simplejson.dumps(data, indent=4)) + sys.exit(0) else: for line in c.out.split('\n'): # Ignore bad packages as top level. diff --git a/tests/integration/test_cli.py b/tests/integration/test_cli.py index ad84912b3b..caccc57bc5 100644 --- a/tests/integration/test_cli.py +++ b/tests/integration/test_cli.py @@ -48,6 +48,7 @@ def test_pipenv_graph(PipenvInstance, pypi): p.pipenv('install requests') assert 'requests' in p.pipenv('graph').out assert 'requests' in p.pipenv('graph --json').out + assert 'requests' in p.pipenv('graph --json-tree').out @pytest.mark.cli