Merge pull request #94 from ciarancourtney/master

#69 Add '--exclude' arg to exclude CSV list of packages and children from output
This commit is contained in:
Vineet Naik 2018-05-15 22:19:16 +05:30 committed by GitHub
commit ba5d5e2fa0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 99 additions and 7 deletions

View File

@ -263,6 +263,9 @@ Usage
-p PACKAGES, --packages PACKAGES
Comma separated list of select packages to show in the
output. If set, --all will be ignored.
-e PACKAGES, --exclude PACKAGES
Comma separated list of select packages to exclude from
the output. If set, --all will be ignored.
-j, --json Display dependency tree as json. This will yield "raw"
output that may be used by external tools. This option
overrides all other options.

View File

@ -280,8 +280,8 @@ class ReqPackage(Package):
'required_version': self.version_spec}
def render_tree(tree, list_all=True, show_only=None, frozen=False):
"""Convert to tree to string representation
def render_tree(tree, list_all=True, show_only=None, frozen=False, exclude=None):
"""Convert tree to string representation
:param dict tree: the package tree
:param bool list_all: whether to list all the pgks at the root
@ -291,6 +291,8 @@ def render_tree(tree, list_all=True, show_only=None, frozen=False):
output. This is optional arg, default: None.
:param bool frozen: whether or not show the names of the pkgs in
the output that's favourable to pip --freeze
:param set exclude: set of select packages to be excluded from the
output. This is optional arg, default: None.
:returns: string representation of the tree
:rtype: str
@ -310,6 +312,8 @@ def render_tree(tree, list_all=True, show_only=None, frozen=False):
nodes = [p for p in nodes if p.key not in branch_keys]
def aux(node, parent=None, indent=0, chain=None):
if exclude and (node.key in exclude or node.project_name in exclude):
return []
if chain is None:
chain = [node.project_name]
node_str = node.render(parent, frozen)
@ -527,6 +531,11 @@ def get_parser():
'Comma separated list of select packages to show '
'in the output. If set, --all will be ignored.'
))
parser.add_argument('-e', '--exclude',
help=(
'Comma separated list of select packages to exclude '
'from the output. If set, --all will be ignored.'
), metavar='PACKAGES')
parser.add_argument('-j', '--json', action='store_true', default=False,
help=(
'Display dependency tree as json. This will yield '
@ -548,10 +557,13 @@ def get_parser():
return parser
def main():
def _get_args():
parser = get_parser()
args = parser.parse_args()
return parser.parse_args()
def main():
args = _get_args()
pkgs = get_installed_distributions(local_only=args.local_only,
user_only=args.user_only)
@ -600,10 +612,15 @@ def main():
return_code = 1
show_only = set(args.packages.split(',')) if args.packages else None
exclude = set(args.exclude.split(',')) if args.exclude else None
if show_only and exclude and (show_only & exclude):
print('Conflicting packages found in --packages and --exclude lists.', file=sys.stderr)
sys.exit(1)
tree = render_tree(tree if not args.reverse else reverse_tree(tree),
list_all=args.all, show_only=show_only,
frozen=args.freeze)
frozen=args.freeze, exclude=exclude)
print(tree)
return return_code

View File

@ -6,11 +6,13 @@ from contextlib import contextmanager
from tempfile import NamedTemporaryFile
from operator import attrgetter
import pytest
from pipdeptree import (build_dist_index, construct_tree,
DistPackage, ReqPackage, render_tree,
reverse_tree, cyclic_deps, conflicting_deps,
get_parser, render_json, render_json_tree,
dump_graphviz, print_graphviz)
dump_graphviz, print_graphviz, main)
def venv_fixture(pickle_file):
@ -122,6 +124,42 @@ def test_render_tree_list_all():
assert 'itsdangerous==0.23' in lines
def test_render_tree_exclude():
tree_str = render_tree(tree, list_all=True, exclude={'itsdangerous', 'SQLAlchemy', 'Flask', 'markupsafe', 'wheel'})
assert tree_str == """\
alembic==0.6.2
- Mako [required: Any, installed: 0.9.1]
Flask-Script==0.6.6
gnureadline==6.3.8
ipython==2.0.0
Jinja2==2.7.2
Lookupy==0.1
Mako==0.9.1
psycopg2==2.7.3.2
redis==2.9.1
slugify==0.0.1
Werkzeug==0.9.4"""
def test_render_tree_exclude_reverse():
rtree = reverse_tree(tree)
tree_str = render_tree(rtree, list_all=True, exclude={'itsdangerous', 'SQLAlchemy', 'Flask', 'markupsafe', 'wheel'})
assert tree_str == """\
alembic==0.6.2
Flask-Script==0.6.6
gnureadline==6.3.8
ipython==2.0.0
Jinja2==2.7.2
Lookupy==0.1
Mako==0.9.1
- alembic==0.6.2 [requires: Mako]
psycopg2==2.7.3.2
redis==2.9.1
slugify==0.0.1
Werkzeug==0.9.4"""
def test_render_tree_freeze():
tree_str = render_tree(tree, list_all=False, frozen=True)
lines = set()
@ -298,3 +336,37 @@ def test_conflicting_deps():
flask: [jinja],
uritemplate: [simplejson],
}
def test_main_basic(monkeypatch):
parser = get_parser()
args = parser.parse_args('')
def _get_args():
return args
monkeypatch.setattr('pipdeptree._get_args', _get_args)
assert main() == 0
def test_main_show_only_and_exclude_ok(monkeypatch):
parser = get_parser()
args = parser.parse_args('--packages Flask --exclude Jinja2'.split())
def _get_args():
return args
monkeypatch.setattr('pipdeptree._get_args', _get_args)
assert main() == 0
def test_main_show_only_and_exclude_fails(monkeypatch):
parser = get_parser()
args = parser.parse_args('--packages Flask --exclude Jinja2,Flask'.split())
def _get_args():
return args
monkeypatch.setattr('pipdeptree._get_args', _get_args)
with pytest.raises(SystemExit):
main()

View File

@ -7,7 +7,7 @@ MarkupSafe==0.18
SQLAlchemy==0.9.1
Werkzeug==0.9.4
alembic==0.6.2
gnureadline==6.3.3
gnureadline==6.3.8
ipython==2.0.0
itsdangerous==0.23
psycopg2==2.7.3.2