Mercurial > hg > WSGraph
annotate wsgraph/model.py @ 26:60d7e38a20cd
mostly notes to self
author | Jeff Hammel <jhammel@mozilla.com> |
---|---|
date | Wed, 12 Dec 2012 18:42:13 -0800 |
parents | d1a8c1436ded |
children | 4bed1424bb3f |
rev | line source |
---|---|
0 | 1 from abc import abstractmethod |
9
0affca1f4dc0
start using deepcopy since lord knows we cant trust users
Jeff Hammel <jhammel@mozilla.com>
parents:
8
diff
changeset
|
2 from copy import deepcopy |
15 | 3 from utils import isiterable |
0 | 4 |
25 | 5 class Graph(object): |
0 | 6 |
7 @abstractmethod | |
8 def node(self, name, **values): | |
10
81d68388ec97
some nonsense about how this model is full of holes and how it should be better
Jeff Hammel <jhammel@mozilla.com>
parents:
9
diff
changeset
|
9 """ |
81d68388ec97
some nonsense about how this model is full of holes and how it should be better
Jeff Hammel <jhammel@mozilla.com>
parents:
9
diff
changeset
|
10 get or set a node |
81d68388ec97
some nonsense about how this model is full of holes and how it should be better
Jeff Hammel <jhammel@mozilla.com>
parents:
9
diff
changeset
|
11 |
81d68388ec97
some nonsense about how this model is full of holes and how it should be better
Jeff Hammel <jhammel@mozilla.com>
parents:
9
diff
changeset
|
12 When setting a node, a value of `None` will pop the value from |
81d68388ec97
some nonsense about how this model is full of holes and how it should be better
Jeff Hammel <jhammel@mozilla.com>
parents:
9
diff
changeset
|
13 the nodal values |
81d68388ec97
some nonsense about how this model is full of holes and how it should be better
Jeff Hammel <jhammel@mozilla.com>
parents:
9
diff
changeset
|
14 """ |
11 | 15 # TODO: values should not be **kwargs as you could conceivably want |
16 # to set a node or edge to an empty dict | |
17 # Instead, should be (self, name, values=None) | |
0 | 18 |
19 @abstractmethod | |
20 def nodes(self): | |
21 """returns a list of all nodes""" | |
22 | |
23 @abstractmethod | |
10
81d68388ec97
some nonsense about how this model is full of holes and how it should be better
Jeff Hammel <jhammel@mozilla.com>
parents:
9
diff
changeset
|
24 def edge(self, node1, node2, **values): |
81d68388ec97
some nonsense about how this model is full of holes and how it should be better
Jeff Hammel <jhammel@mozilla.com>
parents:
9
diff
changeset
|
25 """ |
81d68388ec97
some nonsense about how this model is full of holes and how it should be better
Jeff Hammel <jhammel@mozilla.com>
parents:
9
diff
changeset
|
26 get or set edge from node1 to node2 |
81d68388ec97
some nonsense about how this model is full of holes and how it should be better
Jeff Hammel <jhammel@mozilla.com>
parents:
9
diff
changeset
|
27 """ |
81d68388ec97
some nonsense about how this model is full of holes and how it should be better
Jeff Hammel <jhammel@mozilla.com>
parents:
9
diff
changeset
|
28 |
81d68388ec97
some nonsense about how this model is full of holes and how it should be better
Jeff Hammel <jhammel@mozilla.com>
parents:
9
diff
changeset
|
29 @abstractmethod |
0 | 30 def edges(self): |
31 """returns a list of all edges""" | |
32 | |
23
24d57daaca21
well, now the request dispatches
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
33 def __call__(self): |
24d57daaca21
well, now the request dispatches
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
34 """ |
24d57daaca21
well, now the request dispatches
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
35 returns JSGN format of graph: |
24d57daaca21
well, now the request dispatches
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
36 {'nodes': {'node1': {}, |
24d57daaca21
well, now the request dispatches
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
37 'node2': {}, ...}, |
24d57daaca21
well, now the request dispatches
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
38 'edges': {'node1': {'node2': {}, |
24d57daaca21
well, now the request dispatches
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
39 'node3': {}, ...}, |
24d57daaca21
well, now the request dispatches
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
40 'node2': {'node1': {}, ...}} |
24d57daaca21
well, now the request dispatches
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
41 } |
24d57daaca21
well, now the request dispatches
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
42 """ |
24d57daaca21
well, now the request dispatches
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
43 retval = {'nodes': {}, 'edges': {}} |
24d57daaca21
well, now the request dispatches
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
44 for node in self.nodes(): |
24d57daaca21
well, now the request dispatches
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
45 retval['nodes'][node] = self.node(node) |
24d57daaca21
well, now the request dispatches
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
46 for node1, node2 in self.edges(): |
24d57daaca21
well, now the request dispatches
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
47 retval['edges'].setdefault(node1, {})[node2] = self.edge(node1, node2) |
24d57daaca21
well, now the request dispatches
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
48 return retval |
24d57daaca21
well, now the request dispatches
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
49 |
0 | 50 def __getitem__(self, key): |
51 """ | |
52 if key is a basestring, return the node of that name; | |
53 if key is a 2-tuple/list, return the edge of that name | |
54 """ | |
55 | |
15 | 56 if isinstance(key, basestring) or (not isiterable(key)): |
8 | 57 return self.node(key) |
58 else: | |
59 return self.edge(*key) | |
60 | |
61 def __contains__(self, key): | |
62 """ | |
63 if key is ..., returns if that node is in the graph | |
64 if key is a 2-tuple/list, returns if the edge is in the graph | |
65 """ | |
66 # XXX not necessarily the best implementation! | |
15 | 67 if isinstance(key, basestring) or (not isiterable(key)): |
8 | 68 return key in self.nodes() |
69 else: | |
70 return tuple(key) in self.edges() | |
0 | 71 |
15 | 72 |
25 | 73 class MemoryCache(Graph): |
15 | 74 """volatile in-memory representation of a graph""" |
0 | 75 |
76 def __init__(self): | |
77 self._edges = {} | |
78 self._nodes = {} | |
79 | |
80 def node(self, name, **values): | |
81 if values: | |
82 # setter | |
9
0affca1f4dc0
start using deepcopy since lord knows we cant trust users
Jeff Hammel <jhammel@mozilla.com>
parents:
8
diff
changeset
|
83 self._nodes[name] = deepcopy(values) |
0 | 84 else: |
85 # getter | |
9
0affca1f4dc0
start using deepcopy since lord knows we cant trust users
Jeff Hammel <jhammel@mozilla.com>
parents:
8
diff
changeset
|
86 # TODO: deepcopy |
0 | 87 return self._nodes.get(name, None) |
88 | |
89 def nodes(self): | |
90 return self._nodes.keys() | |
91 | |
92 def edge(self, node1, node2, **values): | |
93 if values: | |
94 # setter | |
9
0affca1f4dc0
start using deepcopy since lord knows we cant trust users
Jeff Hammel <jhammel@mozilla.com>
parents:
8
diff
changeset
|
95 self._edges[(node1, node2)] = deepcopy(values) |
0 | 96 else: |
97 # getter | |
9
0affca1f4dc0
start using deepcopy since lord knows we cant trust users
Jeff Hammel <jhammel@mozilla.com>
parents:
8
diff
changeset
|
98 # TODO: deepcopy |
0 | 99 return self._edges.get((node1, node2), None) |
100 | |
101 def edges(self): | |
102 return self._edges.keys() | |
25 | 103 |
104 class FileCache(MemoryCache): | |
105 """on-disk JSON file cache""" | |
106 | |
107 def __init__(self, filename): | |
108 self.filename = filename | |
109 raise NotImplementedError | |
110 | |
111 # TODO: CLI entry point to convert from one model to another | |
112 # def main() |