]> granicus.if.org Git - python/commitdiff
Preferences is a general module to get (and set) preferences in
authorJack Jansen <jack.jansen@cwi.nl>
Mon, 8 Sep 1997 13:26:36 +0000 (13:26 +0000)
committerJack Jansen <jack.jansen@cwi.nl>
Mon, 8 Sep 1997 13:26:36 +0000 (13:26 +0000)
resource files with various inheritence rules, parsers, etc.

pythonprefs uses this to create a single uniform interface to all
relevant python preferences.

Mac/Lib/preferences.py [new file with mode: 0644]
Mac/Lib/pythonprefs.py [new file with mode: 0644]

diff --git a/Mac/Lib/preferences.py b/Mac/Lib/preferences.py
new file mode 100644 (file)
index 0000000..810d9cc
--- /dev/null
@@ -0,0 +1,219 @@
+#
+# 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
+       
diff --git a/Mac/Lib/pythonprefs.py b/Mac/Lib/pythonprefs.py
new file mode 100644 (file)
index 0000000..1f9fd98
--- /dev/null
@@ -0,0 +1,122 @@
+from preferences import *
+
+# Names of Python resources
+PREFNAME_NAME="PythonPreferenceFileName"
+
+# Resource IDs in the preferences file
+PATH_ID = 128
+DIR_ID = 128
+POPT_ID = 128
+GUSI_ID = 10240
+
+# Override IDs (in the applet)
+OVERRIDE_PATH_ID = 129
+OVERRIDE_DIR_ID = 129
+OVERRIDE_POPT_ID = 129
+OVERRIDE_GUSI_ID = 10241
+
+# version
+CUR_VERSION=3
+
+preffilename = PstringLoader(AnyResLoader('STR ', resname=PREFNAME_NAME)).load()
+pref_fss = preferencefile(preffilename, 'Pyth', 'pref')
+
+class PoptLoader(VersionLoader):
+       def __init__(self, loader):
+               VersionLoader.__init__(self, "bbbbbbbbbb", loader)
+               
+       def versioncheck(self, data):
+               if data[0] == CUR_VERSION:
+                       return data
+               print 'old resource'
+               raise Error, "old resource"
+               
+class GusiLoader:
+       def __init__(self, loader):
+               self.loader = loader
+               self.data = None
+               
+       def load(self):
+               self.data = self.loader.load()
+               while self.data[10:14] != '0181':
+                       self.loader.delete(1)
+                       self.loader.load()
+               tp = self.data[0:4]
+               cr = self.data[4:8]
+               flags = ord(self.data[9])
+               delay = ((flags & 0x20) == 0x20)
+               return cr, tp, delay
+               
+       def save(self, (cr, tp, delay)):
+               flags = ord(self.data[9])
+               if delay:
+                       flags = flags | 0x20
+               else:
+                       flags = flags & ~0x20
+               newdata = tp + cr + self.data[8] + chr(flags) + self.data[10:]
+               self.loader.save(newdata)
+               
+popt_default_default = NullLoader(chr(CUR_VERSION) + 8*'\0')
+popt_default = AnyResLoader('Popt', POPT_ID, default=popt_default_default)
+popt_loader = ResLoader(pref_fss, 'Popt', POPT_ID, default=popt_default)
+popt = PoptLoader(popt_loader)
+
+dir_default = AnyResLoader('alis', DIR_ID)
+dir = ResLoader(pref_fss, 'alis', DIR_ID, default=dir_default)
+
+gusi_default = AnyResLoader('GU\267I', GUSI_ID)
+gusi_loader = ResLoader(pref_fss, 'GU\267I', GUSI_ID, default=gusi_default)
+gusi = GusiLoader(gusi_loader)
+
+path_default = AnyResLoader('STR#', PATH_ID)
+path_loader = ResLoader(pref_fss, 'STR#', PATH_ID, default=path_default)
+path = StrListLoader(path_loader)
+
+class PythonOptions:
+       def __init__(self, popt=popt, dir=dir, gusi=gusi, path=path):
+               self.popt = popt
+               self.dir = dir
+               self.gusi = gusi
+               self.path = path
+               
+       def load(self):
+               dict = {}
+               dict['path'] = self.path.load()
+               diralias = self.dir.load()
+               dirfss, dummy = macfs.RawAlias(diralias).Resolve()
+               dict['dir'] = dirfss
+               dict['creator'], dict['type'], dict['delayconsole'] = self.gusi.load()
+               flags = self.popt.load()
+               dict['version'], dict['inspect'], dict['verbose'], dict['optimize'], \
+                       dict['unbuffered'], dict['debugging'], dict['keepopen'], dict['keeperror'], \
+                       dict['nointopt'], dict['noargs'] = flags
+               return dict
+               
+       def save(self, dict):
+               self.path.save(dict['path'])
+               diralias = macfs.FSSpec(dict['dir']).NewAlias().data
+               self.dir.save(diralias)
+               self.gusi.save((dict['creator'], dict['type'], dict['delayconsole']))
+               flags = dict['version'], dict['inspect'], dict['verbose'], dict['optimize'], \
+                       dict['unbuffered'], dict['debugging'], dict['keepopen'], dict['keeperror'], \
+                       dict['nointopt'], dict['noargs'] 
+               self.popt.save(flags)
+
+def AppletOptions(file):
+       fss = macfs.FSSpec(file)
+       a_popt = PoptLoader(ResLoader(fss, 'Popt', OVERRIDE_POPT_ID, default=popt_loader))
+       a_dir = ResLoader(fss, 'alis', OVERRIDE_DIR_ID, default=dir)
+       a_gusi = ResLoader(fss, 'GU\267I', OVERRIDE_GUSI_ID, default=gusi_loader)
+       a_path = StrListLoader(fss, 'STR#', OVERRIDE_PATH_ID, default=path_loader)
+       return PythonOptions(a_popt, a_dir, a_gusi, a_path)
+       
+def _test():
+       import preferences
+       preferences.debug = 1
+       dict = PythonOptions().load()
+       for k in dict.keys():
+               print k, '\t', dict[k]
+               
+if __name__ == '__main__':
+       _test()
+