Gentoo Archives: gentoo-commits

From: "Zac Medico (zmedico)" <zmedico@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] portage r15423 - in main/trunk/pym/portage: . util
Date: Mon, 22 Feb 2010 02:50:59
Message-Id: E1NjONn-0004wI-HD@stork.gentoo.org
1 Author: zmedico
2 Date: 2010-02-22 02:50:49 +0000 (Mon, 22 Feb 2010)
3 New Revision: 15423
4
5 Added:
6 main/trunk/pym/portage/util/digraph.py
7 Modified:
8 main/trunk/pym/portage/__init__.py
9 Log:
10 Move portage.digraph class to portage.util.digraph.digraph.
11
12
13 Modified: main/trunk/pym/portage/__init__.py
14 ===================================================================
15 --- main/trunk/pym/portage/__init__.py 2010-02-22 02:39:48 UTC (rev 15422)
16 +++ main/trunk/pym/portage/__init__.py 2010-02-22 02:50:49 UTC (rev 15423)
17 @@ -115,6 +115,7 @@
18 'pickle_read,pickle_write,stack_dictlist,stack_dicts,' + \
19 'stack_lists,unique_array,varexpand,writedict,writemsg,' + \
20 'writemsg_stdout,write_atomic',
21 + 'portage.util.digraph:digraph',
22 'portage.versions',
23 'portage.versions:best,catpkgsplit,catsplit,cpv_getkey,' + \
24 'cpv_getkey@getCPFromCPV,endversion_keys,' + \
25 @@ -679,282 +680,6 @@
26
27 return rlist
28
29 -#beautiful directed graph object
30 -
31 -class digraph(object):
32 - def __init__(self):
33 - """Create an empty digraph"""
34 -
35 - # { node : ( { child : priority } , { parent : priority } ) }
36 - self.nodes = {}
37 - self.order = []
38 -
39 - def add(self, node, parent, priority=0):
40 - """Adds the specified node with the specified parent.
41 -
42 - If the dep is a soft-dep and the node already has a hard
43 - relationship to the parent, the relationship is left as hard."""
44 -
45 - if node not in self.nodes:
46 - self.nodes[node] = ({}, {}, node)
47 - self.order.append(node)
48 -
49 - if not parent:
50 - return
51 -
52 - if parent not in self.nodes:
53 - self.nodes[parent] = ({}, {}, parent)
54 - self.order.append(parent)
55 -
56 - priorities = self.nodes[node][1].get(parent)
57 - if priorities is None:
58 - priorities = []
59 - self.nodes[node][1][parent] = priorities
60 - self.nodes[parent][0][node] = priorities
61 - priorities.append(priority)
62 - priorities.sort()
63 -
64 - def remove(self, node):
65 - """Removes the specified node from the digraph, also removing
66 - and ties to other nodes in the digraph. Raises KeyError if the
67 - node doesn't exist."""
68 -
69 - if node not in self.nodes:
70 - raise KeyError(node)
71 -
72 - for parent in self.nodes[node][1]:
73 - del self.nodes[parent][0][node]
74 - for child in self.nodes[node][0]:
75 - del self.nodes[child][1][node]
76 -
77 - del self.nodes[node]
78 - self.order.remove(node)
79 -
80 - def difference_update(self, t):
81 - """
82 - Remove all given nodes from node_set. This is more efficient
83 - than multiple calls to the remove() method.
84 - """
85 - if isinstance(t, (list, tuple)) or \
86 - not hasattr(t, "__contains__"):
87 - t = frozenset(t)
88 - order = []
89 - for node in self.order:
90 - if node not in t:
91 - order.append(node)
92 - continue
93 - for parent in self.nodes[node][1]:
94 - del self.nodes[parent][0][node]
95 - for child in self.nodes[node][0]:
96 - del self.nodes[child][1][node]
97 - del self.nodes[node]
98 - self.order = order
99 -
100 - def remove_edge(self, child, parent):
101 - """
102 - Remove edge in the direction from child to parent. Note that it is
103 - possible for a remaining edge to exist in the opposite direction.
104 - Any endpoint vertices that become isolated will remain in the graph.
105 - """
106 -
107 - # Nothing should be modified when a KeyError is raised.
108 - for k in parent, child:
109 - if k not in self.nodes:
110 - raise KeyError(k)
111 -
112 - # Make sure the edge exists.
113 - if child not in self.nodes[parent][0]:
114 - raise KeyError(child)
115 - if parent not in self.nodes[child][1]:
116 - raise KeyError(parent)
117 -
118 - # Remove the edge.
119 - del self.nodes[child][1][parent]
120 - del self.nodes[parent][0][child]
121 -
122 - def __iter__(self):
123 - return iter(self.order)
124 -
125 - def contains(self, node):
126 - """Checks if the digraph contains mynode"""
127 - return node in self.nodes
128 -
129 - def get(self, key, default=None):
130 - node_data = self.nodes.get(key, self)
131 - if node_data is self:
132 - return default
133 - return node_data[2]
134 -
135 - def all_nodes(self):
136 - """Return a list of all nodes in the graph"""
137 - return self.order[:]
138 -
139 - def child_nodes(self, node, ignore_priority=None):
140 - """Return all children of the specified node"""
141 - if ignore_priority is None:
142 - return list(self.nodes[node][0])
143 - children = []
144 - if hasattr(ignore_priority, '__call__'):
145 - for child, priorities in self.nodes[node][0].items():
146 - for priority in priorities:
147 - if not ignore_priority(priority):
148 - children.append(child)
149 - break
150 - else:
151 - for child, priorities in self.nodes[node][0].items():
152 - if ignore_priority < priorities[-1]:
153 - children.append(child)
154 - return children
155 -
156 - def parent_nodes(self, node, ignore_priority=None):
157 - """Return all parents of the specified node"""
158 - if ignore_priority is None:
159 - return list(self.nodes[node][1])
160 - parents = []
161 - if hasattr(ignore_priority, '__call__'):
162 - for parent, priorities in self.nodes[node][1].items():
163 - for priority in priorities:
164 - if not ignore_priority(priority):
165 - parents.append(parent)
166 - break
167 - else:
168 - for parent, priorities in self.nodes[node][1].items():
169 - if ignore_priority < priorities[-1]:
170 - parents.append(parent)
171 - return parents
172 -
173 - def leaf_nodes(self, ignore_priority=None):
174 - """Return all nodes that have no children
175 -
176 - If ignore_soft_deps is True, soft deps are not counted as
177 - children in calculations."""
178 -
179 - leaf_nodes = []
180 - if ignore_priority is None:
181 - for node in self.order:
182 - if not self.nodes[node][0]:
183 - leaf_nodes.append(node)
184 - elif hasattr(ignore_priority, '__call__'):
185 - for node in self.order:
186 - is_leaf_node = True
187 - for child, priorities in self.nodes[node][0].items():
188 - for priority in priorities:
189 - if not ignore_priority(priority):
190 - is_leaf_node = False
191 - break
192 - if not is_leaf_node:
193 - break
194 - if is_leaf_node:
195 - leaf_nodes.append(node)
196 - else:
197 - for node in self.order:
198 - is_leaf_node = True
199 - for child, priorities in self.nodes[node][0].items():
200 - if ignore_priority < priorities[-1]:
201 - is_leaf_node = False
202 - break
203 - if is_leaf_node:
204 - leaf_nodes.append(node)
205 - return leaf_nodes
206 -
207 - def root_nodes(self, ignore_priority=None):
208 - """Return all nodes that have no parents.
209 -
210 - If ignore_soft_deps is True, soft deps are not counted as
211 - parents in calculations."""
212 -
213 - root_nodes = []
214 - if ignore_priority is None:
215 - for node in self.order:
216 - if not self.nodes[node][1]:
217 - root_nodes.append(node)
218 - elif hasattr(ignore_priority, '__call__'):
219 - for node in self.order:
220 - is_root_node = True
221 - for parent, priorities in self.nodes[node][1].items():
222 - for priority in priorities:
223 - if not ignore_priority(priority):
224 - is_root_node = False
225 - break
226 - if not is_root_node:
227 - break
228 - if is_root_node:
229 - root_nodes.append(node)
230 - else:
231 - for node in self.order:
232 - is_root_node = True
233 - for parent, priorities in self.nodes[node][1].items():
234 - if ignore_priority < priorities[-1]:
235 - is_root_node = False
236 - break
237 - if is_root_node:
238 - root_nodes.append(node)
239 - return root_nodes
240 -
241 - def is_empty(self):
242 - """Checks if the digraph is empty"""
243 - return len(self.nodes) == 0
244 -
245 - def clone(self):
246 - clone = digraph()
247 - clone.nodes = {}
248 - memo = {}
249 - for children, parents, node in self.nodes.values():
250 - children_clone = {}
251 - for child, priorities in children.items():
252 - priorities_clone = memo.get(id(priorities))
253 - if priorities_clone is None:
254 - priorities_clone = priorities[:]
255 - memo[id(priorities)] = priorities_clone
256 - children_clone[child] = priorities_clone
257 - parents_clone = {}
258 - for parent, priorities in parents.items():
259 - priorities_clone = memo.get(id(priorities))
260 - if priorities_clone is None:
261 - priorities_clone = priorities[:]
262 - memo[id(priorities)] = priorities_clone
263 - parents_clone[parent] = priorities_clone
264 - clone.nodes[node] = (children_clone, parents_clone, node)
265 - clone.order = self.order[:]
266 - return clone
267 -
268 - # Backward compatibility
269 - addnode = add
270 - allnodes = all_nodes
271 - allzeros = leaf_nodes
272 - hasnode = contains
273 - __contains__ = contains
274 - empty = is_empty
275 - copy = clone
276 -
277 - def delnode(self, node):
278 - try:
279 - self.remove(node)
280 - except KeyError:
281 - pass
282 -
283 - def firstzero(self):
284 - leaf_nodes = self.leaf_nodes()
285 - if leaf_nodes:
286 - return leaf_nodes[0]
287 - return None
288 -
289 - def hasallzeros(self, ignore_priority=None):
290 - return len(self.leaf_nodes(ignore_priority=ignore_priority)) == \
291 - len(self.order)
292 -
293 - def debug_print(self):
294 - def output(s):
295 - writemsg(s, noiselevel=-1)
296 - for node in self.nodes:
297 - output("%s " % (node,))
298 - if self.nodes[node][0]:
299 - output("depends on\n")
300 - else:
301 - output("(no children)\n")
302 - for child, priorities in self.nodes[node][0].items():
303 - output(" %s (%s)\n" % (child, priorities[-1],))
304 -
305 #parse /etc/env.d and generate /etc/profile.env
306
307 def env_update(makelinks=1, target_root=None, prev_mtimes=None, contents=None,
308
309 Added: main/trunk/pym/portage/util/digraph.py
310 ===================================================================
311 --- main/trunk/pym/portage/util/digraph.py (rev 0)
312 +++ main/trunk/pym/portage/util/digraph.py 2010-02-22 02:50:49 UTC (rev 15423)
313 @@ -0,0 +1,281 @@
314 +# Copyright 2010 Gentoo Foundation
315 +# Distributed under the terms of the GNU General Public License v2
316 +# $Id$
317 +
318 +class digraph(object):
319 + """
320 + A directed graph object.
321 + """
322 +
323 + def __init__(self):
324 + """Create an empty digraph"""
325 +
326 + # { node : ( { child : priority } , { parent : priority } ) }
327 + self.nodes = {}
328 + self.order = []
329 +
330 + def add(self, node, parent, priority=0):
331 + """Adds the specified node with the specified parent.
332 +
333 + If the dep is a soft-dep and the node already has a hard
334 + relationship to the parent, the relationship is left as hard."""
335 +
336 + if node not in self.nodes:
337 + self.nodes[node] = ({}, {}, node)
338 + self.order.append(node)
339 +
340 + if not parent:
341 + return
342 +
343 + if parent not in self.nodes:
344 + self.nodes[parent] = ({}, {}, parent)
345 + self.order.append(parent)
346 +
347 + priorities = self.nodes[node][1].get(parent)
348 + if priorities is None:
349 + priorities = []
350 + self.nodes[node][1][parent] = priorities
351 + self.nodes[parent][0][node] = priorities
352 + priorities.append(priority)
353 + priorities.sort()
354 +
355 + def remove(self, node):
356 + """Removes the specified node from the digraph, also removing
357 + and ties to other nodes in the digraph. Raises KeyError if the
358 + node doesn't exist."""
359 +
360 + if node not in self.nodes:
361 + raise KeyError(node)
362 +
363 + for parent in self.nodes[node][1]:
364 + del self.nodes[parent][0][node]
365 + for child in self.nodes[node][0]:
366 + del self.nodes[child][1][node]
367 +
368 + del self.nodes[node]
369 + self.order.remove(node)
370 +
371 + def difference_update(self, t):
372 + """
373 + Remove all given nodes from node_set. This is more efficient
374 + than multiple calls to the remove() method.
375 + """
376 + if isinstance(t, (list, tuple)) or \
377 + not hasattr(t, "__contains__"):
378 + t = frozenset(t)
379 + order = []
380 + for node in self.order:
381 + if node not in t:
382 + order.append(node)
383 + continue
384 + for parent in self.nodes[node][1]:
385 + del self.nodes[parent][0][node]
386 + for child in self.nodes[node][0]:
387 + del self.nodes[child][1][node]
388 + del self.nodes[node]
389 + self.order = order
390 +
391 + def remove_edge(self, child, parent):
392 + """
393 + Remove edge in the direction from child to parent. Note that it is
394 + possible for a remaining edge to exist in the opposite direction.
395 + Any endpoint vertices that become isolated will remain in the graph.
396 + """
397 +
398 + # Nothing should be modified when a KeyError is raised.
399 + for k in parent, child:
400 + if k not in self.nodes:
401 + raise KeyError(k)
402 +
403 + # Make sure the edge exists.
404 + if child not in self.nodes[parent][0]:
405 + raise KeyError(child)
406 + if parent not in self.nodes[child][1]:
407 + raise KeyError(parent)
408 +
409 + # Remove the edge.
410 + del self.nodes[child][1][parent]
411 + del self.nodes[parent][0][child]
412 +
413 + def __iter__(self):
414 + return iter(self.order)
415 +
416 + def contains(self, node):
417 + """Checks if the digraph contains mynode"""
418 + return node in self.nodes
419 +
420 + def get(self, key, default=None):
421 + node_data = self.nodes.get(key, self)
422 + if node_data is self:
423 + return default
424 + return node_data[2]
425 +
426 + def all_nodes(self):
427 + """Return a list of all nodes in the graph"""
428 + return self.order[:]
429 +
430 + def child_nodes(self, node, ignore_priority=None):
431 + """Return all children of the specified node"""
432 + if ignore_priority is None:
433 + return list(self.nodes[node][0])
434 + children = []
435 + if hasattr(ignore_priority, '__call__'):
436 + for child, priorities in self.nodes[node][0].items():
437 + for priority in priorities:
438 + if not ignore_priority(priority):
439 + children.append(child)
440 + break
441 + else:
442 + for child, priorities in self.nodes[node][0].items():
443 + if ignore_priority < priorities[-1]:
444 + children.append(child)
445 + return children
446 +
447 + def parent_nodes(self, node, ignore_priority=None):
448 + """Return all parents of the specified node"""
449 + if ignore_priority is None:
450 + return list(self.nodes[node][1])
451 + parents = []
452 + if hasattr(ignore_priority, '__call__'):
453 + for parent, priorities in self.nodes[node][1].items():
454 + for priority in priorities:
455 + if not ignore_priority(priority):
456 + parents.append(parent)
457 + break
458 + else:
459 + for parent, priorities in self.nodes[node][1].items():
460 + if ignore_priority < priorities[-1]:
461 + parents.append(parent)
462 + return parents
463 +
464 + def leaf_nodes(self, ignore_priority=None):
465 + """Return all nodes that have no children
466 +
467 + If ignore_soft_deps is True, soft deps are not counted as
468 + children in calculations."""
469 +
470 + leaf_nodes = []
471 + if ignore_priority is None:
472 + for node in self.order:
473 + if not self.nodes[node][0]:
474 + leaf_nodes.append(node)
475 + elif hasattr(ignore_priority, '__call__'):
476 + for node in self.order:
477 + is_leaf_node = True
478 + for child, priorities in self.nodes[node][0].items():
479 + for priority in priorities:
480 + if not ignore_priority(priority):
481 + is_leaf_node = False
482 + break
483 + if not is_leaf_node:
484 + break
485 + if is_leaf_node:
486 + leaf_nodes.append(node)
487 + else:
488 + for node in self.order:
489 + is_leaf_node = True
490 + for child, priorities in self.nodes[node][0].items():
491 + if ignore_priority < priorities[-1]:
492 + is_leaf_node = False
493 + break
494 + if is_leaf_node:
495 + leaf_nodes.append(node)
496 + return leaf_nodes
497 +
498 + def root_nodes(self, ignore_priority=None):
499 + """Return all nodes that have no parents.
500 +
501 + If ignore_soft_deps is True, soft deps are not counted as
502 + parents in calculations."""
503 +
504 + root_nodes = []
505 + if ignore_priority is None:
506 + for node in self.order:
507 + if not self.nodes[node][1]:
508 + root_nodes.append(node)
509 + elif hasattr(ignore_priority, '__call__'):
510 + for node in self.order:
511 + is_root_node = True
512 + for parent, priorities in self.nodes[node][1].items():
513 + for priority in priorities:
514 + if not ignore_priority(priority):
515 + is_root_node = False
516 + break
517 + if not is_root_node:
518 + break
519 + if is_root_node:
520 + root_nodes.append(node)
521 + else:
522 + for node in self.order:
523 + is_root_node = True
524 + for parent, priorities in self.nodes[node][1].items():
525 + if ignore_priority < priorities[-1]:
526 + is_root_node = False
527 + break
528 + if is_root_node:
529 + root_nodes.append(node)
530 + return root_nodes
531 +
532 + def is_empty(self):
533 + """Checks if the digraph is empty"""
534 + return len(self.nodes) == 0
535 +
536 + def clone(self):
537 + clone = digraph()
538 + clone.nodes = {}
539 + memo = {}
540 + for children, parents, node in self.nodes.values():
541 + children_clone = {}
542 + for child, priorities in children.items():
543 + priorities_clone = memo.get(id(priorities))
544 + if priorities_clone is None:
545 + priorities_clone = priorities[:]
546 + memo[id(priorities)] = priorities_clone
547 + children_clone[child] = priorities_clone
548 + parents_clone = {}
549 + for parent, priorities in parents.items():
550 + priorities_clone = memo.get(id(priorities))
551 + if priorities_clone is None:
552 + priorities_clone = priorities[:]
553 + memo[id(priorities)] = priorities_clone
554 + parents_clone[parent] = priorities_clone
555 + clone.nodes[node] = (children_clone, parents_clone, node)
556 + clone.order = self.order[:]
557 + return clone
558 +
559 + def delnode(self, node):
560 + try:
561 + self.remove(node)
562 + except KeyError:
563 + pass
564 +
565 + def firstzero(self):
566 + leaf_nodes = self.leaf_nodes()
567 + if leaf_nodes:
568 + return leaf_nodes[0]
569 + return None
570 +
571 + def hasallzeros(self, ignore_priority=None):
572 + return len(self.leaf_nodes(ignore_priority=ignore_priority)) == \
573 + len(self.order)
574 +
575 + def debug_print(self):
576 + def output(s):
577 + writemsg(s, noiselevel=-1)
578 + for node in self.nodes:
579 + output("%s " % (node,))
580 + if self.nodes[node][0]:
581 + output("depends on\n")
582 + else:
583 + output("(no children)\n")
584 + for child, priorities in self.nodes[node][0].items():
585 + output(" %s (%s)\n" % (child, priorities[-1],))
586 +
587 + # Backward compatibility
588 + addnode = add
589 + allnodes = all_nodes
590 + allzeros = leaf_nodes
591 + hasnode = contains
592 + __contains__ = contains
593 + empty = is_empty
594 + copy = clone
595
596
597 Property changes on: main/trunk/pym/portage/util/digraph.py
598 ___________________________________________________________________
599 Added: svn:keywords
600 + Id