Projects
/
mdb-ng
Archived
4
0
Fork 0
This repository has been archived on 2024-07-04. You can view files and clone it, but cannot push or open issues or pull requests.
mdb-ng/lib/mdb/db.py

149 lines
4.6 KiB
Python

#
# $Id$
#
# This file contains class definitions and interface to the database
# itself while defining objects that the database will return.
#
import rcs, os
#
# The most generic exception that this library will raise.
#
class PVVDBError(Exception):
pass
#
# PVVMember is the class that represents a record in the database.
# Its interface is like a dict with a few additional methods to
# talk to the database itself.
#
class PVVMember(dict):
def __init__(self, data, dbref):
# Populate the object with the fields and values provided in the
# `data' object. `dbref' is a pointer to the PVVDB instance that
# created the PVVMember instance.
pass
def save(self):
# Synchronise the object to disk via the database interface.
pass
def load(self):
# Update the object with the data on disk.
pass
def is_saved(self):
# Checks whether the objects need to be saved or loaded.
pass
#
# PVVDB is the class that interfaces to the directory structure and files.
# It also verifies the data read from the files and written to it.
#
class PVVDB:
def __init__(self, base):
# Find the record definition file, read it, verify it and
# set the legal set of fields.
self.base = base # base database directory
self.locks = [] # list of activated locks
self.rcs = rcs.RCS() # an RCS interface function
self.format = self.__format(self.base)
def __del__(self):
# clean up locks and such before being deleted.
for username in self.locks:
self.rcs.unlock(username)
def __filename(self, username):
# transform the username into a tuple with the full name of
# the databasefile and the latest revision number.
return self.rcs.rcsname(os.path.join(self.base, username))
def __format(self, file_path):
# parses and verifies the .format files for a database.
fh = file(file_path)
fmt = {}
for line in fh:
if line[0] == "#":
continue
name, value = line.strip().split(":", 1)
value = value.split("#", 1)[0].strip()
if not value in ['scalar', 'list']:
raise PVVDBError, "%s not legal .format datatype." % value
fmt[name] = value
return fmt
def lock(self, username, pedantic=False):
# Lock the record.
if username in self.locks and pedantic:
raise PVVDBError, "%s already locked." % `username`
self.rcs.lock(self.__filename(username))
self.locks.append(username)
def unlock(self, username, pedantic=False):
# Unlock the record.
if not username in self.locks and pedantic:
raise PVVDBError, "%s not locked." % `username`
self.rcs.unlock(self.__filename(username))
self.locks.remove(username)
def load(self, username, lock=False):
# Read the record from the database. Will do an automatic lock
# if `lock' is True.
if lock:
self.lock(username)
userfile = file(self.__filename(username))
member = {}
for line in userfile:
key, value = line.strip().split(": ", 1)
if not key in self.format:
raise PVVDBError, "%s not a legal attribute." % `key`
v = None
# handle the list datatype
if self.format[key] == 'list':
v = []
# XXX: needs to respect escaping of field separators
for e in value.split(", "):
v.append(e)
elif self.format[key] == 'scalar':
v = value
else:
# we should not be here
raise PVVDBError, "%s not legal datatype." % `self.format[key]`
member[key] = value
return PVVMember(member, username)
def save(self, username, comment="", lock=False):
# Write the record to the database. Will automatically unlock
# the record if `lock' is True. A `comment' can be supplied that
# explains the changes made.
pass
#
# Regular interface to the database.
#
pathmap = {}
def connect(path):
# returns a PVVDB instance to that path. If asked for another
# PVVDB instance with the same path as earlier, it will return
# the same object.
if not path in pathmap:
pathmap[path] = PVVDB(path)
return pathmap[path]
def disconnect(dbo):
# do not do anything, really. PVVDB objects will clean up
# automatically when deleted. is here for future database
# systems.
pass