mirror of
https://github.com/python/cpython.git
synced 2025-07-24 03:35:53 +00:00
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.
This commit is contained in:
parent
447e01b04e
commit
8a99a8aa89
2 changed files with 341 additions and 0 deletions
219
Mac/Lib/preferences.py
Normal file
219
Mac/Lib/preferences.py
Normal file
|
@ -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
|
||||
|
122
Mac/Lib/pythonprefs.py
Normal file
122
Mac/Lib/pythonprefs.py
Normal file
|
@ -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()
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue