Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8a99a8a

Browse files
committed
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.
1 parent 447e01b commit 8a99a8a

2 files changed

Lines changed: 341 additions & 0 deletions

File tree

Mac/Lib/preferences.py

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
#
2+
# General parser/loaders for preferences files and such
3+
#
4+
import Res
5+
import macfs
6+
import struct
7+
import MACFS
8+
9+
READ=1
10+
READWRITE=3
11+
Error = "Preferences.Error"
12+
13+
debug = 0
14+
15+
class NullLoader:
16+
def __init__(self, data=None):
17+
self.data = data
18+
19+
def load(self):
20+
if self.data is None:
21+
raise Error, "No default given"
22+
return self.data
23+
24+
def save(self, data):
25+
raise Error, "Cannot save to default value"
26+
27+
def delete(self, deep=0):
28+
if debug:
29+
print 'Attempt to delete default value'
30+
raise Error, "Cannot delete default value"
31+
32+
_defaultdefault = NullLoader()
33+
34+
class ResLoader:
35+
def __init__(self, filename, resid, resnum=None, resname=None, default=_defaultdefault):
36+
self.filename = filename
37+
self.fss = macfs.FSSpec(self.filename)
38+
self.resid = resid
39+
self.resnum = resnum
40+
self.resname = resname
41+
self.default = default
42+
self.data = None
43+
44+
def load(self):
45+
oldrh = Res.CurResFile()
46+
try:
47+
rh = Res.FSpOpenResFile(self.fss, READ)
48+
except Res.Error:
49+
self.data = self.default.load()
50+
return self.data
51+
try:
52+
if self.resname:
53+
handle = Res.Get1NamedResource(self.resid, self.resname)
54+
else:
55+
handle = Res.Get1Resource(self.resid, self.resnum)
56+
except Res.Error:
57+
self.data = self.default.load()
58+
else:
59+
if debug:
60+
print 'Loaded', (self.resid, self.resnum, self.resname), 'from', self.fss.as_pathname()
61+
self.data = handle.data
62+
Res.CloseResFile(rh)
63+
Res.UseResFile(oldrh)
64+
return self.data
65+
66+
def save(self, data):
67+
if self.data is None or self.data != data:
68+
oldrh = Res.CurResFile()
69+
rh = Res.FSpOpenResFile(self.fss, READWRITE)
70+
try:
71+
handle = Res.Get1Resource(self.resid, self.resnum)
72+
except Res.Error:
73+
handle = Res.Resource(data)
74+
handle.AddResource(self.resid, self.resnum, '')
75+
if debug:
76+
print 'Added', (self.resid, self.resnum), 'to', self.fss.as_pathname()
77+
else:
78+
handle.data = data
79+
handle.ChangedResource()
80+
if debug:
81+
print 'Changed', (self.resid, self.resnum), 'in', self.fss.as_pathname()
82+
Res.CloseResFile(rh)
83+
Res.UseResFile(oldrh)
84+
85+
def delete(self, deep=0):
86+
if debug:
87+
print 'Deleting in', self.fss.as_pathname(), `self.data`, deep
88+
oldrh = Res.CurResFile()
89+
rh = Res.FSpOpenResFile(self.fss, READWRITE)
90+
try:
91+
handle = Res.Get1Resource(self.resid, self.resnum)
92+
except Res.Error:
93+
if deep:
94+
if debug: print 'deep in', self.default
95+
self.default.delete(1)
96+
else:
97+
handle.RemoveResource()
98+
if debug:
99+
print 'Deleted', (self.resid, self.resnum), 'from', self.fss.as_pathname()
100+
self.data = None
101+
Res.CloseResFile(rh)
102+
Res.UseResFile(oldrh)
103+
104+
class AnyResLoader:
105+
def __init__(self, resid, resnum=None, resname=None, default=_defaultdefault):
106+
self.resid = resid
107+
self.resnum = resnum
108+
self.resname = resname
109+
self.default = default
110+
self.data = None
111+
112+
def load(self):
113+
try:
114+
if self.resname:
115+
handle = Res.GetNamedResource(self.resid, self.resname)
116+
else:
117+
handle = Res.GetResource(self.resid, self.resnum)
118+
except Res.Error:
119+
self.data = self.default.load()
120+
else:
121+
self.data = handle.data
122+
return self.data
123+
124+
def save(self, data):
125+
raise Error, "Cannot save AnyResLoader preferences"
126+
127+
def delete(self, deep=0):
128+
raise Error, "Cannot delete AnyResLoader preferences"
129+
130+
class StructLoader:
131+
def __init__(self, format, loader):
132+
self.format = format
133+
self.loader = loader
134+
135+
def load(self):
136+
data = self.loader.load()
137+
return struct.unpack(self.format, data)
138+
139+
def save(self, data):
140+
data = apply(struct.pack, (self.format,)+data)
141+
self.loader.save(data)
142+
143+
def delete(self, deep=0):
144+
self.loader.delete(deep)
145+
146+
class PstringLoader:
147+
def __init__(self, loader):
148+
self.loader = loader
149+
150+
def load(self):
151+
data = self.loader.load()
152+
len = ord(data[0])
153+
return data[1:1+len]
154+
155+
def save(self, data):
156+
if len(data) > 255:
157+
raise Error, "String too big for pascal-style"
158+
self.loader.save(chr(len(data))+data)
159+
160+
def delete(self, deep=0):
161+
self.loader.delete(deep)
162+
163+
class VersionLoader(StructLoader):
164+
def load(self):
165+
while 1:
166+
data = self.loader.load()
167+
if debug:
168+
print 'Versionloader:', `data`
169+
try:
170+
rv = struct.unpack(self.format, data)
171+
rv = self.versioncheck(rv)
172+
return rv
173+
except (struct.error, Error):
174+
self.delete(1)
175+
176+
def versioncheck(self, data):
177+
return data
178+
179+
class StrListLoader:
180+
def __init__(self, loader):
181+
self.loader = loader
182+
183+
def load(self):
184+
data = self.loader.load()
185+
num, = struct.unpack('h', data[:2])
186+
data = data[2:]
187+
rv = []
188+
for i in range(num):
189+
strlen = ord(data[0])
190+
if strlen < 0: strlen = strlen + 256
191+
str = data[1:strlen+1]
192+
data = data[strlen+1:]
193+
rv.append(str)
194+
return rv
195+
196+
def save(self, list):
197+
rv = struct.pack('h', len(list))
198+
for str in list:
199+
rv = rv + chr(len(str)) + str
200+
self.loader.save(rv)
201+
202+
def delete(self, deep=0):
203+
self.loader.delete(deep)
204+
205+
def preferencefile(filename, creator=None, type=None):
206+
create = creator != None and type != None
207+
vrefnum, dirid = macfs.FindFolder(MACFS.kOnSystemDisk, 'pref', create)
208+
fss = macfs.FSSpec((vrefnum, dirid, filename))
209+
oldrf = Res.CurResFile()
210+
if create:
211+
try:
212+
rh = Res.FSpOpenResFile(fss, READ)
213+
except Res.Error:
214+
Res.FSpCreateResFile(fss, creator, type, MACFS.smAllScripts)
215+
else:
216+
Res.CloseResFile(rh)
217+
Res.UseResFile(oldrf)
218+
return fss
219+

