1228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum# Module 'riscospath' -- common operations on RISC OS pathnames.
2228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
3228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum# contributed by Andrew Clover  ( andrew@oaktree.co.uk )
4228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
5228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum# The "os.path" name is an alias for this module on RISC OS systems;
6228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum# on other systems (e.g. Mac, Windows), os.path provides the same
7228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum# operations in a manner specific to that platform, and is an alias
8228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum# to another module (e.g. macpath, ntpath).
9228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
10228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum"""
11228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van RossumInstead of importing this module directly, import os and refer to this module
12228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossumas os.path.
13228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum"""
14228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
15117910dc445a2262bd96bbfefaf43714ae59c11bSkip Montanaro# strings representing various path-related bits and pieces
16117910dc445a2262bd96bbfefaf43714ae59c11bSkip Montanarocurdir = '@'
17117910dc445a2262bd96bbfefaf43714ae59c11bSkip Montanaropardir = '^'
18a94568a7535de60f1144e4eea0d027b87017a4b4Martin v. Löwisextsep = '/'
19117910dc445a2262bd96bbfefaf43714ae59c11bSkip Montanarosep = '.'
20117910dc445a2262bd96bbfefaf43714ae59c11bSkip Montanaropathsep = ','
21117910dc445a2262bd96bbfefaf43714ae59c11bSkip Montanarodefpath = '<Run$Dir>'
22117910dc445a2262bd96bbfefaf43714ae59c11bSkip Montanaroaltsep = None
23228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
24228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum# Imports - make an error-generating swi object if the swi module is not
25228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum# available (ie. we are not running on RISC OS Python)
26228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
27228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossumimport os, stat, string
28228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
29228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossumtry:
30683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    import swi
31228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossumexcept ImportError:
32683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    class _swi:
33683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters        def swi(*a):
34683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters            raise AttributeError, 'This function only available under RISC OS'
35683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters        block= swi
36683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    swi= _swi()
37228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
38228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum[_false, _true]= range(2)
39228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
40228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum_roots= ['$', '&', '%', '@', '\\']
41228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
42228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
43228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum# _allowMOSFSNames
44228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum# After importing riscospath, set _allowMOSFSNames true if you want the module
45228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum# to understand the "-SomeFS-" notation left over from the old BBC Master MOS,
46228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum# as well as the standard "SomeFS:" notation. Set this to be fully backwards
47228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum# compatible but remember that "-SomeFS-" can also be a perfectly valid file
48228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum# name so care must be taken when splitting and joining paths.
49228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
50228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum_allowMOSFSNames= _false
51228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
52228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
53228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum## Path manipulation, RISC OS stylee.
54228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
55228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossumdef _split(p):
56683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    """
57683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters  split filing system name (including special field) and drive specifier from rest
58683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters  of path. This is needed by many riscospath functions.
59228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum  """
60683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    dash= _allowMOSFSNames and p[:1]=='-'
61683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    if dash:
62683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters        q= string.find(p, '-', 1)+1
63683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    else:
64683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters        if p[:1]==':':
65683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters            q= 0
66683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters        else:
67683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters            q= string.find(p, ':')+1 # q= index of start of non-FS portion of path
68683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    s= string.find(p, '#')
69683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    if s==-1 or s>q:
70683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters        s= q # find end of main FS name, not including special field
71228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum    else:
72683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters        for c in p[dash:s]:
7379e75e1916c33ee8e3de4c1b6c38221f2dba315cFred Drake            if c not in string.ascii_letters:
74683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters                q= 0
75683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters                break # disallow invalid non-special-field characters in FS name
76683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    r= q
77683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    if p[q:q+1]==':':
78683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters        r= string.find(p, '.', q+1)+1
79683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters        if r==0:
80683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters            r= len(p) # find end of drive name (if any) following FS name (if any)
81683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    return (p[:q], p[q:r], p[r:])
82228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
83228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
84228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossumdef normcase(p):
85683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    """
86683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters  Normalize the case of a pathname. This converts to lowercase as the native RISC
87683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters  OS filesystems are case-insensitive. However, not all filesystems have to be,
88683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters  and there's no simple way to find out what type an FS is argh.
89228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum  """
90683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    return string.lower(p)
91228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
92228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
93228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossumdef isabs(p):
94683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    """
95683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters  Return whether a path is absolute. Under RISC OS, a file system specifier does
96683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters  not make a path absolute, but a drive name or number does, and so does using the
97683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters  symbol for root, URD, library, CSD or PSD. This means it is perfectly possible
98683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters  to have an "absolute" URL dependent on the current working directory, and
99683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters  equally you can have a "relative" URL that's on a completely different device to
100683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters  the current one argh.
101228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum  """
102683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    (fs, drive, path)= _split(p)
103683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    return drive!='' or path[:1] in _roots
104228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
105228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
106228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossumdef join(a, *p):
107683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    """
108683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters  Join path elements with the directory separator, replacing the entire path when
109683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters  an absolute or FS-changing path part is found.
110228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum  """
111683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    j= a
112683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    for b in p:
113683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters        (fs, drive, path)= _split(b)
114e2ae77b8b8a62e648bb1864a9b36ef3280984404Guido van Rossum        if j=='' or fs!='' or drive!='' or path[:1] in _roots:
115683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters            j= b
116e2ae77b8b8a62e648bb1864a9b36ef3280984404Guido van Rossum        elif j[-1]==':':
117e2ae77b8b8a62e648bb1864a9b36ef3280984404Guido van Rossum            j= j+b
118683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters        else:
119683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters            j= j+'.'+b
120683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    return j
121228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
122228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
123228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossumdef split(p):
124683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    """
125683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters  Split a path in head (everything up to the last '.') and tail (the rest). FS
126683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters  name must still be dealt with separately since special field may contain '.'.
127228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum  """
128683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    (fs, drive, path)= _split(p)
129683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    q= string.rfind(path, '.')
130683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    if q!=-1:
131683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters        return (fs+drive+path[:q], path[q+1:])
132683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    return ('', p)
133228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
134228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
135228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossumdef splitext(p):
136683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    """
137683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters  Split a path in root and extension. This assumes the 'using slash for dot and
138683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters  dot for slash with foreign files' convention common in RISC OS is in force.
139228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum  """
140683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    (tail, head)= split(p)
141683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    if '/' in head:
142683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters        q= len(head)-string.rfind(head, '/')
143683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters        return (p[:-q], p[-q:])
144683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    return (p, '')
145228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
146228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
147228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossumdef splitdrive(p):
148683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    """
149683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters  Split a pathname into a drive specification (including FS name) and the rest of
150683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters  the path. The terminating dot of the drive name is included in the drive
151683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters  specification.
152228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum  """
153683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    (fs, drive, path)= _split(p)
154683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    return (fs+drive, p)
155228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
156228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
157228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossumdef basename(p):
158683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    """
159683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters  Return the tail (basename) part of a path.
160228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum  """
161683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    return split(p)[1]
162228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
163228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
164228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossumdef dirname(p):
165683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    """
166683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters  Return the head (dirname) part of a path.
167228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum  """
168683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    return split(p)[0]
169228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
170228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
171649f8e7de2ad8fc42748b56e8e64574478d2d7feGeorg Brandldef commonprefix(m):
172649f8e7de2ad8fc42748b56e8e64574478d2d7feGeorg Brandl    "Given a list of pathnames, returns the longest common leading component"
173649f8e7de2ad8fc42748b56e8e64574478d2d7feGeorg Brandl    if not m: return ''
174649f8e7de2ad8fc42748b56e8e64574478d2d7feGeorg Brandl    s1 = min(m)
175649f8e7de2ad8fc42748b56e8e64574478d2d7feGeorg Brandl    s2 = max(m)
176649f8e7de2ad8fc42748b56e8e64574478d2d7feGeorg Brandl    n = min(len(s1), len(s2))
177649f8e7de2ad8fc42748b56e8e64574478d2d7feGeorg Brandl    for i in xrange(n):
178649f8e7de2ad8fc42748b56e8e64574478d2d7feGeorg Brandl        if s1[i] != s2[i]:
179649f8e7de2ad8fc42748b56e8e64574478d2d7feGeorg Brandl            return s1[:i]
180649f8e7de2ad8fc42748b56e8e64574478d2d7feGeorg Brandl    return s1[:n]
181228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
182228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
183228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum## File access functions. Why are we in os.path?
184228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
185228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossumdef getsize(p):
186683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    """
187683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters  Return the size of a file, reported by os.stat().
188228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum  """
189683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    st= os.stat(p)
190683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    return st[stat.ST_SIZE]
191228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
192228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
193228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossumdef getmtime(p):
194683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    """
195683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters  Return the last modification time of a file, reported by os.stat().
196228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum  """
197683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    st = os.stat(p)
198683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    return st[stat.ST_MTIME]
199228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
200228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossumgetatime= getmtime
201228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
202228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
203228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum# RISC OS-specific file access functions
204228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
205228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossumdef exists(p):
206683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    """
207683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters  Test whether a path exists.
208228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum  """
209683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    try:
210683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters        return swi.swi('OS_File', '5s;i', p)!=0
211683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    except swi.error:
212683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters        return 0
213228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
214ae882f798435266b41a9c8966562102345a3eda5Johannes Gijsberslexists = exists
215ae882f798435266b41a9c8966562102345a3eda5Johannes Gijsbers
216228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
217228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossumdef isdir(p):
218683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    """
219683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters  Is a path a directory? Includes image files.
220228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum  """
221683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    try:
222683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters        return swi.swi('OS_File', '5s;i', p) in [2, 3]
223683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    except swi.error:
224683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters        return 0
225228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
226228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
227228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossumdef isfile(p):
228683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    """
229683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters  Test whether a path is a file, including image files.
230228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum  """
231683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    try:
232683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters        return swi.swi('OS_File', '5s;i', p) in [1, 3]
233683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    except swi.error:
234683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters        return 0
235228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
236228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
237228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossumdef islink(p):
238683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    """
239683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters  RISC OS has no links or mounts.
240228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum  """
241683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    return _false
242228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
243228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossumismount= islink
244228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
245228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
246228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum# Same-file testing.
247228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
248228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum# samefile works on filename comparison since there is no ST_DEV and ST_INO is
249228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum# not reliably unique (esp. directories). First it has to normalise the
250228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum# pathnames, which it can do 'properly' using OS_FSControl since samefile can
251228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum# assume it's running on RISC OS (unlike normpath).
252228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
253228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossumdef samefile(fa, fb):
254683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    """
255683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters  Test whether two pathnames reference the same actual file.
256228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum  """
257683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    l= 512
258683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    b= swi.block(l)
259683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    swi.swi('OS_FSControl', 'isb..i', 37, fa, b, l)
260683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    fa= b.ctrlstring()
261683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    swi.swi('OS_FSControl', 'isb..i', 37, fb, b, l)
262683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    fb= b.ctrlstring()
263683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    return fa==fb
264228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
265228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
266228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossumdef sameopenfile(a, b):
267683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    """
268683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters  Test whether two open file objects reference the same file.
269228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum  """
270683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    return os.fstat(a)[stat.ST_INO]==os.fstat(b)[stat.ST_INO]
271228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
272228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
273228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum## Path canonicalisation
274228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
275228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum# 'user directory' is taken as meaning the User Root Directory, which is in
276228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum# practice never used, for anything.
277228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
278228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossumdef expanduser(p):
279683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    (fs, drive, path)= _split(p)
280683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    l= 512
281683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    b= swi.block(l)
282683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters
283683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    if path[:1]!='@':
284683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters        return p
285683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    if fs=='':
286683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters        fsno= swi.swi('OS_Args', '00;i')
287683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters        swi.swi('OS_FSControl', 'iibi', 33, fsno, b, l)
288683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters        fsname= b.ctrlstring()
289228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum    else:
290683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters        if fs[:1]=='-':
291683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters            fsname= fs[1:-1]
292683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters        else:
293683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters            fsname= fs[:-1]
294683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters        fsname= string.split(fsname, '#', 1)[0] # remove special field from fs
295683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    x= swi.swi('OS_FSControl', 'ib2s.i;.....i', 54, b, fsname, l)
296228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum    if x<l:
297683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters        urd= b.tostring(0, l-x-1)
298683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    else: # no URD! try CSD
299683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters        x= swi.swi('OS_FSControl', 'ib0s.i;.....i', 54, b, fsname, l)
300683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters        if x<l:
301683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters            urd= b.tostring(0, l-x-1)
302683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters        else: # no CSD! use root
303683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters            urd= '$'
304683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    return fsname+':'+urd+path[1:]
305228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
306228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum# Environment variables are in angle brackets.
307228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
308228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossumdef expandvars(p):
309683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    """
310683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters  Expand environment variables using OS_GSTrans.
311228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum  """
312683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    l= 512
313683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    b= swi.block(l)
314683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    return b.tostring(0, swi.swi('OS_GSTrans', 'sbi;..i', p, b, l))
315228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
316228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
3171422e9dc60bd795b0bf8d8877087ce1eb6ad6942Tim Peters# Return an absolute path. RISC OS' osfscontrol_canonicalise_path does this among others
3181422e9dc60bd795b0bf8d8877087ce1eb6ad6942Tim Petersabspath = os.expand
319228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
320228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
32183eeef4b067b7182778581c9fdfb104492647bd4Guido van Rossum# realpath is a no-op on systems without islink support
32283eeef4b067b7182778581c9fdfb104492647bd4Guido van Rossumrealpath = abspath
32383eeef4b067b7182778581c9fdfb104492647bd4Guido van Rossum
32483eeef4b067b7182778581c9fdfb104492647bd4Guido van Rossum
325228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum# Normalize a path. Only special path element under RISC OS is "^" for "..".
326228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
327228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossumdef normpath(p):
328683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    """
329683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters  Normalize path, eliminating up-directory ^s.
330228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum  """
331683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    (fs, drive, path)= _split(p)
332683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    rhs= ''
333683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    ups= 0
334683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    while path!='':
335683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters        (path, el)= split(path)
336683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters        if el=='^':
337683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters            ups= ups+1
338228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum        else:
339683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters            if ups>0:
340683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters                ups= ups-1
341683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters            else:
342683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters                if rhs=='':
343683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters                    rhs= el
344683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters                else:
345683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters                    rhs= el+'.'+rhs
346683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    while ups>0:
347683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters        ups= ups-1
348683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters        rhs= '^.'+rhs
349683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    return fs+drive+rhs
350228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
351228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
352228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum# Directory tree walk.
353228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum# Independent of host system. Why am I in os.path?
354228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossum
355228d80736c39e41a6b46dad211df0ba871b0c8f8Guido van Rossumdef walk(top, func, arg):
356cf5e6a4a5dc85ca21bc62b0555781283a9810c3cTim Peters    """Directory tree walk with callback function.
357cf5e6a4a5dc85ca21bc62b0555781283a9810c3cTim Peters
358cf5e6a4a5dc85ca21bc62b0555781283a9810c3cTim Peters    For each directory in the directory tree rooted at top (including top
359cf5e6a4a5dc85ca21bc62b0555781283a9810c3cTim Peters    itself, but excluding '.' and '..'), call func(arg, dirname, fnames).
360cf5e6a4a5dc85ca21bc62b0555781283a9810c3cTim Peters    dirname is the name of the directory, and fnames a list of the names of
361cf5e6a4a5dc85ca21bc62b0555781283a9810c3cTim Peters    the files and subdirectories in dirname (excluding '.' and '..').  func
362cf5e6a4a5dc85ca21bc62b0555781283a9810c3cTim Peters    may modify the fnames list in-place (e.g. via del or slice assignment),
363cf5e6a4a5dc85ca21bc62b0555781283a9810c3cTim Peters    and walk will only recurse into the subdirectories whose names remain in
364cf5e6a4a5dc85ca21bc62b0555781283a9810c3cTim Peters    fnames; this can be used to implement a filter, or to impose a specific
365cf5e6a4a5dc85ca21bc62b0555781283a9810c3cTim Peters    order of visiting.  No semantics are defined for, or required of, arg,
366cf5e6a4a5dc85ca21bc62b0555781283a9810c3cTim Peters    beyond that arg is always passed to func.  It can be used, e.g., to pass
367cf5e6a4a5dc85ca21bc62b0555781283a9810c3cTim Peters    a filename pattern, or a mutable object designed to accumulate
368cf5e6a4a5dc85ca21bc62b0555781283a9810c3cTim Peters    statistics.  Passing None for arg is common."""
369cf5e6a4a5dc85ca21bc62b0555781283a9810c3cTim Peters
370683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    try:
371683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters        names= os.listdir(top)
372683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    except os.error:
373683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters        return
374683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    func(arg, top, names)
375683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters    for name in names:
376683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters        name= join(top, name)
377683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters        if isdir(name) and not islink(name):
378683ecc7374fd5ab05b03565b0f1191419fd9ae1aTim Peters            walk(name, func, arg)
379