| 319 | ALL = "all" |
| 320 | |
| 321 | class Graph(dict): |
| 322 | |
| 323 | def __init__(self, layout=SPRING, distance=10.0): |
| 324 | """ A network of nodes connected by edges that can be drawn with a given layout. |
| 325 | """ |
| 326 | self.nodes = [] # List of Node objects. |
| 327 | self.edges = [] # List of Edge objects. |
| 328 | self.root = None |
| 329 | self._adjacency = None # Cached adjacency() dict. |
| 330 | self.layout = layout==SPRING and GraphSpringLayout(self) or GraphLayout(self) |
| 331 | self.distance = distance |
| 332 | |
| 333 | def __getitem__(self, id): |
| 334 | try: |
| 335 | return dict.__getitem__(self, id) |
| 336 | except KeyError: |
| 337 | raise KeyError, "no node with id '%s' in graph" % id |
| 338 | |
| 339 | def append(self, base, *args, **kwargs): |
| 340 | """ Appends a Node or Edge to the graph: Graph.append(Node, id="rabbit"). |
| 341 | """ |
| 342 | kwargs["base"] = base |
| 343 | if issubclass(base, Node): |
| 344 | return self.add_node(*args, **kwargs) |
| 345 | if issubclass(base, Edge): |
| 346 | return self.add_edge(*args, **kwargs) |
| 347 | |
| 348 | def add_node(self, id, *args, **kwargs): |
| 349 | """ Appends a new Node to the graph. |
| 350 | An optional base parameter can be used to pass a subclass of Node. |
| 351 | """ |
| 352 | n = kwargs.pop("base", Node) |
| 353 | n = isinstance(id, Node) and id or self.get(id) or n(id, *args, **kwargs) |
| 354 | if n.id not in self: |
| 355 | self.nodes.append(n) |
| 356 | self[n.id] = n; n.graph = self |
| 357 | self.root = kwargs.get("root", False) and n or self.root |
| 358 | # Clear adjacency cache. |
| 359 | self._adjacency = None |
| 360 | return n |
| 361 | |
| 362 | def add_edge(self, id1, id2, *args, **kwargs): |
| 363 | """ Appends a new Edge to the graph. |
| 364 | An optional base parameter can be used to pass a subclass of Edge: |
| 365 | Graph.add_edge("cold", "winter", base=IsPropertyOf) |
| 366 | """ |
| 367 | # Create nodes that are not yet part of the graph. |
| 368 | n1 = self.add_node(id1) |
| 369 | n2 = self.add_node(id2) |
| 370 | # Creates an Edge instance. |
| 371 | # If an edge (in the same direction) already exists, yields that edge instead. |
| 372 | e1 = n1.links.edge(n2) |
| 373 | if e1 and e1.node1 == n1 and e1.node2 == n2: |
| 374 | return e1 |
| 375 | e2 = kwargs.pop("base", Edge) |
| 376 | e2 = e2(n1, n2, *args, **kwargs) |
| 377 | self.edges.append(e2) |
| 378 | # Synchronizes Node.links: |
no outgoing calls
no test coverage detected
searching dependent graphs…