Mac/Lib/pythonprefs.py

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
from preferences import *
2+
3+
# Names of Python resources
4+
PREFNAME_NAME="PythonPreferenceFileName"
5+
6+
# Resource IDs in the preferences file
7+
PATH_ID = 128
8+
DIR_ID = 128
9+
POPT_ID = 128
10+
GUSI_ID = 10240
11+
12+
# Override IDs (in the applet)
13+
OVERRIDE_PATH_ID = 129
14+
OVERRIDE_DIR_ID = 129
15+
OVERRIDE_POPT_ID = 129
16+
OVERRIDE_GUSI_ID = 10241
17+
18+
# version
19+
CUR_VERSION=3
20+
21+
preffilename = PstringLoader(AnyResLoader('STR ', resname=PREFNAME_NAME)).load()
22+
pref_fss = preferencefile(preffilename, 'Pyth', 'pref')
23+
24+
class PoptLoader(VersionLoader):
25+
def __init__(self, loader):
26+
VersionLoader.__init__(self, "bbbbbbbbbb", loader)
27+
28+
def versioncheck(self, data):
29+
if data[0] == CUR_VERSION:
30+
return data
31+
print 'old resource'
32+
raise Error, "old resource"
33+
34+
class GusiLoader:
35+
def __init__(self, loader):
36+
self.loader = loader
37+
self.data = None
38+
39+
def load(self):
40+
self.data = self.loader.load()
41+
while self.data[10:14] != '0181':
42+
self.loader.delete(1)
43+
self.loader.load()
44+
tp = self.data[0:4]
45+
cr = self.data[4:8]
46+
flags = ord(self.data[9])
47+
delay = ((flags & 0x20) == 0x20)
48+
return cr, tp, delay
49+
50+
def save(self, (cr, tp, delay)):
51+
flags = ord(self.data[9])
52+
if delay:
53+
flags = flags | 0x20
54+
else:
55+
flags = flags & ~0x20
56+
newdata = tp + cr + self.data[8] + chr(flags) + self.data[10:]
57+
self.loader.save(newdata)
58+
59+
popt_default_default = NullLoader(chr(CUR_VERSION) + 8*'\0')
60+
popt_default = AnyResLoader('Popt', POPT_ID, default=popt_default_default)
61+
popt_loader = ResLoader(pref_fss, 'Popt', POPT_ID, default=popt_default)
62+
popt = PoptLoader(popt_loader)
63+
64+
dir_default = AnyResLoader('alis', DIR_ID)
65+
dir = ResLoader(pref_fss, 'alis', DIR_ID, default=dir_default)
66+
67+
gusi_default = AnyResLoader('GU\267I', GUSI_ID)
68+
gusi_loader = ResLoader(pref_fss, 'GU\267I', GUSI_ID, default=gusi_default)
69+
gusi = GusiLoader(gusi_loader)
70+
71+
path_default = AnyResLoader('STR#', PATH_ID)
72+
path_loader = ResLoader(pref_fss, 'STR#', PATH_ID, default=path_default)
73+
path = StrListLoader(path_loader)
74+
75+
class PythonOptions:
76+
def __init__(self, popt=popt, dir=dir, gusi=gusi, path=path):
77+
self.popt = popt
78+
self.dir = dir
79+
self.gusi = gusi
80+
self.path = path
81+
82+
def load(self):
83+
dict = {}
84+
dict['path'] = self.path.load()
85+
diralias = self.dir.load()
86+
dirfss, dummy = macfs.RawAlias(diralias).Resolve()
87+
dict['dir'] = dirfss
88+
dict['creator'], dict['type'], dict['delayconsole'] = self.gusi.load()
89+
flags = self.popt.load()
90+
dict['version'], dict['inspect'], dict['verbose'], dict['optimize'], \
91+
dict['unbuffered'], dict['debugging'], dict['keepopen'], dict['keeperror'], \
92+
dict['nointopt'], dict['noargs'] = flags
93+
return dict
94+
95+
def save(self, dict):
96+
self.path.save(dict['path'])
97+
diralias = macfs.FSSpec(dict['dir']).NewAlias().data
98+
self.dir.save(diralias)
99+
self.gusi.save((dict['creator'], dict['type'], dict['delayconsole']))
100+
flags = dict['version'], dict['inspect'], dict['verbose'], dict['optimize'], \
101+
dict['unbuffered'], dict['debugging'], dict['keepopen'], dict['keeperror'], \
102+
dict['nointopt'], dict['noargs']
103+
self.popt.save(flags)
104+
105+
def AppletOptions(file):
106+
fss = macfs.FSSpec(file)
107+
a_popt = PoptLoader(ResLoader(fss, 'Popt', OVERRIDE_POPT_ID, default=popt_loader))
108+
a_dir = ResLoader(fss, 'alis', OVERRIDE_DIR_ID, default=dir)
109+
a_gusi = ResLoader(fss, 'GU\267I', OVERRIDE_GUSI_ID, default=gusi_loader)
110+
a_path = StrListLoader(fss, 'STR#', OVERRIDE_PATH_ID, default=path_loader)
111+
return PythonOptions(a_popt, a_dir, a_gusi, a_path)
112+
113+
def _test():
114+
import preferences
115+
preferences.debug = 1
116+
dict = PythonOptions().load()
117+
for k in dict.keys():
118+
print k, '\t', dict[k]
119+
120+
if __name__ == '__main__':
121+
_test()
122+

0 commit comments

Comments
 (0)