Skip to content

Commit 4e623ba

Browse files
author
Richard Jones
committed
largish changes as a start of splitting off bits and pieces...
to allow more flexible installation / database back-ends
1 parent e0cd371 commit 4e623ba

File tree

6 files changed

+239
-211
lines changed

6 files changed

+239
-211
lines changed

CHANGES

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,5 @@
5151
. Fixed handling of None String property in grouped list headings
5252
. Fixed adding new issue with no change note
5353
. Added an issue priority of support
54-
54+
. Fixed values in text input fields which contained quotes (") are now
55+
quoted.

hyperdb.py

Lines changed: 18 additions & 206 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,22 @@
1-
# $Id: hyperdb.py,v 1.4 2001-07-19 06:27:07 anthonybaxter Exp $
1+
# $Id: hyperdb.py,v 1.5 2001-07-20 07:35:55 richard Exp $
22

3-
import bsddb, os, cPickle, re, string
3+
# standard python modules
4+
import cPickle, re, string
45

6+
# roundup modules
57
import date
8+
9+
10+
RETIRED_FLAG = '__hyperdb_retired'
11+
12+
#
13+
# Here's where we figure which db to use....
14+
#
15+
import hyperdb_bsddb
16+
Database = hyperdb_bsddb.Database
17+
hyperdb_bsddb.RETIRED_FLAG = RETIRED_FLAG
18+
19+
620
#
721
# Types
822
#
@@ -45,165 +59,10 @@ class Multilink(BaseType, Link):
4559
class DatabaseError(ValueError):
4660
pass
4761

62+
4863
#
49-
# Now the database
64+
# The base Class class
5065
#
51-
RETIRED_FLAG = '__hyperdb_retired'
52-
class Database:
53-
"""A database for storing records containing flexible data types."""
54-
55-
def __init__(self, storagelocator, journaltag=None):
56-
"""Open a hyperdatabase given a specifier to some storage.
57-
58-
The meaning of 'storagelocator' depends on the particular
59-
implementation of the hyperdatabase. It could be a file name,
60-
a directory path, a socket descriptor for a connection to a
61-
database over the network, etc.
62-
63-
The 'journaltag' is a token that will be attached to the journal
64-
entries for any edits done on the database. If 'journaltag' is
65-
None, the database is opened in read-only mode: the Class.create(),
66-
Class.set(), and Class.retire() methods are disabled.
67-
"""
68-
self.dir, self.journaltag = storagelocator, journaltag
69-
self.classes = {}
70-
71-
#
72-
# Classes
73-
#
74-
def __getattr__(self, classname):
75-
"""A convenient way of calling self.getclass(classname)."""
76-
return self.classes[classname]
77-
78-
def addclass(self, cl):
79-
cn = cl.classname
80-
if self.classes.has_key(cn):
81-
raise ValueError, cn
82-
self.classes[cn] = cl
83-
84-
def getclasses(self):
85-
"""Return a list of the names of all existing classes."""
86-
l = self.classes.keys()
87-
l.sort()
88-
return l
89-
90-
def getclass(self, classname):
91-
"""Get the Class object representing a particular class.
92-
93-
If 'classname' is not a valid class name, a KeyError is raised.
94-
"""
95-
return self.classes[classname]
96-
97-
#
98-
# Class DBs
99-
#
100-
def clear(self):
101-
for cn in self.classes.keys():
102-
db = os.path.join(self.dir, 'nodes.%s'%cn)
103-
bsddb.btopen(db, 'n')
104-
db = os.path.join(self.dir, 'journals.%s'%cn)
105-
bsddb.btopen(db, 'n')
106-
107-
def getclassdb(self, classname, mode='r'):
108-
''' grab a connection to the class db that will be used for
109-
multiple actions
110-
'''
111-
path = os.path.join(os.getcwd(), self.dir, 'nodes.%s'%classname)
112-
return bsddb.btopen(path, mode)
113-
114-
def addnode(self, classname, nodeid, node):
115-
''' add the specified node to its class's db
116-
'''
117-
db = self.getclassdb(classname, 'c')
118-
db[nodeid] = cPickle.dumps(node, 1)
119-
db.close()
120-
setnode = addnode
121-
122-
def getnode(self, classname, nodeid, cldb=None):
123-
''' add the specified node to its class's db
124-
'''
125-
db = cldb or self.getclassdb(classname)
126-
if not db.has_key(nodeid):
127-
raise IndexError, nodeid
128-
res = cPickle.loads(db[nodeid])
129-
if not cldb: db.close()
130-
return res
131-
132-
def hasnode(self, classname, nodeid, cldb=None):
133-
''' add the specified node to its class's db
134-
'''
135-
db = cldb or self.getclassdb(classname)
136-
res = db.has_key(nodeid)
137-
if not cldb: db.close()
138-
return res
139-
140-
def countnodes(self, classname, cldb=None):
141-
db = cldb or self.getclassdb(classname)
142-
return len(db.keys())
143-
if not cldb: db.close()
144-
return res
145-
146-
def getnodeids(self, classname, cldb=None):
147-
db = cldb or self.getclassdb(classname)
148-
res = db.keys()
149-
if not cldb: db.close()
150-
return res
151-
152-
#
153-
# Journal
154-
#
155-
def addjournal(self, classname, nodeid, action, params):
156-
''' Journal the Action
157-
'action' may be:
158-
159-
'create' or 'set' -- 'params' is a dictionary of property values
160-
'link' or 'unlink' -- 'params' is (classname, nodeid, propname)
161-
'retire' -- 'params' is None
162-
'''
163-
entry = (nodeid, date.Date(), self.journaltag, action, params)
164-
db = bsddb.btopen(os.path.join(self.dir, 'journals.%s'%classname), 'c')
165-
if db.has_key(nodeid):
166-
s = db[nodeid]
167-
l = cPickle.loads(db[nodeid])
168-
l.append(entry)
169-
else:
170-
l = [entry]
171-
db[nodeid] = cPickle.dumps(l)
172-
db.close()
173-
174-
def getjournal(self, classname, nodeid):
175-
''' get the journal for id
176-
'''
177-
db = bsddb.btopen(os.path.join(self.dir, 'journals.%s'%classname), 'r')
178-
res = cPickle.loads(db[nodeid])
179-
db.close()
180-
return res
181-
182-
def close(self):
183-
''' Close the Database - we must release the circular refs so that
184-
we can be del'ed and the underlying bsddb connections closed
185-
cleanly.
186-
'''
187-
self.classes = None
188-
189-
190-
#
191-
# Basic transaction support
192-
#
193-
# TODO: well, write these methods (and then use them in other code)
194-
def register_action(self):
195-
''' Register an action to the transaction undo log
196-
'''
197-
198-
def commit(self):
199-
''' Commit the current transaction, start a new one
200-
'''
201-
202-
def rollback(self):
203-
''' Reverse all actions from the current transaction
204-
'''
205-
206-
20766
class Class:
20867
"""The handle to a particular class of nodes in a hyperdatabase."""
20968

@@ -876,53 +735,6 @@ def Choice(name, *options):
876735
cl.create(name=option[i], order=i)
877736
return hyperdb.Link(name)
878737

879-
880-
if __name__ == '__main__':
881-
import pprint
882-
db = Database("test_db", "richard")
883-
status = Class(db, "status", name=String())
884-
status.setkey("name")
885-
print db.status.create(name="unread")
886-
print db.status.create(name="in-progress")
887-
print db.status.create(name="testing")
888-
print db.status.create(name="resolved")
889-
print db.status.count()
890-
print db.status.list()
891-
print db.status.lookup("in-progress")
892-
db.status.retire(3)
893-
print db.status.list()
894-
issue = Class(db, "issue", title=String(), status=Link("status"))
895-
db.issue.create(title="spam", status=1)
896-
db.issue.create(title="eggs", status=2)
897-
db.issue.create(title="ham", status=4)
898-
db.issue.create(title="arguments", status=2)
899-
db.issue.create(title="abuse", status=1)
900-
user = Class(db, "user", username=String(), password=String())
901-
user.setkey("username")
902-
db.issue.addprop(fixer=Link("user"))
903-
print db.issue.getprops()
904-
#{"title": <hyperdb.String>, "status": <hyperdb.Link to "status">,
905-
#"user": <hyperdb.Link to "user">}
906-
db.issue.set(5, status=2)
907-
print db.issue.get(5, "status")
908-
print db.status.get(2, "name")
909-
print db.issue.get(5, "title")
910-
print db.issue.find(status = db.status.lookup("in-progress"))
911-
print db.issue.history(5)
912-
# [(<Date 2000-06-28.19:09:43>, "ping", "create", {"title": "abuse", "status": 1}),
913-
# (<Date 2000-06-28.19:11:04>, "ping", "set", {"status": 2})]
914-
print db.status.history(1)
915-
# [(<Date 2000-06-28.19:09:43>, "ping", "link", ("issue", 5, "status")),
916-
# (<Date 2000-06-28.19:11:04>, "ping", "unlink", ("issue", 5, "status"))]
917-
print db.status.history(2)
918-
# [(<Date 2000-06-28.19:11:04>, "ping", "link", ("issue", 5, "status"))]
919-
920-
# TODO: set up some filter tests
921-
922738
#
923739
# $Log: not supported by cvs2svn $
924-
# Revision 1.3 2001/07/19 05:52:22 anthonybaxter
925-
# Added CVS keywords Id and Log to all python files.
926-
#
927-
#
928740

0 commit comments

Comments
 (0)