cpython/Mac/Lib/preferences.py
Jack Jansen 8a99a8aa89 Preferences is a general module to get (and set) preferences in
resource files with various inheritence rules, parsers, etc.

pythonprefs uses this to create a single uniform interface to all
relevant python preferences.
1997-09-08 13:26:36 +00:00

220 lines
5.2 KiB
Python

#
# General parser/loaders for preferences files and such
#
import Res
import macfs
import struct
import MACFS
READ=1
READWRITE=3
Error = "Preferences.Error"
debug = 0
class NullLoader:
def __init__(self, data=None):
self.data = data
def load(self):
if self.data is None:
raise Error, "No default given"
return self.data
def save(self, data):
raise Error, "Cannot save to default value"
def delete(self, deep=0):
if debug:
print 'Attempt to delete default value'
raise Error, "Cannot delete default value"
_defaultdefault = NullLoader()
class ResLoader:
def __init__(self, filename, resid, resnum=None, resname=None, default=_defaultdefault):
self.filename = filename
self.fss = macfs.FSSpec(self.filename)
self.resid = resid
self.resnum = resnum
self.resname = resname
self.default = default
self.data = None
def load(self):
oldrh = Res.CurResFile()
try:
rh = Res.FSpOpenResFile(self.fss, READ)
except Res.Error:
self.data = self.default.load()
return self.data
try:
if self.resname:
handle = Res.Get1NamedResource(self.resid, self.resname)
else:
handle = Res.Get1Resource(self.resid, self.resnum)
except Res.Error:
self.data = self.default.load()
else:
if debug:
print 'Loaded', (self.resid, self.resnum, self.resname), 'from', self.fss.as_pathname()
self.data = handle.data
Res.CloseResFile(rh)
Res.UseResFile(oldrh)
return self.data
def save(self, data):
if self.data is None or self.data != data:
oldrh = Res.CurResFile()
rh = Res.FSpOpenResFile(self.fss, READWRITE)
try:
handle = Res.Get1Resource(self.resid, self.resnum)
except Res.Error:
handle = Res.Resource(data)
handle.AddResource(self.resid, self.resnum, '')
if debug:
print 'Added', (self.resid, self.resnum), 'to', self.fss.as_pathname()
else:
handle.data = data
handle.ChangedResource()
if debug:
print 'Changed', (self.resid, self.resnum), 'in', self.fss.as_pathname()
Res.CloseResFile(rh)
Res.UseResFile(oldrh)
def delete(self, deep=0):
if debug:
print 'Deleting in', self.fss.as_pathname(), `self.data`, deep
oldrh = Res.CurResFile()
rh = Res.FSpOpenResFile(self.fss, READWRITE)
try:
handle = Res.Get1Resource(self.resid, self.resnum)
except Res.Error:
if deep:
if debug: print 'deep in', self.default
self.default.delete(1)
else:
handle.RemoveResource()
if debug:
print 'Deleted', (self.resid, self.resnum), 'from', self.fss.as_pathname()
self.data = None
Res.CloseResFile(rh)
Res.UseResFile(oldrh)
class AnyResLoader:
def __init__(self, resid, resnum=None, resname=None, default=_defaultdefault):
self.resid = resid
self.resnum = resnum
self.resname = resname
self.default = default
self.data = None
def load(self):
try:
if self.resname:
handle = Res.GetNamedResource(self.resid, self.resname)
else:
handle = Res.GetResource(self.resid, self.resnum)
except Res.Error:
self.data = self.default.load()
else:
self.data = handle.data
return self.data
def save(self, data):
raise Error, "Cannot save AnyResLoader preferences"
def delete(self, deep=0):
raise Error, "Cannot delete AnyResLoader preferences"
class StructLoader:
def __init__(self, format, loader):
self.format = format
self.loader = loader
def load(self):
data = self.loader.load()
return struct.unpack(self.format, data)
def save(self, data):
data = apply(struct.pack, (self.format,)+data)
self.loader.save(data)
def delete(self, deep=0):
self.loader.delete(deep)
class PstringLoader:
def __init__(self, loader):
self.loader = loader
def load(self):
data = self.loader.load()
len = ord(data[0])
return data[1:1+len]
def save(self, data):
if len(data) > 255:
raise Error, "String too big for pascal-style"
self.loader.save(chr(len(data))+data)
def delete(self, deep=0):
self.loader.delete(deep)
class VersionLoader(StructLoader):
def load(self):
while 1:
data = self.loader.load()
if debug:
print 'Versionloader:', `data`
try:
rv = struct.unpack(self.format, data)
rv = self.versioncheck(rv)
return rv
except (struct.error, Error):
self.delete(1)
def versioncheck(self, data):
return data
class StrListLoader:
def __init__(self, loader):
self.loader = loader
def load(self):
data = self.loader.load()
num, = struct.unpack('h', data[:2])
data = data[2:]
rv = []
for i in range(num):
strlen = ord(data[0])
if strlen < 0: strlen = strlen + 256
str = data[1:strlen+1]
data = data[strlen+1:]
rv.append(str)
return rv
def save(self, list):
rv = struct.pack('h', len(list))
for str in list:
rv = rv + chr(len(str)) + str
self.loader.save(rv)
def delete(self, deep=0):
self.loader.delete(deep)
def preferencefile(filename, creator=None, type=None):
create = creator != None and type != None
vrefnum, dirid = macfs.FindFolder(MACFS.kOnSystemDisk, 'pref', create)
fss = macfs.FSSpec((vrefnum, dirid, filename))
oldrf = Res.CurResFile()
if create:
try:
rh = Res.FSpOpenResFile(fss, READ)
except Res.Error:
Res.FSpCreateResFile(fss, creator, type, MACFS.smAllScripts)
else:
Res.CloseResFile(rh)
Res.UseResFile(oldrf)
return fss