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
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
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
ee45f44394a0 i need a name, Bastian
Jeff Hammel <jhammel@mozilla.com>
parents: 11
diff changeset
3 from utils import isiterable
0
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
4
25
d1a8c1436ded notes to self
Jeff Hammel <jhammel@mozilla.com>
parents: 23
diff changeset
5 class Graph(object):
0
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
6
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
7 @abstractmethod
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
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
7b8e40eda563 more notes to self
Jeff Hammel <jhammel@mozilla.com>
parents: 10
diff changeset
15 # TODO: values should not be **kwargs as you could conceivably want
7b8e40eda563 more notes to self
Jeff Hammel <jhammel@mozilla.com>
parents: 10
diff changeset
16 # to set a node or edge to an empty dict
7b8e40eda563 more notes to self
Jeff Hammel <jhammel@mozilla.com>
parents: 10
diff changeset
17 # Instead, should be (self, name, values=None)
0
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
18
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
19 @abstractmethod
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
20 def nodes(self):
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
21 """returns a list of all nodes"""
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
22
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
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
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
30 def edges(self):
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
31 """returns a list of all edges"""
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
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
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
50 def __getitem__(self, key):
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
51 """
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
52 if key is a basestring, return the node of that name;
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
53 if key is a 2-tuple/list, return the edge of that name
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
54 """
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
55
15
ee45f44394a0 i need a name, Bastian
Jeff Hammel <jhammel@mozilla.com>
parents: 11
diff changeset
56 if isinstance(key, basestring) or (not isiterable(key)):
8
f1f7a505e0d0 __contains__ method
Jeff Hammel <jhammel@mozilla.com>
parents: 0
diff changeset
57 return self.node(key)
f1f7a505e0d0 __contains__ method
Jeff Hammel <jhammel@mozilla.com>
parents: 0
diff changeset
58 else:
f1f7a505e0d0 __contains__ method
Jeff Hammel <jhammel@mozilla.com>
parents: 0
diff changeset
59 return self.edge(*key)
f1f7a505e0d0 __contains__ method
Jeff Hammel <jhammel@mozilla.com>
parents: 0
diff changeset
60
f1f7a505e0d0 __contains__ method
Jeff Hammel <jhammel@mozilla.com>
parents: 0
diff changeset
61 def __contains__(self, key):
f1f7a505e0d0 __contains__ method
Jeff Hammel <jhammel@mozilla.com>
parents: 0
diff changeset
62 """
f1f7a505e0d0 __contains__ method
Jeff Hammel <jhammel@mozilla.com>
parents: 0
diff changeset
63 if key is ..., returns if that node is in the graph
f1f7a505e0d0 __contains__ method
Jeff Hammel <jhammel@mozilla.com>
parents: 0
diff changeset
64 if key is a 2-tuple/list, returns if the edge is in the graph
f1f7a505e0d0 __contains__ method
Jeff Hammel <jhammel@mozilla.com>
parents: 0
diff changeset
65 """
f1f7a505e0d0 __contains__ method
Jeff Hammel <jhammel@mozilla.com>
parents: 0
diff changeset
66 # XXX not necessarily the best implementation!
15
ee45f44394a0 i need a name, Bastian
Jeff Hammel <jhammel@mozilla.com>
parents: 11
diff changeset
67 if isinstance(key, basestring) or (not isiterable(key)):
8
f1f7a505e0d0 __contains__ method
Jeff Hammel <jhammel@mozilla.com>
parents: 0
diff changeset
68 return key in self.nodes()
f1f7a505e0d0 __contains__ method
Jeff Hammel <jhammel@mozilla.com>
parents: 0
diff changeset
69 else:
f1f7a505e0d0 __contains__ method
Jeff Hammel <jhammel@mozilla.com>
parents: 0
diff changeset
70 return tuple(key) in self.edges()
0
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
71
15
ee45f44394a0 i need a name, Bastian
Jeff Hammel <jhammel@mozilla.com>
parents: 11
diff changeset
72
25
d1a8c1436ded notes to self
Jeff Hammel <jhammel@mozilla.com>
parents: 23
diff changeset
73 class MemoryCache(Graph):
15
ee45f44394a0 i need a name, Bastian
Jeff Hammel <jhammel@mozilla.com>
parents: 11
diff changeset
74 """volatile in-memory representation of a graph"""
0
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
75
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
76 def __init__(self):
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
77 self._edges = {}
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
78 self._nodes = {}
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
79
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
80 def node(self, name, **values):
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
81 if values:
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
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
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
84 else:
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
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
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
87 return self._nodes.get(name, None)
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
88
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
89 def nodes(self):
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
90 return self._nodes.keys()
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
91
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
92 def edge(self, node1, node2, **values):
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
93 if values:
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
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
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
96 else:
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
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
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
99 return self._edges.get((node1, node2), None)
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
100
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
101 def edges(self):
cfcfa093e4b4 initial commit
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
102 return self._edges.keys()
25
d1a8c1436ded notes to self
Jeff Hammel <jhammel@mozilla.com>
parents: 23
diff changeset
103
d1a8c1436ded notes to self
Jeff Hammel <jhammel@mozilla.com>
parents: 23
diff changeset
104 class FileCache(MemoryCache):
d1a8c1436ded notes to self
Jeff Hammel <jhammel@mozilla.com>
parents: 23
diff changeset
105 """on-disk JSON file cache"""
d1a8c1436ded notes to self
Jeff Hammel <jhammel@mozilla.com>
parents: 23
diff changeset
106
d1a8c1436ded notes to self
Jeff Hammel <jhammel@mozilla.com>
parents: 23
diff changeset
107 def __init__(self, filename):
d1a8c1436ded notes to self
Jeff Hammel <jhammel@mozilla.com>
parents: 23
diff changeset
108 self.filename = filename
d1a8c1436ded notes to self
Jeff Hammel <jhammel@mozilla.com>
parents: 23
diff changeset
109 raise NotImplementedError
d1a8c1436ded notes to self
Jeff Hammel <jhammel@mozilla.com>
parents: 23
diff changeset
110
d1a8c1436ded notes to self
Jeff Hammel <jhammel@mozilla.com>
parents: 23
diff changeset
111 # TODO: CLI entry point to convert from one model to another
d1a8c1436ded notes to self
Jeff Hammel <jhammel@mozilla.com>
parents: 23
diff changeset
112 # def main()