1"""macresource - Locate and open the resources needed for a script."""
2
3from warnings import warnpy3k
4warnpy3k("In 3.x, the macresource module is removed.", stacklevel=2)
5
6from Carbon import Res
7import os
8import sys
9import MacOS
10import macostools
11
12class ArgumentError(TypeError): pass
13class ResourceFileNotFoundError(ImportError): pass
14
15def need(restype, resid, filename=None, modname=None):
16    """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.
21
22    Returns the refno of the resource file opened (or None)"""
23
24    if modname is None and filename is None:
25        raise ArgumentError, "Either filename or modname argument (or both) must be given"
26
27    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
41
42    # 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'
48
49    # 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 modname in sys.modules:
55        mod = sys.modules[modname]
56        if hasattr(mod, '__file__'):
57            searchdirs = [os.path.dirname(mod.__file__)]
58    searchdirs.extend(sys.path)
59
60    # 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
67
68    refno = open_pathname(pathname)
69
70    # 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
76
77def open_pathname(pathname, verbose=0):
78    """Open a resource file given by pathname, possibly decoding an
79    AppleSingle file"""
80    # 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.
83    try:
84        refno = Res.FSOpenResourceFile(pathname, u'', 1)
85    except Res.Error, arg:
86        if arg[0] != -199:
87            # -199 is "bad resource map"
88            raise
89    else:
90        return refno
91    # Finally try decoding an AppleSingle file
92    pathname = _decode(pathname, verbose=verbose)
93    refno = Res.FSOpenResourceFile(pathname, u'', 1)
94
95def resource_pathname(pathname, verbose=0):
96    """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."""
99    # 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.
102    try:
103        refno = Res.FSOpenResourceFile(pathname, u'', 1)
104    except Res.Error, arg:
105        if arg[0] != -199:
106            # -199 is "bad resource map"
107            raise
108    else:
109        return refno
110    # Finally try decoding an AppleSingle file
111    pathname = _decode(pathname, verbose=verbose)
112    return pathname
113
114def open_error_resource():
115    """Open the resource file containing the error code to error message
116    mapping."""
117    need('Estr', 1, filename="errors.rsrc", modname=__name__)
118
119def _decode(pathname, verbose=0):
120    # 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
136