blob: 0a66d76ae7720a3a39083fbdbb0067286310e83e [file] [log] [blame]
Jack Jansende3226f2001-08-27 21:21:07 +00001"""macresource - Locate and open the resources needed for a script."""
2
Benjamin Peterson23681932008-05-12 21:42:13 +00003from warnings import warnpy3k
4warnpy3k("In 3.x, the macresource module is removed.")
5
Jack Jansende3226f2001-08-27 21:21:07 +00006from Carbon import Res
7import os
8import sys
Jack Jansen946c1942003-02-17 16:47:12 +00009import MacOS
10import macostools
Jack Jansende3226f2001-08-27 21:21:07 +000011
12class ArgumentError(TypeError): pass
13class ResourceFileNotFoundError(ImportError): pass
14
15def need(restype, resid, filename=None, modname=None):
Jack Jansen0ae32202003-04-09 13:25:43 +000016 """Open a resource file, if needed. restype and resid
17 are required parameters, and identify the resource for which to test. If it
18 is available we are done. If it is not available we look for a file filename
19 (default: modname with .rsrc appended) either in the same folder as
20 where modname was loaded from, or otherwise across sys.path.
Tim Peters182b5ac2004-07-18 06:16:08 +000021
Jack Jansen0ae32202003-04-09 13:25:43 +000022 Returns the refno of the resource file opened (or None)"""
Jack Jansende3226f2001-08-27 21:21:07 +000023
Jack Jansen0ae32202003-04-09 13:25:43 +000024 if modname is None and filename is None:
25 raise ArgumentError, "Either filename or modname argument (or both) must be given"
Tim Peters182b5ac2004-07-18 06:16:08 +000026
Jack Jansen0ae32202003-04-09 13:25:43 +000027 if type(resid) is type(1):
28 try:
29 h = Res.GetResource(restype, resid)
30 except Res.Error:
31 pass
32 else:
33 return None
34 else:
35 try:
36 h = Res.GetNamedResource(restype, resid)
37 except Res.Error:
38 pass
39 else:
40 return None
Tim Peters182b5ac2004-07-18 06:16:08 +000041
Jack Jansen0ae32202003-04-09 13:25:43 +000042 # Construct a filename if we don't have one
43 if not filename:
44 if '.' in modname:
45 filename = modname.split('.')[-1] + '.rsrc'
46 else:
47 filename = modname + '.rsrc'
Tim Peters182b5ac2004-07-18 06:16:08 +000048
Jack Jansen0ae32202003-04-09 13:25:43 +000049 # Now create a list of folders to search
50 searchdirs = []
51 if modname == '__main__':
52 # If we're main we look in the current directory
53 searchdirs = [os.curdir]
54 if sys.modules.has_key(modname):
55 mod = sys.modules[modname]
56 if hasattr(mod, '__file__'):
57 searchdirs = [os.path.dirname(mod.__file__)]
58 searchdirs.extend(sys.path)
Tim Peters182b5ac2004-07-18 06:16:08 +000059
Jack Jansen0ae32202003-04-09 13:25:43 +000060 # And look for the file
61 for dir in searchdirs:
62 pathname = os.path.join(dir, filename)
63 if os.path.exists(pathname):
64 break
65 else:
66 raise ResourceFileNotFoundError, filename
Tim Peters182b5ac2004-07-18 06:16:08 +000067
Jack Jansen0ae32202003-04-09 13:25:43 +000068 refno = open_pathname(pathname)
Tim Peters182b5ac2004-07-18 06:16:08 +000069
Jack Jansen0ae32202003-04-09 13:25:43 +000070 # And check that the resource exists now
71 if type(resid) is type(1):
72 h = Res.GetResource(restype, resid)
73 else:
74 h = Res.GetNamedResource(restype, resid)
75 return refno
Tim Peters182b5ac2004-07-18 06:16:08 +000076
Jack Jansenccd8e8d2002-08-09 13:44:03 +000077def open_pathname(pathname, verbose=0):
Jack Jansen0ae32202003-04-09 13:25:43 +000078 """Open a resource file given by pathname, possibly decoding an
79 AppleSingle file"""
80 try:
81 refno = Res.FSpOpenResFile(pathname, 1)
82 except Res.Error, arg:
83 if arg[0] in (-37, -39):
84 # No resource fork. We may be on OSX, and this may be either
85 # a data-fork based resource file or a AppleSingle file
86 # from the CVS repository.
87 try:
88 refno = Res.FSOpenResourceFile(pathname, u'', 1)
89 except Res.Error, arg:
90 if arg[0] != -199:
91 # -199 is "bad resource map"
92 raise
93 else:
94 return refno
95 # Finally try decoding an AppleSingle file
96 pathname = _decode(pathname, verbose=verbose)
97 refno = Res.FSOpenResourceFile(pathname, u'', 1)
98 else:
99 raise
100 return refno
Tim Peters182b5ac2004-07-18 06:16:08 +0000101
Jack Jansencba861e2003-02-25 23:02:03 +0000102def resource_pathname(pathname, verbose=0):
Jack Jansen0ae32202003-04-09 13:25:43 +0000103 """Return the pathname for a resource file (either DF or RF based).
104 If the pathname given already refers to such a file simply return it,
105 otherwise first decode it."""
106 try:
107 refno = Res.FSpOpenResFile(pathname, 1)
108 Res.CloseResFile(refno)
109 except Res.Error, arg:
110 if arg[0] in (-37, -39):
111 # No resource fork. We may be on OSX, and this may be either
112 # a data-fork based resource file or a AppleSingle file
113 # from the CVS repository.
114 try:
115 refno = Res.FSOpenResourceFile(pathname, u'', 1)
116 except Res.Error, arg:
117 if arg[0] != -199:
118 # -199 is "bad resource map"
119 raise
120 else:
121 return refno
122 # Finally try decoding an AppleSingle file
123 pathname = _decode(pathname, verbose=verbose)
124 else:
125 raise
126 return pathname
Tim Peters182b5ac2004-07-18 06:16:08 +0000127
Jack Jansendde800e2002-11-07 23:07:05 +0000128def open_error_resource():
Jack Jansen0ae32202003-04-09 13:25:43 +0000129 """Open the resource file containing the error code to error message
130 mapping."""
131 need('Estr', 1, filename="errors.rsrc", modname=__name__)
Tim Peters182b5ac2004-07-18 06:16:08 +0000132
Jack Jansencba861e2003-02-25 23:02:03 +0000133def _decode(pathname, verbose=0):
Jack Jansen0ae32202003-04-09 13:25:43 +0000134 # Decode an AppleSingle resource file, return the new pathname.
135 newpathname = pathname + '.df.rsrc'
136 if os.path.exists(newpathname) and \
137 os.stat(newpathname).st_mtime >= os.stat(pathname).st_mtime:
138 return newpathname
139 if hasattr(os, 'access') and not \
140 os.access(os.path.dirname(pathname), os.W_OK|os.X_OK):
141 # The destination directory isn't writeable. Create the file in
142 # a temporary directory
143 import tempfile
144 fd, newpathname = tempfile.mkstemp(".rsrc")
145 if verbose:
146 print 'Decoding', pathname, 'to', newpathname
147 import applesingle
148 applesingle.decode(pathname, newpathname, resonly=1)
149 return newpathname