blob: d693c87226d6b0faf0e039b64df35619cfaa7406 [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
Benjamin Petersona6864e02008-07-14 17:42:17 +00004warnpy3k("In 3.x, the macresource module is removed.", stacklevel=2)
Benjamin Peterson23681932008-05-12 21:42:13 +00005
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"""
Ronald Oussoren25967582009-09-06 10:00:26 +000080 # No resource fork. We may be on OSX, and this may be either
81 # a data-fork based resource file or a AppleSingle file
82 # from the CVS repository.
Jack Jansen0ae32202003-04-09 13:25:43 +000083 try:
Ronald Oussoren25967582009-09-06 10:00:26 +000084 refno = Res.FSOpenResourceFile(pathname, u'', 1)
Jack Jansen0ae32202003-04-09 13:25:43 +000085 except Res.Error, arg:
Ronald Oussoren25967582009-09-06 10:00:26 +000086 if arg[0] != -199:
87 # -199 is "bad resource map"
Jack Jansen0ae32202003-04-09 13:25:43 +000088 raise
Ronald Oussoren25967582009-09-06 10:00:26 +000089 else:
90 return refno
91 # Finally try decoding an AppleSingle file
92 pathname = _decode(pathname, verbose=verbose)
93 refno = Res.FSOpenResourceFile(pathname, u'', 1)
Tim Peters182b5ac2004-07-18 06:16:08 +000094
Jack Jansencba861e2003-02-25 23:02:03 +000095def resource_pathname(pathname, verbose=0):
Jack Jansen0ae32202003-04-09 13:25:43 +000096 """Return the pathname for a resource file (either DF or RF based).
97 If the pathname given already refers to such a file simply return it,
98 otherwise first decode it."""
Ronald Oussoren25967582009-09-06 10:00:26 +000099 # No resource fork. We may be on OSX, and this may be either
100 # a data-fork based resource file or a AppleSingle file
101 # from the CVS repository.
Jack Jansen0ae32202003-04-09 13:25:43 +0000102 try:
Ronald Oussoren25967582009-09-06 10:00:26 +0000103 refno = Res.FSOpenResourceFile(pathname, u'', 1)
Jack Jansen0ae32202003-04-09 13:25:43 +0000104 except Res.Error, arg:
Ronald Oussoren25967582009-09-06 10:00:26 +0000105 if arg[0] != -199:
106 # -199 is "bad resource map"
Jack Jansen0ae32202003-04-09 13:25:43 +0000107 raise
Ronald Oussoren25967582009-09-06 10:00:26 +0000108 else:
109 return refno
110 # Finally try decoding an AppleSingle file
111 pathname = _decode(pathname, verbose=verbose)
Jack Jansen0ae32202003-04-09 13:25:43 +0000112 return pathname
Tim Peters182b5ac2004-07-18 06:16:08 +0000113
Jack Jansendde800e2002-11-07 23:07:05 +0000114def open_error_resource():
Jack Jansen0ae32202003-04-09 13:25:43 +0000115 """Open the resource file containing the error code to error message
116 mapping."""
117 need('Estr', 1, filename="errors.rsrc", modname=__name__)
Tim Peters182b5ac2004-07-18 06:16:08 +0000118
Jack Jansencba861e2003-02-25 23:02:03 +0000119def _decode(pathname, verbose=0):
Jack Jansen0ae32202003-04-09 13:25:43 +0000120 # Decode an AppleSingle resource file, return the new pathname.
121 newpathname = pathname + '.df.rsrc'
122 if os.path.exists(newpathname) and \
123 os.stat(newpathname).st_mtime >= os.stat(pathname).st_mtime:
124 return newpathname
125 if hasattr(os, 'access') and not \
126 os.access(os.path.dirname(pathname), os.W_OK|os.X_OK):
127 # The destination directory isn't writeable. Create the file in
128 # a temporary directory
129 import tempfile
130 fd, newpathname = tempfile.mkstemp(".rsrc")
131 if verbose:
132 print 'Decoding', pathname, 'to', newpathname
133 import applesingle
134 applesingle.decode(pathname, newpathname, resonly=1)
135 return newpathname