annotate hyperdb.py @ 5:72a0ba086b3e

Added CVS keywords $Id$ and $Log$ to all python files.
author Anthony Baxter <anthonybaxter@users.sourceforge.net>
date Thu, 19 Jul 2001 05:52:22 +0000
parents 97559f7bae2e
children 3b0a72f54613
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
5
72a0ba086b3e Added CVS keywords $Id$ and $Log$ to all python files.
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents: 3
diff changeset
1 # $Id: hyperdb.py,v 1.3 2001-07-19 05:52:22 anthonybaxter Exp $
72a0ba086b3e Added CVS keywords $Id$ and $Log$ to all python files.
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents: 3
diff changeset
2
0
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
3 import bsddb, os, cPickle, re, string
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
4
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
5 import date
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
6 #
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
7 # Types
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
8 #
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
9 class BaseType:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
10 isStringType = 0
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
11 isDateType = 0
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
12 isIntervalType = 0
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
13 isLinkType = 0
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
14 isMultilinkType = 0
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
15
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
16 class String(BaseType):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
17 def __init__(self):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
18 """An object designating a String property."""
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
19 pass
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
20 def __repr__(self):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
21 return '<%s>'%self.__class__
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
22 isStringType = 1
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
23
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
24 class Date(BaseType, String):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
25 isDateType = 1
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
26
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
27 class Interval(BaseType, String):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
28 isIntervalType = 1
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
29
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
30 class Link(BaseType):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
31 def __init__(self, classname):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
32 """An object designating a Link property that links to
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
33 nodes in a specified class."""
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
34 self.classname = classname
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
35 def __repr__(self):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
36 return '<%s to "%s">'%(self.__class__, self.classname)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
37 isLinkType = 1
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
38
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
39 class Multilink(BaseType, Link):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
40 """An object designating a Multilink property that links
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
41 to nodes in a specified class.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
42 """
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
43 isMultilinkType = 1
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
44
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
45 class DatabaseError(ValueError):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
46 pass
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
47
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
48 #
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
49 # Now the database
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
50 #
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
51 RETIRED_FLAG = '__hyperdb_retired'
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
52 class Database:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
53 """A database for storing records containing flexible data types."""
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
54
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
55 def __init__(self, storagelocator, journaltag=None):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
56 """Open a hyperdatabase given a specifier to some storage.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
57
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
58 The meaning of 'storagelocator' depends on the particular
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
59 implementation of the hyperdatabase. It could be a file name,
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
60 a directory path, a socket descriptor for a connection to a
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
61 database over the network, etc.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
62
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
63 The 'journaltag' is a token that will be attached to the journal
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
64 entries for any edits done on the database. If 'journaltag' is
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
65 None, the database is opened in read-only mode: the Class.create(),
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
66 Class.set(), and Class.retire() methods are disabled.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
67 """
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
68 self.dir, self.journaltag = storagelocator, journaltag
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
69 self.classes = {}
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
70
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
71 #
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
72 # Classes
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
73 #
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
74 def __getattr__(self, classname):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
75 """A convenient way of calling self.getclass(classname)."""
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
76 return self.classes[classname]
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
77
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
78 def addclass(self, cl):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
79 cn = cl.classname
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
80 if self.classes.has_key(cn):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
81 raise ValueError, cn
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
82 self.classes[cn] = cl
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
83
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
84 def getclasses(self):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
85 """Return a list of the names of all existing classes."""
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
86 l = self.classes.keys()
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
87 l.sort()
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
88 return l
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
89
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
90 def getclass(self, classname):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
91 """Get the Class object representing a particular class.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
92
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
93 If 'classname' is not a valid class name, a KeyError is raised.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
94 """
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
95 return self.classes[classname]
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
96
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
97 #
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
98 # Class DBs
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
99 #
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
100 def clear(self):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
101 for cn in self.classes.keys():
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
102 db = os.path.join(self.dir, 'nodes.%s'%cn)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
103 bsddb.btopen(db, 'n')
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
104 db = os.path.join(self.dir, 'journals.%s'%cn)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
105 bsddb.btopen(db, 'n')
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
106
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
107 def getclassdb(self, classname, mode='r'):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
108 ''' grab a connection to the class db that will be used for
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
109 multiple actions
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
110 '''
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
111 path = os.path.join(os.getcwd(), self.dir, 'nodes.%s'%classname)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
112 return bsddb.btopen(path, mode)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
113
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
114 def addnode(self, classname, nodeid, node):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
115 ''' add the specified node to its class's db
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
116 '''
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
117 db = self.getclassdb(classname, 'c')
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
118 db[nodeid] = cPickle.dumps(node, 1)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
119 db.close()
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
120 setnode = addnode
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
121
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
122 def getnode(self, classname, nodeid, cldb=None):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
123 ''' add the specified node to its class's db
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
124 '''
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
125 db = cldb or self.getclassdb(classname)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
126 if not db.has_key(nodeid):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
127 raise IndexError, nodeid
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
128 res = cPickle.loads(db[nodeid])
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
129 if not cldb: db.close()
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
130 return res
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
131
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
132 def hasnode(self, classname, nodeid, cldb=None):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
133 ''' add the specified node to its class's db
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
134 '''
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
135 db = cldb or self.getclassdb(classname)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
136 res = db.has_key(nodeid)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
137 if not cldb: db.close()
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
138 return res
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
139
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
140 def countnodes(self, classname, cldb=None):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
141 db = cldb or self.getclassdb(classname)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
142 return len(db.keys())
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
143 if not cldb: db.close()
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
144 return res
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
145
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
146 def getnodeids(self, classname, cldb=None):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
147 db = cldb or self.getclassdb(classname)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
148 res = db.keys()
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
149 if not cldb: db.close()
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
150 return res
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
151
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
152 #
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
153 # Journal
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
154 #
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
155 def addjournal(self, classname, nodeid, action, params):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
156 ''' Journal the Action
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
157 'action' may be:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
158
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
159 'create' or 'set' -- 'params' is a dictionary of property values
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
160 'link' or 'unlink' -- 'params' is (classname, nodeid, propname)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
161 'retire' -- 'params' is None
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
162 '''
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
163 entry = (nodeid, date.Date(), self.journaltag, action, params)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
164 db = bsddb.btopen(os.path.join(self.dir, 'journals.%s'%classname), 'c')
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
165 if db.has_key(nodeid):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
166 s = db[nodeid]
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
167 l = cPickle.loads(db[nodeid])
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
168 l.append(entry)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
169 else:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
170 l = [entry]
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
171 db[nodeid] = cPickle.dumps(l)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
172 db.close()
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
173
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
174 def getjournal(self, classname, nodeid):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
175 ''' get the journal for id
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
176 '''
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
177 db = bsddb.btopen(os.path.join(self.dir, 'journals.%s'%classname), 'r')
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
178 res = cPickle.loads(db[nodeid])
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
179 db.close()
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
180 return res
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
181
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
182 def close(self):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
183 ''' Close the Database - we must release the circular refs so that
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
184 we can be del'ed and the underlying bsddb connections closed
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
185 cleanly.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
186 '''
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
187 self.classes = None
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
188
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
189
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
190 #
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
191 # Basic transaction support
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
192 #
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
193 # TODO: well, write these methods (and then use them in other code)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
194 def register_action(self):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
195 ''' Register an action to the transaction undo log
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
196 '''
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
197
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
198 def commit(self):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
199 ''' Commit the current transaction, start a new one
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
200 '''
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
201
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
202 def rollback(self):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
203 ''' Reverse all actions from the current transaction
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
204 '''
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
205
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
206
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
207 class Class:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
208 """The handle to a particular class of nodes in a hyperdatabase."""
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
209
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
210 def __init__(self, db, classname, **properties):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
211 """Create a new class with a given name and property specification.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
212
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
213 'classname' must not collide with the name of an existing class,
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
214 or a ValueError is raised. The keyword arguments in 'properties'
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
215 must map names to property objects, or a TypeError is raised.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
216 """
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
217 self.classname = classname
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
218 self.properties = properties
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
219 self.db = db
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
220 self.key = ''
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
221
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
222 # do the db-related init stuff
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
223 db.addclass(self)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
224
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
225 # Editing nodes:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
226
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
227 def create(self, **propvalues):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
228 """Create a new node of this class and return its id.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
229
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
230 The keyword arguments in 'propvalues' map property names to values.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
231
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
232 The values of arguments must be acceptable for the types of their
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
233 corresponding properties or a TypeError is raised.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
234
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
235 If this class has a key property, it must be present and its value
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
236 must not collide with other key strings or a ValueError is raised.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
237
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
238 Any other properties on this class that are missing from the
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
239 'propvalues' dictionary are set to None.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
240
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
241 If an id in a link or multilink property does not refer to a valid
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
242 node, an IndexError is raised.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
243 """
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
244 if self.db.journaltag is None:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
245 raise DatabaseError, 'Database open read-only'
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
246 newid = str(self.count() + 1)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
247
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
248 # validate propvalues
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
249 num_re = re.compile('^\d+$')
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
250 for key, value in propvalues.items():
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
251 if key == self.key:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
252 try:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
253 self.lookup(value)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
254 except KeyError:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
255 pass
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
256 else:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
257 raise ValueError, 'node with key "%s" exists'%value
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
258
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
259 prop = self.properties[key]
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
260
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
261 if prop.isLinkType:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
262 value = str(value)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
263 link_class = self.properties[key].classname
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
264 if not num_re.match(value):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
265 try:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
266 value = self.db.classes[link_class].lookup(value)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
267 except:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
268 raise ValueError, 'new property "%s": %s not a %s'%(
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
269 key, value, self.properties[key].classname)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
270 propvalues[key] = value
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
271 if not self.db.hasnode(link_class, value):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
272 raise ValueError, '%s has no node %s'%(link_class, value)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
273
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
274 # register the link with the newly linked node
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
275 self.db.addjournal(link_class, value, 'link',
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
276 (self.classname, newid, key))
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
277
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
278 elif prop.isMultilinkType:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
279 if type(value) != type([]):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
280 raise TypeError, 'new property "%s" not a list of ids'%key
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
281 link_class = self.properties[key].classname
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
282 l = []
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
283 for entry in map(str, value):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
284 if not num_re.match(entry):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
285 try:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
286 entry = self.db.classes[link_class].lookup(entry)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
287 except:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
288 raise ValueError, 'new property "%s": %s not a %s'%(
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
289 key, entry, self.properties[key].classname)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
290 l.append(entry)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
291 value = l
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
292 propvalues[key] = value
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
293
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
294 # handle additions
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
295 for id in value:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
296 if not self.db.hasnode(link_class, id):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
297 raise ValueError, '%s has no node %s'%(link_class, id)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
298 # register the link with the newly linked node
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
299 self.db.addjournal(link_class, id, 'link',
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
300 (self.classname, newid, key))
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
301
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
302 elif prop.isStringType:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
303 if type(value) != type(''):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
304 raise TypeError, 'new property "%s" not a string'%key
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
305
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
306 elif prop.isDateType:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
307 if not hasattr(value, 'isDate'):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
308 raise TypeError, 'new property "%s" not a Date'% key
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
309
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
310 elif prop.isIntervalType:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
311 if not hasattr(value, 'isInterval'):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
312 raise TypeError, 'new property "%s" not an Interval'% key
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
313
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
314 for key,prop in self.properties.items():
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
315 if propvalues.has_key(str(key)):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
316 continue
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
317 if prop.isMultilinkType:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
318 propvalues[key] = []
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
319 else:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
320 propvalues[key] = None
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
321
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
322 # done
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
323 self.db.addnode(self.classname, newid, propvalues)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
324 self.db.addjournal(self.classname, newid, 'create', propvalues)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
325 return newid
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
326
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
327 def get(self, nodeid, propname):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
328 """Get the value of a property on an existing node of this class.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
329
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
330 'nodeid' must be the id of an existing node of this class or an
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
331 IndexError is raised. 'propname' must be the name of a property
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
332 of this class or a KeyError is raised.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
333 """
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
334 d = self.db.getnode(self.classname, str(nodeid))
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
335 return d[propname]
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
336
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
337 # XXX not in spec
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
338 def getnode(self, nodeid):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
339 ''' Return a convenience wrapper for the node
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
340 '''
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
341 return Node(self, nodeid)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
342
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
343 def set(self, nodeid, **propvalues):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
344 """Modify a property on an existing node of this class.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
345
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
346 'nodeid' must be the id of an existing node of this class or an
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
347 IndexError is raised.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
348
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
349 Each key in 'propvalues' must be the name of a property of this
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
350 class or a KeyError is raised.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
351
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
352 All values in 'propvalues' must be acceptable types for their
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
353 corresponding properties or a TypeError is raised.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
354
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
355 If the value of the key property is set, it must not collide with
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
356 other key strings or a ValueError is raised.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
357
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
358 If the value of a Link or Multilink property contains an invalid
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
359 node id, a ValueError is raised.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
360 """
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
361 if not propvalues:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
362 return
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
363 if self.db.journaltag is None:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
364 raise DatabaseError, 'Database open read-only'
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
365 nodeid = str(nodeid)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
366 node = self.db.getnode(self.classname, nodeid)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
367 if node.has_key(RETIRED_FLAG):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
368 raise IndexError
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
369 num_re = re.compile('^\d+$')
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
370 for key, value in propvalues.items():
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
371 if not node.has_key(key):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
372 raise KeyError, key
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
373
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
374 if key == self.key:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
375 try:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
376 self.lookup(value)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
377 except KeyError:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
378 pass
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
379 else:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
380 raise ValueError, 'node with key "%s" exists'%value
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
381
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
382 prop = self.properties[key]
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
383
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
384 if prop.isLinkType:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
385 value = str(value)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
386 link_class = self.properties[key].classname
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
387 if not num_re.match(value):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
388 try:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
389 value = self.db.classes[link_class].lookup(value)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
390 except:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
391 raise ValueError, 'new property "%s": %s not a %s'%(
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
392 key, value, self.properties[key].classname)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
393
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
394 if not self.db.hasnode(link_class, value):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
395 raise ValueError, '%s has no node %s'%(link_class, value)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
396
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
397 # register the unlink with the old linked node
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
398 if node[key] is not None:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
399 self.db.addjournal(link_class, node[key], 'unlink',
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
400 (self.classname, nodeid, key))
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
401
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
402 # register the link with the newly linked node
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
403 if value is not None:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
404 self.db.addjournal(link_class, value, 'link',
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
405 (self.classname, nodeid, key))
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
406
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
407 elif prop.isMultilinkType:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
408 if type(value) != type([]):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
409 raise TypeError, 'new property "%s" not a list of ids'%key
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
410 link_class = self.properties[key].classname
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
411 l = []
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
412 for entry in map(str, value):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
413 if not num_re.match(entry):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
414 try:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
415 entry = self.db.classes[link_class].lookup(entry)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
416 except:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
417 raise ValueError, 'new property "%s": %s not a %s'%(
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
418 key, entry, self.properties[key].classname)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
419 l.append(entry)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
420 value = l
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
421 propvalues[key] = value
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
422
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
423 #handle removals
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
424 l = node[key]
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
425 for id in l[:]:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
426 if id in value:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
427 continue
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
428 # register the unlink with the old linked node
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
429 self.db.addjournal(link_class, id, 'unlink',
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
430 (self.classname, nodeid, key))
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
431 l.remove(id)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
432
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
433 # handle additions
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
434 for id in value:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
435 if not self.db.hasnode(link_class, id):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
436 raise ValueError, '%s has no node %s'%(link_class, id)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
437 if id in l:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
438 continue
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
439 # register the link with the newly linked node
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
440 self.db.addjournal(link_class, id, 'link',
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
441 (self.classname, nodeid, key))
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
442 l.append(id)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
443
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
444 elif prop.isStringType:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
445 if value is not None and type(value) != type(''):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
446 raise TypeError, 'new property "%s" not a string'%key
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
447
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
448 elif prop.isDateType:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
449 if not hasattr(value, 'isDate'):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
450 raise TypeError, 'new property "%s" not a Date'% key
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
451
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
452 elif prop.isIntervalType:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
453 if not hasattr(value, 'isInterval'):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
454 raise TypeError, 'new property "%s" not an Interval'% key
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
455
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
456 node[key] = value
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
457
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
458 self.db.setnode(self.classname, nodeid, node)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
459 self.db.addjournal(self.classname, nodeid, 'set', propvalues)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
460
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
461 def retire(self, nodeid):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
462 """Retire a node.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
463
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
464 The properties on the node remain available from the get() method,
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
465 and the node's id is never reused.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
466
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
467 Retired nodes are not returned by the find(), list(), or lookup()
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
468 methods, and other nodes may reuse the values of their key properties.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
469 """
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
470 nodeid = str(nodeid)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
471 if self.db.journaltag is None:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
472 raise DatabaseError, 'Database open read-only'
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
473 node = self.db.getnode(self.classname, nodeid)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
474 node[RETIRED_FLAG] = 1
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
475 self.db.setnode(self.classname, nodeid, node)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
476 self.db.addjournal(self.classname, nodeid, 'retired', None)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
477
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
478 def history(self, nodeid):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
479 """Retrieve the journal of edits on a particular node.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
480
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
481 'nodeid' must be the id of an existing node of this class or an
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
482 IndexError is raised.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
483
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
484 The returned list contains tuples of the form
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
485
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
486 (date, tag, action, params)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
487
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
488 'date' is a Timestamp object specifying the time of the change and
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
489 'tag' is the journaltag specified when the database was opened.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
490 """
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
491 return self.db.getjournal(self.classname, nodeid)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
492
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
493 # Locating nodes:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
494
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
495 def setkey(self, propname):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
496 """Select a String property of this class to be the key property.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
497
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
498 'propname' must be the name of a String property of this class or
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
499 None, or a TypeError is raised. The values of the key property on
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
500 all existing nodes must be unique or a ValueError is raised.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
501 """
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
502 self.key = propname
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
503
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
504 def getkey(self):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
505 """Return the name of the key property for this class or None."""
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
506 return self.key
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
507
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
508 # TODO: set up a separate index db file for this? profile?
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
509 def lookup(self, keyvalue):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
510 """Locate a particular node by its key property and return its id.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
511
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
512 If this class has no key property, a TypeError is raised. If the
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
513 'keyvalue' matches one of the values for the key property among
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
514 the nodes in this class, the matching node's id is returned;
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
515 otherwise a KeyError is raised.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
516 """
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
517 cldb = self.db.getclassdb(self.classname)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
518 for nodeid in self.db.getnodeids(self.classname, cldb):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
519 node = self.db.getnode(self.classname, nodeid, cldb)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
520 if node.has_key(RETIRED_FLAG):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
521 continue
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
522 if node[self.key] == keyvalue:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
523 return nodeid
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
524 cldb.close()
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
525 raise KeyError, keyvalue
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
526
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
527 # XXX: change from spec - allows multiple props to match
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
528 def find(self, **propspec):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
529 """Get the ids of nodes in this class which link to a given node.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
530
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
531 'propspec' consists of keyword args propname=nodeid
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
532 'propname' must be the name of a property in this class, or a
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
533 KeyError is raised. That property must be a Link or Multilink
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
534 property, or a TypeError is raised.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
535
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
536 'nodeid' must be the id of an existing node in the class linked
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
537 to by the given property, or an IndexError is raised.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
538 """
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
539 propspec = propspec.items()
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
540 for propname, nodeid in propspec:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
541 nodeid = str(nodeid)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
542 # check the prop is OK
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
543 prop = self.properties[propname]
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
544 if not prop.isLinkType and not prop.isMultilinkType:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
545 raise TypeError, "'%s' not a Link/Multilink property"%propname
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
546 if not self.db.hasnode(prop.classname, nodeid):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
547 raise ValueError, '%s has no node %s'%(link_class, nodeid)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
548
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
549 # ok, now do the find
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
550 cldb = self.db.getclassdb(self.classname)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
551 l = []
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
552 for id in self.db.getnodeids(self.classname, cldb):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
553 node = self.db.getnode(self.classname, id, cldb)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
554 if node.has_key(RETIRED_FLAG):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
555 continue
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
556 for propname, nodeid in propspec:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
557 nodeid = str(nodeid)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
558 property = node[propname]
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
559 if prop.isLinkType and nodeid == property:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
560 l.append(id)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
561 elif prop.isMultilinkType and nodeid in property:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
562 l.append(id)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
563 cldb.close()
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
564 return l
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
565
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
566 def stringFind(self, **requirements):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
567 """Locate a particular node by matching a set of its String properties.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
568
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
569 If the property is not a String property, a TypeError is raised.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
570
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
571 The return is a list of the id of all nodes that match.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
572 """
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
573 for propname in requirements.keys():
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
574 prop = self.properties[propname]
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
575 if not prop.isStringType:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
576 raise TypeError, "'%s' not a String property"%propname
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
577 l = []
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
578 cldb = self.db.getclassdb(self.classname)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
579 for nodeid in self.db.getnodeids(self.classname, cldb):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
580 node = self.db.getnode(self.classname, nodeid, cldb)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
581 if node.has_key(RETIRED_FLAG):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
582 continue
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
583 for key, value in requirements.items():
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
584 if node[key] != value:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
585 break
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
586 else:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
587 l.append(nodeid)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
588 cldb.close()
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
589 return l
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
590
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
591 def list(self):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
592 """Return a list of the ids of the active nodes in this class."""
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
593 l = []
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
594 cn = self.classname
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
595 cldb = self.db.getclassdb(cn)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
596 for nodeid in self.db.getnodeids(cn, cldb):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
597 node = self.db.getnode(cn, nodeid, cldb)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
598 if node.has_key(RETIRED_FLAG):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
599 continue
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
600 l.append(nodeid)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
601 l.sort()
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
602 cldb.close()
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
603 return l
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
604
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
605 # XXX not in spec
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
606 def filter(self, filterspec, sort, group, num_re = re.compile('^\d+$')):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
607 ''' Return a list of the ids of the active nodes in this class that
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
608 match the 'filter' spec, sorted by the group spec and then the
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
609 sort spec
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
610 '''
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
611 cn = self.classname
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
612
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
613 # optimise filterspec
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
614 l = []
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
615 props = self.getprops()
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
616 for k, v in filterspec.items():
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
617 propclass = props[k]
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
618 if propclass.isLinkType:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
619 if type(v) is not type([]):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
620 v = [v]
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
621 # replace key values with node ids
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
622 u = []
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
623 link_class = self.db.classes[propclass.classname]
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
624 for entry in v:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
625 if not num_re.match(entry):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
626 try:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
627 entry = link_class.lookup(entry)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
628 except:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
629 raise ValueError, 'new property "%s": %s not a %s'%(
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
630 key, entry, self.properties[key].classname)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
631 u.append(entry)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
632
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
633 l.append((0, k, u))
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
634 elif propclass.isMultilinkType:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
635 if type(v) is not type([]):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
636 v = [v]
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
637 # replace key values with node ids
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
638 u = []
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
639 link_class = self.db.classes[propclass.classname]
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
640 for entry in v:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
641 if not num_re.match(entry):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
642 try:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
643 entry = link_class.lookup(entry)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
644 except:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
645 raise ValueError, 'new property "%s": %s not a %s'%(
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
646 key, entry, self.properties[key].classname)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
647 u.append(entry)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
648 l.append((1, k, u))
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
649 elif propclass.isStringType:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
650 v = v[0]
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
651 if '*' in v or '?' in v:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
652 # simple glob searching
3
97559f7bae2e Bug fixes:
Richard Jones <richard@users.sourceforge.net>
parents: 0
diff changeset
653 v = v.replace('?', '.')
97559f7bae2e Bug fixes:
Richard Jones <richard@users.sourceforge.net>
parents: 0
diff changeset
654 v = v.replace('*', '.*?')
97559f7bae2e Bug fixes:
Richard Jones <richard@users.sourceforge.net>
parents: 0
diff changeset
655 v = re.compile(v)
0
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
656 l.append((2, k, v))
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
657 elif v[0] == '^':
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
658 # start-anchored
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
659 if v[-1] == '$':
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
660 # _and_ end-anchored
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
661 l.append((6, k, v[1:-1]))
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
662 l.append((3, k, v[1:]))
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
663 elif v[-1] == '$':
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
664 # end-anchored
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
665 l.append((4, k, v[:-1]))
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
666 else:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
667 # substring
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
668 l.append((5, k, v))
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
669 else:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
670 l.append((6, k, v))
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
671 filterspec = l
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
672
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
673 # now, find all the nodes that are active and pass filtering
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
674 l = []
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
675 cldb = self.db.getclassdb(cn)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
676 for nodeid in self.db.getnodeids(cn, cldb):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
677 node = self.db.getnode(cn, nodeid, cldb)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
678 if node.has_key(RETIRED_FLAG):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
679 continue
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
680 # apply filter
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
681 for t, k, v in filterspec:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
682 if t == 0 and node[k] not in v:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
683 # link - if this node'd property doesn't appear in the
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
684 # filterspec's nodeid list, skip it
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
685 break
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
686 elif t == 1:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
687 # multilink - if any of the nodeids required by the
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
688 # filterspec aren't in this node's property, then skip
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
689 # it
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
690 for value in v:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
691 if value not in node[k]:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
692 break
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
693 else:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
694 continue
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
695 break
3
97559f7bae2e Bug fixes:
Richard Jones <richard@users.sourceforge.net>
parents: 0
diff changeset
696 elif t == 2 and not v.search(node[k]):
0
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
697 # RE search
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
698 break
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
699 elif t == 3 and node[k][:len(v)] != v:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
700 # start anchored
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
701 break
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
702 elif t == 4 and node[k][-len(v):] != v:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
703 # end anchored
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
704 break
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
705 elif t == 5 and node[k].find(v) == -1:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
706 # substring search
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
707 break
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
708 elif t == 6 and node[k] != v:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
709 # straight value comparison for the other types
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
710 break
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
711 else:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
712 l.append((nodeid, node))
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
713 l.sort()
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
714 cldb.close()
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
715
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
716 # optimise sort
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
717 m = []
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
718 for entry in sort:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
719 if entry[0] != '-':
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
720 m.append(('+', entry))
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
721 else:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
722 m.append((entry[0], entry[1:]))
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
723 sort = m
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
724
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
725 # optimise group
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
726 m = []
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
727 for entry in group:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
728 if entry[0] != '-':
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
729 m.append(('+', entry))
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
730 else:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
731 m.append((entry[0], entry[1:]))
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
732 group = m
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
733
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
734 # now, sort the result
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
735 def sortfun(a, b, sort=sort, group=group, properties=self.getprops(),
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
736 db = self.db, cl=self):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
737 a_id, an = a
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
738 b_id, bn = b
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
739 for list in group, sort:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
740 for dir, prop in list:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
741 # handle the properties that might be "faked"
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
742 if not an.has_key(prop):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
743 an[prop] = cl.get(a_id, prop)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
744 av = an[prop]
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
745 if not bn.has_key(prop):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
746 bn[prop] = cl.get(b_id, prop)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
747 bv = bn[prop]
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
748
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
749 # sorting is class-specific
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
750 propclass = properties[prop]
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
751
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
752 # String and Date values are sorted in the natural way
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
753 if propclass.isStringType:
3
97559f7bae2e Bug fixes:
Richard Jones <richard@users.sourceforge.net>
parents: 0
diff changeset
754 # clean up the strings
97559f7bae2e Bug fixes:
Richard Jones <richard@users.sourceforge.net>
parents: 0
diff changeset
755 if av and av[0] in string.uppercase:
0
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
756 av = an[prop] = av.lower()
3
97559f7bae2e Bug fixes:
Richard Jones <richard@users.sourceforge.net>
parents: 0
diff changeset
757 if bv and bv[0] in string.uppercase:
0
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
758 bv = bn[prop] = bv.lower()
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
759 if propclass.isStringType or propclass.isDateType:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
760 if dir == '+':
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
761 r = cmp(av, bv)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
762 if r != 0: return r
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
763 elif dir == '-':
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
764 r = cmp(bv, av)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
765 if r != 0: return r
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
766
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
767 # Link properties are sorted according to the value of
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
768 # the "order" property on the linked nodes if it is
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
769 # present; or otherwise on the key string of the linked
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
770 # nodes; or finally on the node ids.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
771 elif propclass.isLinkType:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
772 link = db.classes[propclass.classname]
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
773 if link.getprops().has_key('order'):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
774 if dir == '+':
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
775 r = cmp(link.get(av, 'order'),
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
776 link.get(bv, 'order'))
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
777 if r != 0: return r
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
778 elif dir == '-':
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
779 r = cmp(link.get(bv, 'order'),
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
780 link.get(av, 'order'))
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
781 if r != 0: return r
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
782 elif link.getkey():
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
783 key = link.getkey()
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
784 if dir == '+':
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
785 r = cmp(link.get(av, key), link.get(bv, key))
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
786 if r != 0: return r
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
787 elif dir == '-':
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
788 r = cmp(link.get(bv, key), link.get(av, key))
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
789 if r != 0: return r
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
790 else:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
791 if dir == '+':
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
792 r = cmp(av, bv)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
793 if r != 0: return r
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
794 elif dir == '-':
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
795 r = cmp(bv, av)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
796 if r != 0: return r
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
797
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
798 # Multilink properties are sorted according to how many
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
799 # links are present.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
800 elif propclass.isMultilinkType:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
801 if dir == '+':
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
802 r = cmp(len(av), len(bv))
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
803 if r != 0: return r
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
804 elif dir == '-':
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
805 r = cmp(len(bv), len(av))
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
806 if r != 0: return r
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
807 return cmp(a[0], b[0])
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
808 l.sort(sortfun)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
809 return [i[0] for i in l]
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
810
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
811 def count(self):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
812 """Get the number of nodes in this class.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
813
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
814 If the returned integer is 'numnodes', the ids of all the nodes
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
815 in this class run from 1 to numnodes, and numnodes+1 will be the
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
816 id of the next node to be created in this class.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
817 """
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
818 return self.db.countnodes(self.classname)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
819
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
820 # Manipulating properties:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
821
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
822 def getprops(self):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
823 """Return a dictionary mapping property names to property objects."""
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
824 return self.properties
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
825
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
826 def addprop(self, **properties):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
827 """Add properties to this class.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
828
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
829 The keyword arguments in 'properties' must map names to property
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
830 objects, or a TypeError is raised. None of the keys in 'properties'
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
831 may collide with the names of existing properties, or a ValueError
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
832 is raised before any properties have been added.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
833 """
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
834 for key in properties.keys():
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
835 if self.properties.has_key(key):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
836 raise ValueError, key
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
837 self.properties.update(properties)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
838
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
839
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
840 # XXX not in spec
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
841 class Node:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
842 ''' A convenience wrapper for the given node
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
843 '''
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
844 def __init__(self, cl, nodeid):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
845 self.__dict__['cl'] = cl
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
846 self.__dict__['nodeid'] = nodeid
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
847 def keys(self):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
848 return self.cl.getprops().keys()
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
849 def has_key(self, name):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
850 return self.cl.getprops().has_key(name)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
851 def __getattr__(self, name):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
852 if self.__dict__.has_key(name):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
853 return self.__dict__['name']
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
854 try:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
855 return self.cl.get(self.nodeid, name)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
856 except KeyError, value:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
857 raise AttributeError, str(value)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
858 def __getitem__(self, name):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
859 return self.cl.get(self.nodeid, name)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
860 def __setattr__(self, name, value):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
861 try:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
862 return self.cl.set(self.nodeid, **{name: value})
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
863 except KeyError, value:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
864 raise AttributeError, str(value)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
865 def __setitem__(self, name, value):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
866 self.cl.set(self.nodeid, **{name: value})
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
867 def history(self):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
868 return self.cl.history(self.nodeid)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
869 def retire(self):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
870 return self.cl.retire(self.nodeid)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
871
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
872
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
873 def Choice(name, *options):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
874 cl = Class(db, name, name=hyperdb.String(), order=hyperdb.String())
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
875 for i in range(len(options)):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
876 cl.create(name=option[i], order=i)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
877 return hyperdb.Link(name)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
878
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
879
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
880 if __name__ == '__main__':
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
881 import pprint
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
882 db = Database("test_db", "richard")
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
883 status = Class(db, "status", name=String())
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
884 status.setkey("name")
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
885 print db.status.create(name="unread")
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
886 print db.status.create(name="in-progress")
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
887 print db.status.create(name="testing")
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
888 print db.status.create(name="resolved")
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
889 print db.status.count()
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
890 print db.status.list()
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
891 print db.status.lookup("in-progress")
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
892 db.status.retire(3)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
893 print db.status.list()
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
894 issue = Class(db, "issue", title=String(), status=Link("status"))
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
895 db.issue.create(title="spam", status=1)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
896 db.issue.create(title="eggs", status=2)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
897 db.issue.create(title="ham", status=4)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
898 db.issue.create(title="arguments", status=2)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
899 db.issue.create(title="abuse", status=1)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
900 user = Class(db, "user", username=String(), password=String())
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
901 user.setkey("username")
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
902 db.issue.addprop(fixer=Link("user"))
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
903 print db.issue.getprops()
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
904 #{"title": <hyperdb.String>, "status": <hyperdb.Link to "status">,
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
905 #"user": <hyperdb.Link to "user">}
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
906 db.issue.set(5, status=2)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
907 print db.issue.get(5, "status")
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
908 print db.status.get(2, "name")
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
909 print db.issue.get(5, "title")
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
910 print db.issue.find(status = db.status.lookup("in-progress"))
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
911 print db.issue.history(5)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
912 # [(<Date 2000-06-28.19:09:43>, "ping", "create", {"title": "abuse", "status": 1}),
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
913 # (<Date 2000-06-28.19:11:04>, "ping", "set", {"status": 2})]
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
914 print db.status.history(1)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
915 # [(<Date 2000-06-28.19:09:43>, "ping", "link", ("issue", 5, "status")),
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
916 # (<Date 2000-06-28.19:11:04>, "ping", "unlink", ("issue", 5, "status"))]
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
917 print db.status.history(2)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
918 # [(<Date 2000-06-28.19:11:04>, "ping", "link", ("issue", 5, "status"))]
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
919
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
920 # TODO: set up some filter tests
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
921
5
72a0ba086b3e Added CVS keywords $Id$ and $Log$ to all python files.
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents: 3
diff changeset
922 #
72a0ba086b3e Added CVS keywords $Id$ and $Log$ to all python files.
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents: 3
diff changeset
923 # $Log: not supported by cvs2svn $
72a0ba086b3e Added CVS keywords $Id$ and $Log$ to all python files.
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents: 3
diff changeset
924 #
72a0ba086b3e Added CVS keywords $Id$ and $Log$ to all python files.
Anthony Baxter <anthonybaxter@users.sourceforge.net>
parents: 3
diff changeset
925

Roundup Issue Tracker: http://roundup-tracker.org/