Majorly refactor the code
The primary reason behind refactoring the code is to be able to make it straightforward to implement the --reverse mode (ie. instead of showing package and their sub-deps, it will show the sub-deps and the packages that need them). As a part of this change, wrapper classes have been added for Distribution and Requirements instances that pip returns. These wrapper classes have handle the rendering of the pkg as a root (top level) and a branch (non-top level) accordingly. As a result the same function `render_tree` can be used for --reverse mode. This change doesn't include the --reverse mode implementation. It will be added in the subsequent commit.
This commit is contained in:
parent
07685bd313
commit
8db536eab3
328
pipdeptree.py
328
pipdeptree.py
|
@ -13,99 +13,206 @@ __version__ = '0.4.3'
|
|||
flatten = chain.from_iterable
|
||||
|
||||
|
||||
def req_version(req):
|
||||
"""Builds the version string for the requirement instance
|
||||
def build_dist_index(pkgs):
|
||||
"""Build an index pkgs by their key as a dict.
|
||||
|
||||
:param req: requirement object
|
||||
:returns: the version in desired format
|
||||
:rtype: string or NoneType
|
||||
:param list pkgs: list of pkg_resources.Distribution instances
|
||||
:returns: index of the pkgs by the pkg key
|
||||
:rtype: dict
|
||||
|
||||
"""
|
||||
return ''.join(req.specs[0]) if req.specs else None
|
||||
return {p.key: DistPackage(p) for p in pkgs}
|
||||
|
||||
|
||||
def top_pkg_name(pkg):
|
||||
"""Builds the package name for top level package
|
||||
def construct_tree(index):
|
||||
"""Construct tree representation of the pkgs from the index.
|
||||
|
||||
This just prints the name and the version of the package which may
|
||||
not necessarily match with the output of `pip freeze` which also
|
||||
includes info such as VCS source for editable packages
|
||||
The keys of the dict representing the tree will be objects of type
|
||||
DistPackage and the values will be list of ReqPackage objects.
|
||||
|
||||
:param pkg: pkg_resources.Distribution
|
||||
:returns: the package name and version in the desired format
|
||||
:rtype: string
|
||||
:param dict index: dist index ie. index of pkgs by their keys
|
||||
:returns: tree of pkgs and their dependencies
|
||||
:rtype: dict
|
||||
|
||||
"""
|
||||
return '{0}=={1}'.format(pkg.project_name, pkg.version)
|
||||
return {p: [ReqPackage(r, index.get(r.key))
|
||||
for r in p.requires()]
|
||||
for p in index.values()}
|
||||
|
||||
|
||||
def non_top_pkg_name(req, pkg):
|
||||
"""Builds the package name for a non-top level package
|
||||
class Package(object):
|
||||
"""Abstract class for wrappers around objects that pip returns.
|
||||
|
||||
For the dependencies of the top level packages, the installed
|
||||
version as well as the version required by it's parent package
|
||||
will be specified with it's name
|
||||
|
||||
:param req: requirements instance
|
||||
:param pkg: pkg_resources.Distribution
|
||||
:returns: the package name and version in the desired format
|
||||
:rtype: string
|
||||
This class needs to be subclassed with implementations for
|
||||
`render_as_root` and `render_as_branch` methods.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, obj):
|
||||
self._obj = obj
|
||||
self.project_name = obj.project_name
|
||||
self.key = obj.key
|
||||
# an instance of every subclass of Package will have a
|
||||
# DistPackage object associated with it. In case of
|
||||
# DistPackage class, it will be the object itself.
|
||||
self.dist = None
|
||||
|
||||
def render_as_root(self, frozen):
|
||||
return NotImplementedError
|
||||
|
||||
def render_as_branch(self, parent, frozen):
|
||||
return NotImplementedError
|
||||
|
||||
def render(self, parent=None, frozen=False):
|
||||
if not parent:
|
||||
return self.render_as_root(frozen)
|
||||
else:
|
||||
return self.render_as_branch(parent, frozen)
|
||||
|
||||
def frozen_repr(self):
|
||||
if self.dist:
|
||||
fr = pip.FrozenRequirement.from_dist(self.dist._obj, [])
|
||||
return str(fr).strip()
|
||||
else:
|
||||
return self.project_name
|
||||
|
||||
def __getattr__(self, key):
|
||||
return getattr(self._obj, key)
|
||||
|
||||
def __repr__(self):
|
||||
return '<{0}("{1}")>'.format(self.__class__.__name__, self.key)
|
||||
|
||||
|
||||
class DistPackage(Package):
|
||||
"""Wrapper class for pkg_resources.Distribution instances"""
|
||||
|
||||
def __init__(self, obj):
|
||||
super(DistPackage, self).__init__(obj)
|
||||
# this itself is the associated dist package obj
|
||||
self.dist = self
|
||||
self.version_spec = None
|
||||
|
||||
def render_as_root(self, frozen):
|
||||
if not frozen:
|
||||
return '{0}=={1}'.format(self.project_name, self.version)
|
||||
else:
|
||||
return self.frozen_repr()
|
||||
|
||||
def render_as_branch(self, parent, _frozen):
|
||||
parent_ver_spec = parent.version_spec
|
||||
parent_str = parent.project_name
|
||||
if parent_ver_spec:
|
||||
parent_str += parent_ver_spec
|
||||
return (
|
||||
'{0}=={1} [requires: {2}]'
|
||||
).format(self.project_name, self.version, parent_str)
|
||||
|
||||
def as_requirement(self):
|
||||
return ReqPackage(self._obj.as_requirement(), dist=self)
|
||||
|
||||
|
||||
class ReqPackage(Package):
|
||||
"""Wrapper class for Requirements instance"""
|
||||
|
||||
def __init__(self, obj, dist=None):
|
||||
super(ReqPackage, self).__init__(obj)
|
||||
self.dist = dist
|
||||
|
||||
@property
|
||||
def version_spec(self):
|
||||
specs = self._obj.specs
|
||||
return ''.join(specs[0]) if specs else None
|
||||
|
||||
@property
|
||||
def installed_version(self):
|
||||
# if the dist is None as in some cases, we don't know the
|
||||
# installed version
|
||||
return self.dist.version if self.dist else '?'
|
||||
|
||||
def render_as_root(self, frozen):
|
||||
if not frozen:
|
||||
return '{0}=={1}'.format(self.project_name, self.installed_version)
|
||||
else:
|
||||
return self.frozen_repr()
|
||||
|
||||
def render_as_branch(self, _parent, frozen):
|
||||
if not frozen:
|
||||
vers = []
|
||||
req_ver = req_version(req)
|
||||
if req_ver:
|
||||
vers.append(('required', req_ver))
|
||||
if pkg:
|
||||
vers.append(('installed', pkg.version))
|
||||
if self.version_spec:
|
||||
vers.append(('required', self.version_spec))
|
||||
if self.dist:
|
||||
vers.append(('installed', self.installed_version))
|
||||
if not vers:
|
||||
return req.key
|
||||
return self.key
|
||||
ver_str = ', '.join(['{0}: {1}'.format(k, v) for k, v in vers])
|
||||
return '{0} [{1}]'.format(pkg.project_name, ver_str)
|
||||
return '{0} [{1}]'.format(self.project_name, ver_str)
|
||||
else:
|
||||
return self.render_as_root(frozen)
|
||||
|
||||
|
||||
def top_pkg_src(pkg):
|
||||
"""Returns the frozen package name
|
||||
def render_tree(tree, list_all=True, frozen=False):
|
||||
"""Convert to tree to string representation
|
||||
|
||||
The may or may not be the same as the package name.
|
||||
|
||||
:param pkg: pkg_resources.Distribution
|
||||
:returns: frozen name of the package
|
||||
:rtype: string
|
||||
:param dict tree: the package tree
|
||||
:param bool list_all: whether to list all the pgks at the root
|
||||
level or only those that are the
|
||||
sub-dependencies
|
||||
:param bool frozen: whether or not show the names of the pkgs in
|
||||
the output that's favourable to pip --freeze
|
||||
:returns: string representation of the tree
|
||||
:rtype: str
|
||||
|
||||
"""
|
||||
return str(pip.FrozenRequirement.from_dist(pkg, [])).strip()
|
||||
branch_keys = set(r.key for r in flatten(tree.values()))
|
||||
nodes = tree.keys()
|
||||
use_bullets = not frozen
|
||||
|
||||
key_tree = {k.key: v for k, v in tree.iteritems()}
|
||||
get_children = lambda n: key_tree[n.key]
|
||||
|
||||
if not list_all:
|
||||
nodes = [p for p in nodes if p.key not in branch_keys]
|
||||
|
||||
def aux(node, parent=None, indent=0, chain=None):
|
||||
if chain is None:
|
||||
chain = [node.project_name]
|
||||
node_str = node.render(parent, frozen)
|
||||
if parent:
|
||||
prefix = ' '*indent + ('-' if use_bullets else ' ') + ' '
|
||||
node_str = prefix + node_str
|
||||
result = [node_str]
|
||||
|
||||
# the dist attr for some ReqPackage could be None
|
||||
# eg. testresources, setuptools which is a dependencies of
|
||||
# some pkg but doesn't get listed in the result of
|
||||
# pip.get_installed_distributions.
|
||||
if node.dist:
|
||||
children = [aux(c, node, indent=indent+2,
|
||||
chain=chain+[c.project_name])
|
||||
for c in get_children(node)
|
||||
if c.project_name not in chain]
|
||||
result += list(flatten(children))
|
||||
return result
|
||||
|
||||
lines = flatten([aux(p) for p in nodes])
|
||||
return '\n'.join(lines)
|
||||
|
||||
|
||||
def non_top_pkg_src(_req, pkg):
|
||||
"""Returns frozen package name for non top level package
|
||||
|
||||
:param _req: the requirements instance
|
||||
:param pkg: pkg_resources.Distribution
|
||||
:returns: frozen name of the package
|
||||
:rtype: string
|
||||
|
||||
"""
|
||||
return top_pkg_src(pkg)
|
||||
|
||||
|
||||
def has_multi_versions(reqs):
|
||||
vers = (req_version(r) for r in reqs)
|
||||
return len(set(vers)) > 1
|
||||
|
||||
|
||||
def confusing_deps(req_map):
|
||||
def confusing_deps(tree):
|
||||
"""Returns group of dependencies that are possibly confusing
|
||||
|
||||
eg. if pkg1 requires pkg3>=1.0 and pkg2 requires pkg3>=1.0,<=2.0
|
||||
|
||||
:param dict req_map: mapping of pkgs with the list of their deps
|
||||
:param dict tree: the requirements tree
|
||||
:returns: groups of dependencies paired with their top level pkgs
|
||||
:rtype: list of list of pairs
|
||||
|
||||
"""
|
||||
def has_multi_versions(req_pkgs):
|
||||
return len(set(r.version_spec for r in req_pkgs)) > 1
|
||||
|
||||
deps = defaultdict(list)
|
||||
for p, rs in req_map.items():
|
||||
for p, rs in tree.items():
|
||||
for r in rs:
|
||||
deps[r.key].append((p, r))
|
||||
return [ps for r, ps in deps.items()
|
||||
|
@ -113,63 +220,7 @@ def confusing_deps(req_map):
|
|||
and has_multi_versions(d for p, d in ps)]
|
||||
|
||||
|
||||
def render_tree(pkgs, pkg_index, req_map, list_all,
|
||||
top_pkg_str, non_top_pkg_str, bullets=True):
|
||||
"""Renders a package dependency tree as a string
|
||||
|
||||
:param list pkgs: pkg_resources.Distribution instances
|
||||
:param dict pkg_index: mapping of pkgs with their respective keys
|
||||
:param dict req_map: mapping of pkgs with the list of their deps
|
||||
:param bool list_all: whether to show globally installed pkgs
|
||||
if inside a virtualenv with global access
|
||||
:param function top_pkg_str: function to render a top level
|
||||
package as string
|
||||
:param function non_top_pkg_str: function to render a non-top
|
||||
level package as string
|
||||
:param bool bullets: whether or not to show bullets for child
|
||||
dependencies [default: True]
|
||||
:returns: dependency tree encoded as string
|
||||
:rtype: str
|
||||
|
||||
"""
|
||||
non_top = set(r.key for r in flatten(req_map.values()))
|
||||
top = [p for p in pkgs if p.key not in non_top]
|
||||
|
||||
def aux(pkg, indent=0, chain=None):
|
||||
if chain is None:
|
||||
chain = [pkg.project_name]
|
||||
|
||||
# In this function, pkg can either be a Distribution or
|
||||
# Requirement instance
|
||||
if indent > 0:
|
||||
# this is definitely a Requirement (due to positive
|
||||
# indent) so we need to find the Distribution instance for
|
||||
# it from the pkg_index
|
||||
dist = pkg_index.get(pkg.key)
|
||||
# FixMe! Some dependencies are not present in the result of
|
||||
# `pip.get_installed_distributions`
|
||||
# eg. `testresources`. This is a hack around it.
|
||||
name = pkg.project_name if dist is None else non_top_pkg_str(pkg, dist)
|
||||
result = [' '*indent + ('-' if bullets else ' ') + ' ' + name]
|
||||
else:
|
||||
result = [top_pkg_str(pkg)]
|
||||
|
||||
# FixMe! in case of some pkg not present in list of all
|
||||
# packages, eg. `testresources`, this will fail
|
||||
if pkg.key in pkg_index:
|
||||
pkg_deps = pkg_index[pkg.key].requires()
|
||||
filtered_deps = [
|
||||
aux(d, indent=indent+2, chain=chain+[d.project_name])
|
||||
for d in pkg_deps
|
||||
if d.project_name not in chain]
|
||||
result += list(flatten(filtered_deps))
|
||||
return result
|
||||
|
||||
lines = flatten([aux(p) for p in (pkgs if list_all else top)])
|
||||
return '\n'.join(lines)
|
||||
|
||||
|
||||
def cyclic_deps(pkgs, pkg_index):
|
||||
def cyclic_deps(tree):
|
||||
"""Generator that produces cyclic dependencies
|
||||
|
||||
:param list pkgs: pkg_resources.Distribution instances
|
||||
|
@ -179,16 +230,20 @@ def cyclic_deps(pkgs, pkg_index):
|
|||
:rtype: generator
|
||||
|
||||
"""
|
||||
def aux(pkg, chain):
|
||||
if pkg.key in pkg_index:
|
||||
for d in pkg_index[pkg.key].requires():
|
||||
if d.project_name in chain:
|
||||
yield ' => '.join([str(p) for p in chain] + [str(d)])
|
||||
nodes = tree.keys()
|
||||
key_tree = {k.key: v for k, v in tree.iteritems()}
|
||||
get_children = lambda n: key_tree[n.key]
|
||||
|
||||
def aux(node, chain):
|
||||
if node.dist:
|
||||
for c in get_children(node):
|
||||
if c.project_name in chain:
|
||||
yield ' => '.join([str(p) for p in chain] + [str(c)])
|
||||
else:
|
||||
for cycle in aux(d, chain=chain+[d.project_name]):
|
||||
for cycle in aux(c, chain=chain+[c.project_name]):
|
||||
yield cycle
|
||||
|
||||
for cycle in flatten([aux(p, chain=[]) for p in pkgs]):
|
||||
for cycle in flatten([aux(n, chain=[]) for n in nodes]):
|
||||
yield cycle
|
||||
|
||||
|
||||
|
@ -235,44 +290,33 @@ def main():
|
|||
pkgs = pip.get_installed_distributions(local_only=args.local_only,
|
||||
skip=skip)
|
||||
|
||||
pkg_index = dict((p.key, p) for p in pkgs)
|
||||
req_map = dict((p, p.requires()) for p in pkgs)
|
||||
dist_index = build_dist_index(pkgs)
|
||||
tree = construct_tree(dist_index)
|
||||
|
||||
# show warnings about possibly confusing deps if found and
|
||||
# warnings are enabled
|
||||
if not args.nowarn:
|
||||
confusing = confusing_deps(req_map)
|
||||
confusing = confusing_deps(tree)
|
||||
if confusing:
|
||||
print('Warning!!! Possible confusing dependencies found:', file=sys.stderr)
|
||||
for xs in confusing:
|
||||
for i, (p, d) in enumerate(xs):
|
||||
if d.key in skip:
|
||||
continue
|
||||
pkg = top_pkg_name(p)
|
||||
req = non_top_pkg_name(d, pkg_index[d.key])
|
||||
pkg = p.render_as_root(False)
|
||||
req = d.render_as_branch(p, False)
|
||||
tmpl = ' {0} -> {1}' if i > 0 else '* {0} -> {1}'
|
||||
print(tmpl.format(pkg, req), file=sys.stderr)
|
||||
print('-'*72, file=sys.stderr)
|
||||
|
||||
is_empty, cyclic = peek_into(cyclic_deps(pkgs, pkg_index))
|
||||
is_empty, cyclic = peek_into(cyclic_deps(tree))
|
||||
if not is_empty:
|
||||
print('Warning!!! Cyclic dependencies found:', file=sys.stderr)
|
||||
for xs in cyclic:
|
||||
print('- {0}'.format(xs), file=sys.stderr)
|
||||
print('-'*72, file=sys.stderr)
|
||||
|
||||
if args.freeze:
|
||||
top_pkg_str, non_top_pkg_str = top_pkg_src, non_top_pkg_src
|
||||
else:
|
||||
top_pkg_str, non_top_pkg_str = top_pkg_name, non_top_pkg_name
|
||||
|
||||
tree = render_tree(pkgs,
|
||||
pkg_index=pkg_index,
|
||||
req_map=req_map,
|
||||
list_all=args.all,
|
||||
top_pkg_str=top_pkg_str,
|
||||
non_top_pkg_str=non_top_pkg_str,
|
||||
bullets=not args.freeze)
|
||||
tree = render_tree(tree, list_all=args.all, frozen=args.freeze)
|
||||
print(tree)
|
||||
return 0
|
||||
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import pickle
|
||||
|
||||
from pipdeptree import (req_version, render_tree,
|
||||
top_pkg_name, non_top_pkg_name,
|
||||
top_pkg_src, non_top_pkg_src, peek_into)
|
||||
from pipdeptree import (build_dist_index, construct_tree, peek_into,
|
||||
DistPackage, ReqPackage, render_tree)
|
||||
|
||||
|
||||
def venv_fixture(pickle_file):
|
||||
|
@ -15,48 +14,82 @@ def venv_fixture(pickle_file):
|
|||
"""
|
||||
with open(pickle_file, 'rb') as f:
|
||||
pkgs = pickle.load(f)
|
||||
pkg_index = dict((p.key, p) for p in pkgs)
|
||||
req_map = dict((p, p.requires()) for p in pkgs)
|
||||
return pkgs, pkg_index, req_map
|
||||
dist_index = build_dist_index(pkgs)
|
||||
tree = construct_tree(dist_index)
|
||||
return pkgs, dist_index, tree
|
||||
|
||||
|
||||
pkgs, pkg_index, req_map = venv_fixture('tests/virtualenvs/testenv.pickle')
|
||||
pkgs, dist_index, tree = venv_fixture('tests/virtualenvs/testenv.pickle')
|
||||
|
||||
|
||||
def find_req(req, parent):
|
||||
"""Helper to get the requirement object from it's parent package
|
||||
|
||||
:param req: string
|
||||
:param parent: pkg_resources.Distribution instance
|
||||
:rtype: instance of requirement frozen set
|
||||
|
||||
"""
|
||||
return [r for r in pkg_index[parent].requires() if r.key == req][0]
|
||||
def find_dist(key):
|
||||
return dist_index[key]
|
||||
|
||||
|
||||
def test_req_version():
|
||||
def find_req(key, parent_key):
|
||||
parent = [x for x in tree.keys() if x.key == parent_key][0]
|
||||
return [x for x in tree[parent] if x.key == key][0]
|
||||
|
||||
|
||||
def test_build_dist_index():
|
||||
assert len(dist_index) == len(pkgs)
|
||||
assert all(isinstance(x, str) for x in dist_index.keys())
|
||||
assert all(isinstance(x, DistPackage) for x in dist_index.values())
|
||||
|
||||
|
||||
def test_tree():
|
||||
assert len(tree) == len(pkgs)
|
||||
assert all((isinstance(k, DistPackage) and
|
||||
all(isinstance(v, ReqPackage) for v in vs))
|
||||
for k, vs in tree.iteritems())
|
||||
|
||||
|
||||
def test_DistPackage_render_as_root():
|
||||
alembic = find_dist('alembic')
|
||||
assert alembic.version == '0.6.2'
|
||||
assert alembic.project_name == 'alembic'
|
||||
assert alembic.render_as_root(frozen=False) == 'alembic==0.6.2'
|
||||
|
||||
|
||||
def test_DistPackage_render_as_branch():
|
||||
alembic = find_dist('alembic')
|
||||
assert alembic.project_name == 'alembic'
|
||||
assert alembic.version == '0.6.2'
|
||||
sqlalchemy = find_req('sqlalchemy', 'alembic')
|
||||
assert req_version(sqlalchemy) == '>=0.7.3'
|
||||
mako = find_req('mako', 'alembic')
|
||||
assert req_version(mako) is None
|
||||
assert sqlalchemy.project_name == 'SQLAlchemy'
|
||||
assert sqlalchemy.version_spec == '>=0.7.3'
|
||||
assert sqlalchemy.installed_version == '0.9.1'
|
||||
result_1 = alembic.render_as_branch(sqlalchemy, False)
|
||||
result_2 = alembic.render_as_branch(sqlalchemy, False)
|
||||
assert result_1 == result_2 == 'alembic==0.6.2 [requires: SQLAlchemy>=0.7.3]'
|
||||
|
||||
|
||||
def test_non_top_pkg_name():
|
||||
flask_p = pkg_index['flask']
|
||||
flask_r = find_req('flask', 'flask-script')
|
||||
assert non_top_pkg_name(flask_r, flask_p) == 'Flask [installed: 0.10.1]'
|
||||
def test_ReqPackage_render_as_root():
|
||||
flask = find_req('flask', 'flask-script')
|
||||
assert flask.project_name == 'Flask'
|
||||
assert flask.installed_version == '0.10.1'
|
||||
assert flask.render_as_root(frozen=False) == 'Flask==0.10.1'
|
||||
|
||||
markupsafe_p = pkg_index['markupsafe']
|
||||
markupsafe_jinja2_r = find_req('markupsafe', 'jinja2')
|
||||
assert non_top_pkg_name(markupsafe_jinja2_r, markupsafe_p) == 'MarkupSafe [installed: 0.18]'
|
||||
|
||||
markupsafe_mako_r = find_req('markupsafe', 'mako')
|
||||
assert non_top_pkg_name(markupsafe_mako_r, markupsafe_p) == 'MarkupSafe [required: >=0.9.2, installed: 0.18]'
|
||||
def test_ReqPackage_render_as_branch():
|
||||
mks1 = find_req('markupsafe', 'jinja2')
|
||||
jinja = find_dist('jinja2')
|
||||
assert mks1.project_name == 'markupsafe'
|
||||
assert mks1.installed_version == '0.18'
|
||||
assert mks1.version_spec is None
|
||||
assert mks1.render_as_branch(jinja, False) == 'markupsafe [installed: 0.18]'
|
||||
assert mks1.render_as_branch(jinja, True) == 'MarkupSafe==0.18'
|
||||
mks2 = find_req('markupsafe', 'mako')
|
||||
mako = find_dist('mako')
|
||||
assert mks2.project_name == 'MarkupSafe'
|
||||
assert mks2.installed_version == '0.18'
|
||||
assert mks2.version_spec == '>=0.9.2'
|
||||
assert mks2.render_as_branch(mako, False) == 'MarkupSafe [required: >=0.9.2, installed: 0.18]'
|
||||
assert mks2.render_as_branch(mako, True) == 'MarkupSafe==0.18'
|
||||
|
||||
|
||||
def test_render_tree_only_top():
|
||||
tree_str = render_tree(pkgs, pkg_index, req_map, False,
|
||||
top_pkg_name, non_top_pkg_name)
|
||||
tree_str = render_tree(tree, list_all=False)
|
||||
lines = set(tree_str.split('\n'))
|
||||
assert 'Flask-Script==0.6.6' in lines
|
||||
assert ' - SQLAlchemy [required: >=0.7.3, installed: 0.9.1]' in lines
|
||||
|
@ -65,8 +98,7 @@ def test_render_tree_only_top():
|
|||
|
||||
|
||||
def test_render_tree_list_all():
|
||||
tree_str = render_tree(pkgs, pkg_index, req_map, True,
|
||||
top_pkg_name, non_top_pkg_name)
|
||||
tree_str = render_tree(tree, list_all=True)
|
||||
lines = set(tree_str.split('\n'))
|
||||
assert 'Flask-Script==0.6.6' in lines
|
||||
assert ' - SQLAlchemy [required: >=0.7.3, installed: 0.9.1]' in lines
|
||||
|
@ -75,8 +107,7 @@ def test_render_tree_list_all():
|
|||
|
||||
|
||||
def test_render_tree_freeze():
|
||||
tree_str = render_tree(pkgs, pkg_index, req_map, False,
|
||||
top_pkg_src, non_top_pkg_src, bullets=False)
|
||||
tree_str = render_tree(tree, list_all=False, frozen=True)
|
||||
lines = set()
|
||||
for line in tree_str.split('\n'):
|
||||
# Workaround for https://github.com/pypa/pip/issues/1867
|
||||
|
@ -92,10 +123,8 @@ def test_render_tree_freeze():
|
|||
|
||||
|
||||
def test_render_tree_cyclic_dependency():
|
||||
cyclic_pkgs, pkg_index, req_map = venv_fixture('tests/virtualenvs/cyclicenv.pickle')
|
||||
list_all = True
|
||||
tree_str = render_tree(cyclic_pkgs, pkg_index, req_map, list_all,
|
||||
top_pkg_name, non_top_pkg_name)
|
||||
cyclic_pkgs, dist_index, tree = venv_fixture('tests/virtualenvs/cyclicenv.pickle')
|
||||
tree_str = render_tree(tree, list_all=True)
|
||||
lines = set(tree_str.split('\n'))
|
||||
assert 'CircularDependencyA==0.0.0' in lines
|
||||
assert ' - CircularDependencyB [installed: 0.0.0]' in lines
|
||||
|
@ -104,15 +133,13 @@ def test_render_tree_cyclic_dependency():
|
|||
|
||||
|
||||
def test_render_tree_freeze_cyclic_dependency():
|
||||
cyclic_pkgs, pkg_index, req_map = venv_fixture('tests/virtualenvs/cyclicenv.pickle')
|
||||
list_all = True
|
||||
tree_str = render_tree(cyclic_pkgs, pkg_index, req_map, list_all,
|
||||
top_pkg_src, non_top_pkg_src)
|
||||
cyclic_pkgs, dist_index, tree = venv_fixture('tests/virtualenvs/cyclicenv.pickle')
|
||||
tree_str = render_tree(tree, list_all=True, frozen=True)
|
||||
lines = set(tree_str.split('\n'))
|
||||
assert 'CircularDependencyA==0.0.0' in lines
|
||||
assert ' - CircularDependencyB==0.0.0' in lines
|
||||
assert ' CircularDependencyB==0.0.0' in lines
|
||||
assert 'CircularDependencyB==0.0.0' in lines
|
||||
assert ' - CircularDependencyA==0.0.0' in lines
|
||||
assert ' CircularDependencyA==0.0.0' in lines
|
||||
|
||||
|
||||
def test_peek_into():
|
||||
|
|
Loading…
Reference in New Issue