diff --git a/roundup/hyperdb.py b/roundup/hyperdb.py
index f9f3a2651f5dca7bb257480298963fbdf324a73a..252194c0c93636a041f3a316d733841848c0f9a8 100644 (file)
--- a/roundup/hyperdb.py
+++ b/roundup/hyperdb.py
-# $Id: hyperdb.py,v 1.2 2001-07-22 12:09:32 richard Exp $
+# $Id: hyperdb.py,v 1.9 2001-07-29 09:28:23 richard Exp $
# standard python modules
import cPickle, re, string
If an id in a link or multilink property does not refer to a valid
node, an IndexError is raised.
"""
+ if propvalues.has_key('id'):
+ raise KeyError, '"id" is reserved'
+
if self.db.journaltag is None:
raise DatabaseError, 'Database open read-only'
+
+ # new node's id
newid = str(self.count() + 1)
# validate propvalues
prop = self.properties[key]
if prop.isLinkType:
- value = str(value)
+ if type(value) != type(''):
+ raise ValueError, 'link value must be String'
+# value = str(value)
link_class = self.properties[key].classname
+ # if it isn't a number, it's a key
if not num_re.match(value):
try:
value = self.db.classes[link_class].lookup(value)
except:
- raise ValueError, 'new property "%s": %s not a %s'%(
+ raise IndexError, 'new property "%s": %s not a %s'%(
key, value, self.properties[key].classname)
propvalues[key] = value
if not self.db.hasnode(link_class, value):
- raise ValueError, '%s has no node %s'%(link_class, value)
+ raise IndexError, '%s has no node %s'%(link_class, value)
# register the link with the newly linked node
self.db.addjournal(link_class, value, 'link',
raise TypeError, 'new property "%s" not a list of ids'%key
link_class = self.properties[key].classname
l = []
- for entry in map(str, value):
+ for entry in value:
+ if type(entry) != type(''):
+ raise ValueError, 'link value must be String'
+ # if it isn't a number, it's a key
if not num_re.match(entry):
try:
entry = self.db.classes[link_class].lookup(entry)
except:
- raise ValueError, 'new property "%s": %s not a %s'%(
+ raise IndexError, 'new property "%s": %s not a %s'%(
key, entry, self.properties[key].classname)
l.append(entry)
value = l
# handle additions
for id in value:
if not self.db.hasnode(link_class, id):
- raise ValueError, '%s has no node %s'%(link_class, id)
+ raise IndexError, '%s has no node %s'%(link_class, id)
# register the link with the newly linked node
self.db.addjournal(link_class, id, 'link',
(self.classname, newid, key))
if not hasattr(value, 'isInterval'):
raise TypeError, 'new property "%s" not an Interval'% key
- for key,prop in self.properties.items():
- if propvalues.has_key(str(key)):
+ for key, prop in self.properties.items():
+ if propvalues.has_key(key):
continue
if prop.isMultilinkType:
propvalues[key] = []
IndexError is raised. 'propname' must be the name of a property
of this class or a KeyError is raised.
"""
- d = self.db.getnode(self.classname, str(nodeid))
+ if propname == 'id':
+ return nodeid
+# nodeid = str(nodeid)
+ d = self.db.getnode(self.classname, nodeid)
return d[propname]
# XXX not in spec
"""
if not propvalues:
return
+
+ if propvalues.has_key('id'):
+ raise KeyError, '"id" is reserved'
+
if self.db.journaltag is None:
raise DatabaseError, 'Database open read-only'
- nodeid = str(nodeid)
+
+# nodeid = str(nodeid)
node = self.db.getnode(self.classname, nodeid)
if node.has_key(self.db.RETIRED_FLAG):
raise IndexError
prop = self.properties[key]
if prop.isLinkType:
- value = str(value)
+# value = str(value)
link_class = self.properties[key].classname
+ # if it isn't a number, it's a key
+ if type(value) != type(''):
+ raise ValueError, 'link value must be String'
if not num_re.match(value):
try:
value = self.db.classes[link_class].lookup(value)
except:
- raise ValueError, 'new property "%s": %s not a %s'%(
+ raise IndexError, 'new property "%s": %s not a %s'%(
key, value, self.properties[key].classname)
if not self.db.hasnode(link_class, value):
- raise ValueError, '%s has no node %s'%(link_class, value)
+ raise IndexError, '%s has no node %s'%(link_class, value)
# register the unlink with the old linked node
if node[key] is not None:
raise TypeError, 'new property "%s" not a list of ids'%key
link_class = self.properties[key].classname
l = []
- for entry in map(str, value):
+ for entry in value:
+ # if it isn't a number, it's a key
+ if type(entry) != type(''):
+ raise ValueError, 'link value must be String'
if not num_re.match(entry):
try:
entry = self.db.classes[link_class].lookup(entry)
except:
- raise ValueError, 'new property "%s": %s not a %s'%(
+ raise IndexError, 'new property "%s": %s not a %s'%(
key, entry, self.properties[key].classname)
l.append(entry)
value = l
# handle additions
for id in value:
if not self.db.hasnode(link_class, id):
- raise ValueError, '%s has no node %s'%(link_class, id)
+ raise IndexError, '%s has no node %s'%(link_class, id)
if id in l:
continue
# register the link with the newly linked node
Retired nodes are not returned by the find(), list(), or lookup()
methods, and other nodes may reuse the values of their key properties.
"""
- nodeid = str(nodeid)
+# nodeid = str(nodeid)
if self.db.journaltag is None:
raise DatabaseError, 'Database open read-only'
node = self.db.getnode(self.classname, nodeid)
"""Return the name of the key property for this class or None."""
return self.key
+ def labelprop(self):
+ ''' Return the property name for a label for the given node.
+
+ This method attempts to generate a consistent label for the node.
+ It tries the following in order:
+ 1. key property
+ 2. "name" property
+ 3. "title" property
+ 4. first property from the sorted property name list
+ '''
+ k = self.getkey()
+ if k:
+ return k
+ props = self.getprops()
+ if props.has_key('name'):
+ return 'name'
+ elif props.has_key('title'):
+ return 'title'
+ props = props.keys()
+ props.sort()
+ return props[0]
+
# TODO: set up a separate index db file for this? profile?
def lookup(self, keyvalue):
"""Locate a particular node by its key property and return its id.
"""
propspec = propspec.items()
for propname, nodeid in propspec:
- nodeid = str(nodeid)
+# nodeid = str(nodeid)
# check the prop is OK
prop = self.properties[propname]
if not prop.isLinkType and not prop.isMultilinkType:
if node.has_key(self.db.RETIRED_FLAG):
continue
for propname, nodeid in propspec:
- nodeid = str(nodeid)
+# nodeid = str(nodeid)
property = node[propname]
if prop.isLinkType and nodeid == property:
l.append(id)
u.append(entry)
l.append((1, k, u))
elif propclass.isStringType:
- v = v[0]
if '*' in v or '?' in v:
# simple glob searching
v = v.replace('?', '.')
else:
m.append((entry[0], entry[1:]))
group = m
-
# now, sort the result
def sortfun(a, b, sort=sort, group=group, properties=self.getprops(),
db = self.db, cl=self):
a_id, an = a
b_id, bn = b
+ # sort by group and then sort
for list in group, sort:
for dir, prop in list:
# handle the properties that might be "faked"
# nodes; or finally on the node ids.
elif propclass.isLinkType:
link = db.classes[propclass.classname]
+ if av is None and bv is not None: return -1
+ if av is not None and bv is None: return 1
+ if av is None and bv is None: return 0
if link.getprops().has_key('order'):
if dir == '+':
r = cmp(link.get(av, 'order'),
elif dir == '-':
r = cmp(len(bv), len(av))
if r != 0: return r
+ # end for dir, prop in list:
+ # end for list in sort, group:
+ # if all else fails, compare the ids
return cmp(a[0], b[0])
+
l.sort(sortfun)
return [i[0] for i in l]
def getprops(self):
"""Return a dictionary mapping property names to property objects."""
- return self.properties
+ d = self.properties.copy()
+ d['id'] = String()
+ return d
def addprop(self, **properties):
"""Add properties to this class.
#
# $Log: not supported by cvs2svn $
+# Revision 1.8 2001/07/29 08:27:40 richard
+# Fixed handling of passed-in values in form elements (ie. during a
+# drill-down)
+#
+# Revision 1.7 2001/07/29 07:01:39 richard
+# Added vim command to all source so that we don't get no steenkin' tabs :)
+#
+# Revision 1.6 2001/07/29 05:36:14 richard
+# Cleanup of the link label generation.
+#
+# Revision 1.5 2001/07/29 04:05:37 richard
+# Added the fabricated property "id".
+#
+# Revision 1.4 2001/07/27 06:25:35 richard
+# Fixed some of the exceptions so they're the right type.
+# Removed the str()-ification of node ids so we don't mask oopsy errors any
+# more.
+#
+# Revision 1.3 2001/07/27 05:17:14 richard
+# just some comments
+#
+# Revision 1.2 2001/07/22 12:09:32 richard
+# Final commit of Grande Splite
+#
# Revision 1.1 2001/07/22 11:58:35 richard
# More Grande Splite
#
+#
+# vim: set filetype=python ts=4 sw=4 et si