src/eric7/PipInterface/pipdeptree.py

Tue, 12 Jul 2022 16:26:22 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Tue, 12 Jul 2022 16:26:22 +0200
branch
eric7
changeset 9218
71cf3979a6c9
child 9589
09218eb3ae21
permissions
-rw-r--r--

pip Interface
- included a copy of pipdeptree and patched it to work with Python 3.11+

9218
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
1 #!/usr/bin/env python
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
2 # -*- coding: utf-8 -*-
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
3
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
4 """
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
5 Copyright (c) 2015 Vineet Naik (naikvin@gmail.com)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
6
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
7 Permission is hereby granted, free of charge, to any person obtaining
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
8 a copy of this software and associated documentation files (the
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
9 "Software"), to deal in the Software without restriction, including
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
10 without limitation the rights to use, copy, modify, merge, publish,
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
11 distribute, sublicense, and/or sell copies of the Software, and to
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
12 permit persons to whom the Software is furnished to do so, subject to
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
13 the following conditions:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
14
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
15 The above copyright notice and this permission notice shall be
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
16 included in all copies or substantial portions of the Software.
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
17
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
21 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
22 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
23 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
24 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
25 """
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
26
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
27 #
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
28 # Modified to be used within the eric-ide project.
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
29 #
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
30 # Copyright (c) 2022 Detlev Offenbach <detlev@die-offenbachs.de>
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
31 #
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
32
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
33 from __future__ import print_function
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
34 import os
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
35 import inspect
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
36 import sys
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
37 import subprocess
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
38 from itertools import chain
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
39 from collections import defaultdict, deque
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
40 import argparse
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
41 import json
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
42 from importlib import import_module
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
43 import tempfile
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
44
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
45 try:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
46 from collections import OrderedDict
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
47 except ImportError:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
48 from ordereddict import OrderedDict
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
49
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
50 try:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
51 from collections.abc import Mapping
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
52 except ImportError:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
53 from collections import Mapping
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
54
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
55 from pip._vendor import pkg_resources
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
56 try:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
57 from pip._internal.operations.freeze import FrozenRequirement
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
58 except ImportError:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
59 from pip import FrozenRequirement
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
60
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
61
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
62 __version__ = '2.2.1'
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
63
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
64
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
65 flatten = chain.from_iterable
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
66
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
67
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
68 def sorted_tree(tree):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
69 """Sorts the dict representation of the tree
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
70
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
71 The root packages as well as the intermediate packages are sorted
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
72 in the alphabetical order of the package names.
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
73
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
74 :param dict tree: the pkg dependency tree obtained by calling
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
75 `construct_tree` function
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
76 :returns: sorted tree
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
77 :rtype: collections.OrderedDict
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
78
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
79 """
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
80 return OrderedDict([(k, sorted(v)) for k, v in sorted(tree.items())])
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
81
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
82
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
83 def guess_version(pkg_key, default='?'):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
84 """Guess the version of a pkg when pip doesn't provide it
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
85
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
86 :param str pkg_key: key of the package
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
87 :param str default: default version to return if unable to find
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
88 :returns: version
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
89 :rtype: string
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
90
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
91 """
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
92 try:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
93 m = import_module(pkg_key)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
94 except ImportError:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
95 return default
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
96 else:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
97 v = getattr(m, '__version__', default)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
98 if inspect.ismodule(v):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
99 return getattr(v, '__version__', default)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
100 else:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
101 return v
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
102
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
103
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
104 def frozen_req_from_dist(dist):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
105 # The `pip._internal.metadata` modules were introduced in 21.1.1
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
106 # and the `pip._internal.operations.freeze.FrozenRequirement`
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
107 # class now expects dist to be a subclass of
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
108 # `pip._internal.metadata.BaseDistribution`, however the
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
109 # `pip._internal.utils.misc.get_installed_distributions` continues
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
110 # to return objects of type
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
111 # pip._vendor.pkg_resources.DistInfoDistribution.
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
112 #
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
113 # This is a hacky backward compatible (with older versions of pip)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
114 # fix.
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
115 try:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
116 from pip._internal import metadata
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
117 except ImportError:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
118 pass
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
119 else:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
120 dist = metadata.pkg_resources.Distribution(dist)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
121
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
122 try:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
123 return FrozenRequirement.from_dist(dist)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
124 except TypeError:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
125 return FrozenRequirement.from_dist(dist, [])
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
126
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
127
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
128 class Package(object):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
129 """Abstract class for wrappers around objects that pip returns.
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
130
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
131 This class needs to be subclassed with implementations for
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
132 `render_as_root` and `render_as_branch` methods.
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
133
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
134 """
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
135
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
136 def __init__(self, obj):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
137 self._obj = obj
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
138 self.project_name = obj.project_name
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
139 self.key = obj.key
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
140
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
141 def render_as_root(self, frozen):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
142 return NotImplementedError
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
143
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
144 def render_as_branch(self, frozen):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
145 return NotImplementedError
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
146
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
147 def render(self, parent=None, frozen=False):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
148 if not parent:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
149 return self.render_as_root(frozen)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
150 else:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
151 return self.render_as_branch(frozen)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
152
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
153 @staticmethod
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
154 def frozen_repr(obj):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
155 fr = frozen_req_from_dist(obj)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
156 return str(fr).strip()
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
157
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
158 def __getattr__(self, key):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
159 return getattr(self._obj, key)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
160
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
161 def __repr__(self):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
162 return '<{0}("{1}")>'.format(self.__class__.__name__, self.key)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
163
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
164 def __lt__(self, rhs):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
165 return self.key < rhs.key
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
166
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
167
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
168 class DistPackage(Package):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
169 """Wrapper class for pkg_resources.Distribution instances
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
170
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
171 :param obj: pkg_resources.Distribution to wrap over
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
172 :param req: optional ReqPackage object to associate this
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
173 DistPackage with. This is useful for displaying the
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
174 tree in reverse
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
175 """
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
176
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
177 def __init__(self, obj, req=None):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
178 super(DistPackage, self).__init__(obj)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
179 self.version_spec = None
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
180 self.req = req
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
181
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
182 def render_as_root(self, frozen):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
183 if not frozen:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
184 return '{0}=={1}'.format(self.project_name, self.version)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
185 else:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
186 return self.__class__.frozen_repr(self._obj)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
187
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
188 def render_as_branch(self, frozen):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
189 assert self.req is not None
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
190 if not frozen:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
191 parent_ver_spec = self.req.version_spec
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
192 parent_str = self.req.project_name
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
193 if parent_ver_spec:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
194 parent_str += parent_ver_spec
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
195 return (
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
196 '{0}=={1} [requires: {2}]'
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
197 ).format(self.project_name, self.version, parent_str)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
198 else:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
199 return self.render_as_root(frozen)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
200
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
201 def as_requirement(self):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
202 """Return a ReqPackage representation of this DistPackage"""
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
203 return ReqPackage(self._obj.as_requirement(), dist=self)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
204
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
205 def as_parent_of(self, req):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
206 """Return a DistPackage instance associated to a requirement
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
207
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
208 This association is necessary for reversing the PackageDAG.
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
209
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
210 If `req` is None, and the `req` attribute of the current
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
211 instance is also None, then the same instance will be
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
212 returned.
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
213
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
214 :param ReqPackage req: the requirement to associate with
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
215 :returns: DistPackage instance
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
216
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
217 """
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
218 if req is None and self.req is None:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
219 return self
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
220 return self.__class__(self._obj, req)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
221
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
222 def as_dict(self):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
223 return {'key': self.key,
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
224 'package_name': self.project_name,
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
225 'installed_version': self.version}
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
226
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
227
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
228 class ReqPackage(Package):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
229 """Wrapper class for Requirements instance
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
230
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
231 :param obj: The `Requirements` instance to wrap over
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
232 :param dist: optional `pkg_resources.Distribution` instance for
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
233 this requirement
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
234 """
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
235
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
236 UNKNOWN_VERSION = '?'
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
237
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
238 def __init__(self, obj, dist=None):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
239 super(ReqPackage, self).__init__(obj)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
240 self.dist = dist
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
241
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
242 @property
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
243 def version_spec(self):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
244 specs = sorted(self._obj.specs, reverse=True) # `reverse` makes '>' prior to '<'
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
245 return ','.join([''.join(sp) for sp in specs]) if specs else None
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
246
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
247 @property
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
248 def installed_version(self):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
249 if not self.dist:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
250 return guess_version(self.key, self.UNKNOWN_VERSION)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
251 return self.dist.version
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
252
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
253 @property
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
254 def is_missing(self):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
255 return self.installed_version == self.UNKNOWN_VERSION
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
256
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
257 def is_conflicting(self):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
258 """If installed version conflicts with required version"""
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
259 # unknown installed version is also considered conflicting
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
260 if self.installed_version == self.UNKNOWN_VERSION:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
261 return True
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
262 ver_spec = (self.version_spec if self.version_spec else '')
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
263 req_version_str = '{0}{1}'.format(self.project_name, ver_spec)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
264 req_obj = pkg_resources.Requirement.parse(req_version_str)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
265 return self.installed_version not in req_obj
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
266
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
267 def render_as_root(self, frozen):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
268 if not frozen:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
269 return '{0}=={1}'.format(self.project_name, self.installed_version)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
270 elif self.dist:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
271 return self.__class__.frozen_repr(self.dist._obj)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
272 else:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
273 return self.project_name
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
274
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
275 def render_as_branch(self, frozen):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
276 if not frozen:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
277 req_ver = self.version_spec if self.version_spec else 'Any'
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
278 return (
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
279 '{0} [required: {1}, installed: {2}]'
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
280 ).format(self.project_name, req_ver, self.installed_version)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
281 else:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
282 return self.render_as_root(frozen)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
283
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
284 def as_dict(self):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
285 return {'key': self.key,
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
286 'package_name': self.project_name,
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
287 'installed_version': self.installed_version,
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
288 'required_version': self.version_spec}
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
289
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
290
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
291 class PackageDAG(Mapping):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
292 """Representation of Package dependencies as directed acyclic graph
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
293 using a dict (Mapping) as the underlying datastructure.
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
294
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
295 The nodes and their relationships (edges) are internally
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
296 stored using a map as follows,
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
297
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
298 {a: [b, c],
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
299 b: [d],
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
300 c: [d, e],
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
301 d: [e],
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
302 e: [],
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
303 f: [b],
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
304 g: [e, f]}
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
305
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
306 Here, node `a` has 2 children nodes `b` and `c`. Consider edge
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
307 direction from `a` -> `b` and `a` -> `c` respectively.
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
308
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
309 A node is expected to be an instance of a subclass of
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
310 `Package`. The keys are must be of class `DistPackage` and each
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
311 item in values must be of class `ReqPackage`. (See also
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
312 ReversedPackageDAG where the key and value types are
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
313 interchanged).
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
314
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
315 """
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
316
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
317 @classmethod
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
318 def from_pkgs(cls, pkgs):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
319 pkgs = [DistPackage(p) for p in pkgs]
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
320 idx = {p.key: p for p in pkgs}
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
321 m = {p: [ReqPackage(r, idx.get(r.key))
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
322 for r in p.requires()]
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
323 for p in pkgs}
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
324 return cls(m)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
325
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
326 def __init__(self, m):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
327 """Initialize the PackageDAG object
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
328
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
329 :param dict m: dict of node objects (refer class docstring)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
330 :returns: None
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
331 :rtype: NoneType
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
332
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
333 """
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
334 self._obj = m
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
335 self._index = {p.key: p for p in list(self._obj)}
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
336
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
337 def get_node_as_parent(self, node_key):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
338 """Get the node from the keys of the dict representing the DAG.
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
339
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
340 This method is useful if the dict representing the DAG
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
341 contains different kind of objects in keys and values. Use
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
342 this method to lookup a node obj as a parent (from the keys of
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
343 the dict) given a node key.
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
344
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
345 :param node_key: identifier corresponding to key attr of node obj
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
346 :returns: node obj (as present in the keys of the dict)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
347 :rtype: Object
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
348
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
349 """
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
350 try:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
351 return self._index[node_key]
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
352 except KeyError:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
353 return None
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
354
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
355 def get_children(self, node_key):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
356 """Get child nodes for a node by it's key
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
357
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
358 :param str node_key: key of the node to get children of
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
359 :returns: list of child nodes
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
360 :rtype: ReqPackage[]
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
361
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
362 """
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
363 node = self.get_node_as_parent(node_key)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
364 return self._obj[node] if node else []
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
365
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
366 def filter(self, include, exclude):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
367 """Filters nodes in a graph by given parameters
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
368
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
369 If a node is included, then all it's children are also
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
370 included.
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
371
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
372 :param set include: set of node keys to include (or None)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
373 :param set exclude: set of node keys to exclude (or None)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
374 :returns: filtered version of the graph
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
375 :rtype: PackageDAG
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
376
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
377 """
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
378 # If neither of the filters are specified, short circuit
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
379 if include is None and exclude is None:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
380 return self
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
381
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
382 # Note: In following comparisons, we use lower cased values so
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
383 # that user may specify `key` or `project_name`. As per the
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
384 # documentation, `key` is simply
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
385 # `project_name.lower()`. Refer:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
386 # https://setuptools.readthedocs.io/en/latest/pkg_resources.html#distribution-objects
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
387 if include:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
388 include = set([s.lower() for s in include])
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
389 if exclude:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
390 exclude = set([s.lower() for s in exclude])
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
391 else:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
392 exclude = set([])
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
393
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
394 # Check for mutual exclusion of show_only and exclude sets
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
395 # after normalizing the values to lowercase
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
396 if include and exclude:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
397 assert not (include & exclude)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
398
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
399 # Traverse the graph in a depth first manner and filter the
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
400 # nodes according to `show_only` and `exclude` sets
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
401 stack = deque()
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
402 m = {}
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
403 seen = set([])
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
404 for node in self._obj.keys():
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
405 if node.key in exclude:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
406 continue
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
407 if include is None or node.key in include:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
408 stack.append(node)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
409 while True:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
410 if len(stack) > 0:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
411 n = stack.pop()
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
412 cldn = [c for c in self._obj[n]
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
413 if c.key not in exclude]
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
414 m[n] = cldn
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
415 seen.add(n.key)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
416 for c in cldn:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
417 if c.key not in seen:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
418 cld_node = self.get_node_as_parent(c.key)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
419 if cld_node:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
420 stack.append(cld_node)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
421 else:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
422 # It means there's no root node
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
423 # corresponding to the child node
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
424 # ie. a dependency is missing
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
425 continue
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
426 else:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
427 break
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
428
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
429 return self.__class__(m)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
430
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
431 def reverse(self):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
432 """Reverse the DAG, or turn it upside-down
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
433
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
434 In other words, the directions of edges of the nodes in the
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
435 DAG will be reversed.
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
436
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
437 Note that this function purely works on the nodes in the
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
438 graph. This implies that to perform a combination of filtering
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
439 and reversing, the order in which `filter` and `reverse`
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
440 methods should be applied is important. For eg. if reverse is
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
441 called on a filtered graph, then only the filtered nodes and
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
442 it's children will be considered when reversing. On the other
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
443 hand, if filter is called on reversed DAG, then the definition
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
444 of "child" nodes is as per the reversed DAG.
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
445
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
446 :returns: DAG in the reversed form
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
447 :rtype: ReversedPackageDAG
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
448
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
449 """
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
450 m = defaultdict(list)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
451 child_keys = set(r.key for r in flatten(self._obj.values()))
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
452 for k, vs in self._obj.items():
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
453 for v in vs:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
454 # if v is already added to the dict, then ensure that
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
455 # we are using the same object. This check is required
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
456 # as we're using array mutation
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
457 try:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
458 node = [p for p in m.keys() if p.key == v.key][0]
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
459 except IndexError:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
460 node = v
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
461 m[node].append(k.as_parent_of(v))
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
462 if k.key not in child_keys:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
463 m[k.as_requirement()] = []
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
464 return ReversedPackageDAG(dict(m))
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
465
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
466 def sort(self):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
467 """Return sorted tree in which the underlying _obj dict is an
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
468 OrderedDict, sorted alphabetically by the keys
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
469
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
470 :returns: Instance of same class with OrderedDict
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
471
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
472 """
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
473 return self.__class__(sorted_tree(self._obj))
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
474
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
475 # Methods required by the abstract base class Mapping
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
476 def __getitem__(self, *args):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
477 return self._obj.get(*args)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
478
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
479 def __iter__(self):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
480 return self._obj.__iter__()
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
481
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
482 def __len__(self):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
483 return len(self._obj)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
484
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
485
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
486 class ReversedPackageDAG(PackageDAG):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
487 """Representation of Package dependencies in the reverse
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
488 order.
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
489
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
490 Similar to it's super class `PackageDAG`, the underlying
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
491 datastructure is a dict, but here the keys are expected to be of
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
492 type `ReqPackage` and each item in the values of type
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
493 `DistPackage`.
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
494
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
495 Typically, this object will be obtained by calling
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
496 `PackageDAG.reverse`.
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
497
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
498 """
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
499
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
500 def reverse(self):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
501 """Reverse the already reversed DAG to get the PackageDAG again
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
502
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
503 :returns: reverse of the reversed DAG
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
504 :rtype: PackageDAG
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
505
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
506 """
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
507 m = defaultdict(list)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
508 child_keys = set(r.key for r in flatten(self._obj.values()))
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
509 for k, vs in self._obj.items():
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
510 for v in vs:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
511 try:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
512 node = [p for p in m.keys() if p.key == v.key][0]
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
513 except IndexError:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
514 node = v.as_parent_of(None)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
515 m[node].append(k)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
516 if k.key not in child_keys:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
517 m[k.dist] = []
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
518 return PackageDAG(dict(m))
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
519
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
520
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
521 def render_text(tree, list_all=True, frozen=False):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
522 """Print tree as text on console
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
523
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
524 :param dict tree: the package tree
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
525 :param bool list_all: whether to list all the pgks at the root
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
526 level or only those that are the
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
527 sub-dependencies
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
528 :param bool frozen: whether or not show the names of the pkgs in
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
529 the output that's favourable to pip --freeze
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
530 :returns: None
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
531
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
532 """
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
533 tree = tree.sort()
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
534 nodes = tree.keys()
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
535 branch_keys = set(r.key for r in flatten(tree.values()))
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
536 use_bullets = not frozen
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
537
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
538 if not list_all:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
539 nodes = [p for p in nodes if p.key not in branch_keys]
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
540
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
541 def aux(node, parent=None, indent=0, chain=None):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
542 chain = chain or []
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
543 node_str = node.render(parent, frozen)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
544 if parent:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
545 prefix = ' '*indent + ('- ' if use_bullets else '')
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
546 node_str = prefix + node_str
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
547 result = [node_str]
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
548 children = [aux(c, node, indent=indent+2,
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
549 chain=chain+[c.project_name])
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
550 for c in tree.get_children(node.key)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
551 if c.project_name not in chain]
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
552 result += list(flatten(children))
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
553 return result
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
554
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
555 lines = flatten([aux(p) for p in nodes])
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
556 print('\n'.join(lines))
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
557
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
558
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
559 def render_json(tree, indent):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
560 """Converts the tree into a flat json representation.
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
561
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
562 The json repr will be a list of hashes, each hash having 2 fields:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
563 - package
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
564 - dependencies: list of dependencies
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
565
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
566 :param dict tree: dependency tree
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
567 :param int indent: no. of spaces to indent json
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
568 :returns: json representation of the tree
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
569 :rtype: str
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
570
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
571 """
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
572 tree = tree.sort()
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
573 return json.dumps([{'package': k.as_dict(),
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
574 'dependencies': [v.as_dict() for v in vs]}
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
575 for k, vs in tree.items()],
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
576 indent=indent)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
577
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
578
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
579 def render_json_tree(tree, indent):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
580 """Converts the tree into a nested json representation.
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
581
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
582 The json repr will be a list of hashes, each hash having the following fields:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
583 - package_name
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
584 - key
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
585 - required_version
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
586 - installed_version
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
587 - dependencies: list of dependencies
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
588
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
589 :param dict tree: dependency tree
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
590 :param int indent: no. of spaces to indent json
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
591 :returns: json representation of the tree
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
592 :rtype: str
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
593
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
594 """
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
595 tree = tree.sort()
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
596 branch_keys = set(r.key for r in flatten(tree.values()))
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
597 nodes = [p for p in tree.keys() if p.key not in branch_keys]
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
598
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
599 def aux(node, parent=None, chain=None):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
600 if chain is None:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
601 chain = [node.project_name]
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
602
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
603 d = node.as_dict()
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
604 if parent:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
605 d['required_version'] = node.version_spec if node.version_spec else 'Any'
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
606 else:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
607 d['required_version'] = d['installed_version']
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
608
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
609 d['dependencies'] = [
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
610 aux(c, parent=node, chain=chain+[c.project_name])
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
611 for c in tree.get_children(node.key)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
612 if c.project_name not in chain
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
613 ]
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
614
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
615 return d
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
616
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
617 return json.dumps([aux(p) for p in nodes], indent=indent)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
618
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
619
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
620 def dump_graphviz(tree, output_format='dot', is_reverse=False):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
621 """Output dependency graph as one of the supported GraphViz output formats.
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
622
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
623 :param dict tree: dependency graph
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
624 :param string output_format: output format
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
625 :returns: representation of tree in the specified output format
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
626 :rtype: str or binary representation depending on the output format
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
627
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
628 """
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
629 try:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
630 from graphviz import Digraph
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
631 except ImportError:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
632 print('graphviz is not available, but necessary for the output '
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
633 'option. Please install it.', file=sys.stderr)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
634 sys.exit(1)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
635
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
636 try:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
637 from graphviz import parameters
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
638 except ImportError:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
639 from graphviz import backend
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
640 valid_formats = backend.FORMATS
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
641 print('Deprecation warning! Please upgrade graphviz to version >=0.18.0 '
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
642 'Support for older versions will be removed in upcoming release',
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
643 file=sys.stderr)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
644 else:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
645 valid_formats = parameters.FORMATS
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
646
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
647 if output_format not in valid_formats:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
648 print('{0} is not a supported output format.'.format(output_format),
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
649 file=sys.stderr)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
650 print('Supported formats are: {0}'.format(
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
651 ', '.join(sorted(valid_formats))), file=sys.stderr)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
652 sys.exit(1)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
653
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
654 graph = Digraph(format=output_format)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
655
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
656 if not is_reverse:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
657 for pkg, deps in tree.items():
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
658 pkg_label = '{0}\\n{1}'.format(pkg.project_name, pkg.version)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
659 graph.node(pkg.key, label=pkg_label)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
660 for dep in deps:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
661 edge_label = dep.version_spec or 'any'
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
662 if dep.is_missing:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
663 dep_label = '{0}\\n(missing)'.format(dep.project_name)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
664 graph.node(dep.key, label=dep_label, style='dashed')
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
665 graph.edge(pkg.key, dep.key, style='dashed')
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
666 else:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
667 graph.edge(pkg.key, dep.key, label=edge_label)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
668 else:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
669 for dep, parents in tree.items():
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
670 dep_label = '{0}\\n{1}'.format(dep.project_name,
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
671 dep.installed_version)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
672 graph.node(dep.key, label=dep_label)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
673 for parent in parents:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
674 # req reference of the dep associated with this
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
675 # particular parent package
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
676 req_ref = parent.req
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
677 edge_label = req_ref.version_spec or 'any'
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
678 graph.edge(dep.key, parent.key, label=edge_label)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
679
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
680 # Allow output of dot format, even if GraphViz isn't installed.
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
681 if output_format == 'dot':
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
682 return graph.source
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
683
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
684 # As it's unknown if the selected output format is binary or not, try to
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
685 # decode it as UTF8 and only print it out in binary if that's not possible.
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
686 try:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
687 return graph.pipe().decode('utf-8')
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
688 except UnicodeDecodeError:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
689 return graph.pipe()
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
690
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
691
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
692 def print_graphviz(dump_output):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
693 """Dump the data generated by GraphViz to stdout.
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
694
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
695 :param dump_output: The output from dump_graphviz
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
696 """
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
697 if hasattr(dump_output, 'encode'):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
698 print(dump_output)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
699 else:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
700 with os.fdopen(sys.stdout.fileno(), 'wb') as bytestream:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
701 bytestream.write(dump_output)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
702
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
703
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
704 def conflicting_deps(tree):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
705 """Returns dependencies which are not present or conflict with the
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
706 requirements of other packages.
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
707
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
708 e.g. will warn if pkg1 requires pkg2==2.0 and pkg2==1.0 is installed
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
709
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
710 :param tree: the requirements tree (dict)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
711 :returns: dict of DistPackage -> list of unsatisfied/unknown ReqPackage
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
712 :rtype: dict
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
713
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
714 """
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
715 conflicting = defaultdict(list)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
716 for p, rs in tree.items():
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
717 for req in rs:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
718 if req.is_conflicting():
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
719 conflicting[p].append(req)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
720 return conflicting
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
721
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
722
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
723 def render_conflicts_text(conflicts):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
724 if conflicts:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
725 print('Warning!!! Possibly conflicting dependencies found:',
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
726 file=sys.stderr)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
727 # Enforce alphabetical order when listing conflicts
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
728 pkgs = sorted(conflicts.keys())
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
729 for p in pkgs:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
730 pkg = p.render_as_root(False)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
731 print('* {}'.format(pkg), file=sys.stderr)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
732 for req in conflicts[p]:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
733 req_str = req.render_as_branch(False)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
734 print(' - {}'.format(req_str), file=sys.stderr)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
735
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
736
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
737 def cyclic_deps(tree):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
738 """Return cyclic dependencies as list of tuples
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
739
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
740 :param PackageDAG pkgs: package tree/dag
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
741 :returns: list of tuples representing cyclic dependencies
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
742 :rtype: list
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
743
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
744 """
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
745 index = {p.key: set([r.key for r in rs]) for p, rs in tree.items()}
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
746 cyclic = []
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
747 for p, rs in tree.items():
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
748 for r in rs:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
749 if p.key in index.get(r.key, []):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
750 p_as_dep_of_r = [x for x
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
751 in tree.get(tree.get_node_as_parent(r.key))
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
752 if x.key == p.key][0]
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
753 cyclic.append((p, r, p_as_dep_of_r))
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
754 return cyclic
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
755
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
756
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
757 def render_cycles_text(cycles):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
758 if cycles:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
759 print('Warning!! Cyclic dependencies found:', file=sys.stderr)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
760 # List in alphabetical order of the dependency that's cycling
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
761 # (2nd item in the tuple)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
762 cycles = sorted(cycles, key=lambda xs: xs[1].key)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
763 for a, b, c in cycles:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
764 print('* {0} => {1} => {2}'.format(a.project_name,
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
765 b.project_name,
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
766 c.project_name),
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
767 file=sys.stderr)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
768
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
769
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
770 def get_parser():
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
771 parser = argparse.ArgumentParser(description=(
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
772 'Dependency tree of the installed python packages'
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
773 ))
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
774 parser.add_argument('-v', '--version', action='version',
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
775 version='{0}'.format(__version__))
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
776 parser.add_argument('-f', '--freeze', action='store_true',
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
777 help='Print names so as to write freeze files')
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
778 parser.add_argument('--python', default=sys.executable,
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
779 help='Python to use to look for packages in it (default: where'
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
780 ' installed)')
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
781 parser.add_argument('-a', '--all', action='store_true',
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
782 help='list all deps at top level')
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
783 parser.add_argument('-l', '--local-only',
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
784 action='store_true', help=(
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
785 'If in a virtualenv that has global access '
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
786 'do not show globally installed packages'
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
787 ))
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
788 parser.add_argument('-u', '--user-only', action='store_true',
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
789 help=(
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
790 'Only show installations in the user site dir'
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
791 ))
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
792 parser.add_argument('-w', '--warn', action='store', dest='warn',
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
793 nargs='?', default='suppress',
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
794 choices=('silence', 'suppress', 'fail'),
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
795 help=(
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
796 'Warning control. "suppress" will show warnings '
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
797 'but return 0 whether or not they are present. '
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
798 '"silence" will not show warnings at all and '
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
799 'always return 0. "fail" will show warnings and '
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
800 'return 1 if any are present. The default is '
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
801 '"suppress".'
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
802 ))
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
803 parser.add_argument('-r', '--reverse', action='store_true',
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
804 default=False, help=(
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
805 'Shows the dependency tree in the reverse fashion '
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
806 'ie. the sub-dependencies are listed with the '
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
807 'list of packages that need them under them.'
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
808 ))
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
809 parser.add_argument('-p', '--packages',
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
810 help=(
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
811 'Comma separated list of select packages to show '
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
812 'in the output. If set, --all will be ignored.'
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
813 ))
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
814 parser.add_argument('-e', '--exclude',
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
815 help=(
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
816 'Comma separated list of select packages to exclude '
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
817 'from the output. If set, --all will be ignored.'
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
818 ), metavar='PACKAGES')
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
819 parser.add_argument('-j', '--json', action='store_true', default=False,
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
820 help=(
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
821 'Display dependency tree as json. This will yield '
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
822 '"raw" output that may be used by external tools. '
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
823 'This option overrides all other options.'
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
824 ))
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
825 parser.add_argument('--json-tree', action='store_true', default=False,
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
826 help=(
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
827 'Display dependency tree as json which is nested '
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
828 'the same way as the plain text output printed by default. '
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
829 'This option overrides all other options (except --json).'
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
830 ))
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
831 parser.add_argument('--graph-output', dest='output_format',
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
832 help=(
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
833 'Print a dependency graph in the specified output '
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
834 'format. Available are all formats supported by '
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
835 'GraphViz, e.g.: dot, jpeg, pdf, png, svg'
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
836 ))
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
837 return parser
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
838
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
839
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
840 def _get_args():
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
841 parser = get_parser()
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
842 return parser.parse_args()
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
843
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
844
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
845 def handle_non_host_target(args):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
846 of_python = os.path.abspath(args.python)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
847 # if target is not current python re-invoke it under the actual host
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
848 if of_python != os.path.abspath(sys.executable):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
849 # there's no way to guarantee that graphviz is available, so refuse
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
850 if args.output_format:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
851 print("graphviz functionality is not supported when querying"
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
852 " non-host python", file=sys.stderr)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
853 raise SystemExit(1)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
854 argv = sys.argv[1:] # remove current python executable
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
855 for py_at, value in enumerate(argv):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
856 if value == "--python":
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
857 del argv[py_at]
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
858 del argv[py_at]
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
859 elif value.startswith("--python"):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
860 del argv[py_at]
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
861 # feed the file as argument, instead of file
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
862 # to avoid adding the file path to sys.path, that can affect result
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
863 file_path = inspect.getsourcefile(sys.modules[__name__])
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
864 with open(file_path, 'rt') as file_handler:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
865 content = file_handler.read()
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
866 cmd = [of_python, "-c", content]
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
867 cmd.extend(argv)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
868 # invoke from an empty folder to avoid cwd altering sys.path
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
869 cwd = tempfile.mkdtemp()
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
870 try:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
871 return subprocess.call(cmd, cwd=cwd)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
872 finally:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
873 os.removedirs(cwd)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
874 return None
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
875
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
876
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
877 def get_installed_distributions(local_only=False, user_only=False):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
878 try:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
879 from pip._internal.metadata import get_environment
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
880 except ImportError:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
881 # For backward compatibility with python ver. 2.7 and pip
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
882 # version 20.3.4 (latest pip version that works with python
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
883 # version 2.7)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
884 from pip._internal.utils import misc
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
885 return misc.get_installed_distributions(
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
886 local_only=local_only,
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
887 user_only=user_only
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
888 )
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
889 else:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
890 dists = get_environment(None).iter_installed_distributions(
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
891 local_only=local_only,
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
892 skip=(),
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
893 user_only=user_only
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
894 )
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
895 return [d._dist for d in dists]
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
896
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
897
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
898 def main():
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
899 os.environ["_PIP_USE_IMPORTLIB_METADATA"] = "False"
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
900 # patched for 3.11+ compatibility
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
901
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
902 args = _get_args()
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
903 result = handle_non_host_target(args)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
904 if result is not None:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
905 return result
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
906
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
907 pkgs = get_installed_distributions(local_only=args.local_only,
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
908 user_only=args.user_only)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
909
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
910 tree = PackageDAG.from_pkgs(pkgs)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
911
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
912 is_text_output = not any([args.json, args.json_tree, args.output_format])
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
913
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
914 return_code = 0
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
915
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
916 # Before any reversing or filtering, show warnings to console
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
917 # about possibly conflicting or cyclic deps if found and warnings
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
918 # are enabled (ie. only if output is to be printed to console)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
919 if is_text_output and args.warn != 'silence':
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
920 conflicts = conflicting_deps(tree)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
921 if conflicts:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
922 render_conflicts_text(conflicts)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
923 print('-'*72, file=sys.stderr)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
924
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
925 cycles = cyclic_deps(tree)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
926 if cycles:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
927 render_cycles_text(cycles)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
928 print('-'*72, file=sys.stderr)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
929
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
930 if args.warn == 'fail' and (conflicts or cycles):
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
931 return_code = 1
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
932
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
933 # Reverse the tree (if applicable) before filtering, thus ensuring
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
934 # that the filter will be applied on ReverseTree
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
935 if args.reverse:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
936 tree = tree.reverse()
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
937
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
938 show_only = set(args.packages.split(',')) if args.packages else None
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
939 exclude = set(args.exclude.split(',')) if args.exclude else None
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
940
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
941 if show_only is not None or exclude is not None:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
942 tree = tree.filter(show_only, exclude)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
943
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
944 if args.json:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
945 print(render_json(tree, indent=4))
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
946 elif args.json_tree:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
947 print(render_json_tree(tree, indent=4))
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
948 elif args.output_format:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
949 output = dump_graphviz(tree,
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
950 output_format=args.output_format,
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
951 is_reverse=args.reverse)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
952 print_graphviz(output)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
953 else:
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
954 render_text(tree, args.all, args.freeze)
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
955
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
956 return return_code
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
957
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
958
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
959 if __name__ == '__main__':
71cf3979a6c9 pip Interface
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
960 sys.exit(main())

eric ide

mercurial