44import stat
55
66
7+ # Normalize the case of a pathname. Trivial in Posix, string.lower on Mac.
8+ # On MS-DOS this may also turn slashes into backslashes; however, other
9+ # normalizations (such as optimizing '../' away) are not allowed
10+ # (another function should be defined to do that).
11+
12+ def normcase (s ):
13+ return s
14+
15+
16+ # Return wheter a path is absolute.
17+ # Trivial in Posix, harder on the Mac or MS-DOS.
18+
19+ def isabs (s ):
20+ return s [:1 ] == '/'
21+
22+
723# Join two pathnames.
24+ # Ignore the first part if the second part is absolute.
825# Insert a '/' unless the first part is empty or already ends in '/'.
9- # Ignore the first part altogether if the second part is absolute
10- # (begins with '/').
11- #
26+
1227def join (a , b ):
1328 if b [:1 ] == '/' : return b
1429 if a == '' or a [- 1 :] == '/' : return a + b
1530 # Note: join('x', '') returns 'x/'; is this what we want?
1631 return a + '/' + b
1732
1833
19- cat = join # For compatibility
20-
21-
2234# Split a path in head (empty or ending in '/') and tail (no '/').
2335# The tail will be empty if the path ends in '/'.
24- # It is always true that head+tail = p.
25- #
36+ # It is always true that head + tail == p; also join(head, tail) == p.
37+ # Note that because head ends in '/', if you want to find all components
38+ # of a path by repeatedly getting the head, you will have to strip off
39+ # the trailing '/' yourself (another function should be defined to
40+ # split an entire path into components.)
41+
2642def split (p ):
2743 head , tail = '' , ''
2844 for c in p :
@@ -35,8 +51,8 @@ def split(p):
3551# Split a path in root and extension.
3652# The extension is everything starting at the first dot in the last
3753# pathname component; the root is everything before that.
38- # It is always true that root+ ext = p.
39- #
54+ # It is always true that root + ext = = p.
55+
4056def splitext (p ):
4157 root , ext = '' , ''
4258 for c in p :
@@ -50,13 +66,13 @@ def splitext(p):
5066
5167
5268# Return the tail (basename) part of a path.
53- #
69+
5470def basename (p ):
5571 return split (p )[1 ]
5672
5773
5874# Return the longest prefix of all list elements.
59- #
75+
6076def commonprefix (m ):
6177 if not m : return ''
6278 prefix = m [0 ]
@@ -69,8 +85,20 @@ def commonprefix(m):
6985 return prefix
7086
7187
72- # Does a file/directory exist?
73- #
88+ # Is a path a symbolic link?
89+ # This will always return false on systems where posix.lstat doesn't exist.
90+
91+ def islink (path ):
92+ try :
93+ st = posix .lstat (path )
94+ except (posix .error , AttributeError ):
95+ return 0
96+ return stat .S_ISLNK (st [stat .ST_MODE ])
97+
98+
99+ # Does a path exist?
100+ # This is false for dangling symbolic links.
101+
74102def exists (path ):
75103 try :
76104 st = posix .stat (path )
@@ -80,7 +108,9 @@ def exists(path):
80108
81109
82110# Is a path a posix directory?
83- #
111+ # This follows symbolic links, so both islink() and isdir() can be true
112+ # for the same path.
113+
84114def isdir (path ):
85115 try :
86116 st = posix .stat (path )
@@ -89,19 +119,20 @@ def isdir(path):
89119 return stat .S_ISDIR (st [stat .ST_MODE ])
90120
91121
92- # Is a path a symbolic link?
93- # This will always return false on systems where posix.lstat doesn't exist.
94- #
95- def islink (path ):
122+ # Is a path a regulat file?
123+ # This follows symbolic links, so both islink() and isdir() can be true
124+ # for the same path.
125+
126+ def isfile (path ):
96127 try :
97- st = posix .lstat (path )
98- except ( posix .error , AttributeError ) :
128+ st = posix .stat (path )
129+ except posix .error :
99130 return 0
100- return stat .S_ISLNK (st [stat .ST_MODE ])
131+ return stat .S_ISREG (st [stat .ST_MODE ])
101132
102133
103134# Are two filenames really pointing to the same file?
104- #
135+
105136def samefile (f1 , f2 ):
106137 s1 = posix .stat (f1 )
107138 s2 = posix .stat (f2 )
@@ -111,7 +142,7 @@ def samefile(f1, f2):
111142# Are two open files really referencing the same file?
112143# (Not necessarily the same file descriptor!)
113144# XXX Oops, posix.fstat() doesn't exist yet!
114- #
145+
115146def sameopenfile (fp1 , fp2 ):
116147 s1 = posix .fstat (fp1 )
117148 s2 = posix .fstat (fp2 )
@@ -120,7 +151,7 @@ def sameopenfile(fp1, fp2):
120151
121152# Are two stat buffers (obtained from stat, fstat or lstat)
122153# describing the same file?
123- #
154+
124155def samestat (s1 , s2 ):
125156 return s1 [stat .ST_INO ] == s2 [stat .ST_INO ] and \
126157 s1 [stat .ST_DEV ] == s2 [stat .STD_DEV ]
@@ -143,24 +174,28 @@ def _getmounts():
143174
144175
145176# Is a path a mount point?
146- # This only works for normalized, absolute paths,
177+ # This only works for normalized paths,
147178# and only if the mount table as printed by /etc/mount is correct.
148- # Sorry.
149- #
179+ # It tries to make relative paths absolute by prefixing them with the
180+ # current directory, but it won't normalize arguments containing '../'
181+ # or symbolic links.
182+
150183def ismount (path ):
184+ if not isabs (path ):
185+ path = join (posix .getcwd (), path )
151186 if not _mounts :
152187 _mounts [:] = _getmounts ()
153188 return path in _mounts
154189
155190
156191# Directory tree walk.
157- # For each directory under top (including top itself),
158- # func(arg, dirname, filenames) is called, where dirname
159- # is the name of the directory and filenames is the list of
160- # files (and subdirectories etc.) in the directory.
161- # func may modify the filenames list, to implement a filter,
192+ # For each directory under top (including top itself, but excluding
193+ # '.' and '..'), func(arg, dirname, filenames) is called, where
194+ # dirname is the name of the directory and filenames is the list
195+ # files files (and subdirectories etc.) in the directory.
196+ # The func may modify the filenames list, to implement a filter,
162197# or to impose a different order of visiting.
163- #
198+
164199def walk (top , func , arg ):
165200 try :
166201 names = posix .listdir (top )
@@ -173,3 +208,32 @@ def walk(top, func, arg):
173208 name = join (top , name )
174209 if isdir (name ):
175210 walk (name , func , arg )
211+
212+
213+ # Expand paths beginning with '~' or '~user'.
214+ # '~' means $HOME; '~user' means that user's home directory.
215+ # If the path doesn't begin with '~', or if the user or $HOME is unknown,
216+ # the path is returned unchanged (leaving error reporting to whatever
217+ # function is called with the expanded path as argument).
218+ # See also module 'glob' for expansion of *, ? and [...] in pathnames.
219+ # (A function should also be defined to do full *sh-style environment
220+ # variable expansion.)
221+
222+ def expanduser (path ):
223+ if path [:1 ] <> '~' :
224+ return path
225+ i , n = 1 , len (path )
226+ while i < n and path [i ] <> '/' :
227+ i = i + 1
228+ if i == 1 :
229+ if not posix .environ .has_key ('HOME' ):
230+ return path
231+ userhome = posix .environ ['HOME' ]
232+ else :
233+ import pwd
234+ try :
235+ pwent = pwd .getpwnam (path [1 :i ])
236+ except KeyError :
237+ return path
238+ userhome = pwent [5 ]
239+ return userhome + path [i :]
0 commit comments