blob: af4990fb8bfae18de1117a4489fb16de2f380f85 [file] [log] [blame]
Georg Brandlbde4ad42006-01-20 21:36:02 +00001r"""OS routines for Mac, NT, or Posix depending on what system we're on.
Guido van Rossum31104f41992-01-14 18:28:36 +00002
Guido van Rossum54f22ed2000-02-04 15:10:34 +00003This exports:
Alexandre Vassalottieca20b62008-05-16 02:54:33 +00004 - all functions from posix, nt, os2, or ce, e.g. unlink, stat, etc.
5 - os.path is either posixpath or ntpath
6 - os.name is either 'posix', 'nt', 'os2' or 'ce'.
Guido van Rossum54f22ed2000-02-04 15:10:34 +00007 - os.curdir is a string representing the current directory ('.' or ':')
8 - os.pardir is a string representing the parent directory ('..' or '::')
9 - os.sep is the (or a most common) pathname separator ('/' or ':' or '\\')
Georg Brandled5b9b32008-12-05 07:45:54 +000010 - os.extsep is the extension separator (always '.')
Guido van Rossum4b8c6ea2000-02-04 15:39:30 +000011 - os.altsep is the alternate pathname separator (None or '/')
Guido van Rossum54f22ed2000-02-04 15:10:34 +000012 - os.pathsep is the component separator used in $PATH etc
Guido van Rossum4b8c6ea2000-02-04 15:39:30 +000013 - os.linesep is the line separator in text files ('\r' or '\n' or '\r\n')
Guido van Rossum54f22ed2000-02-04 15:10:34 +000014 - os.defpath is the default search path for executables
Martin v. Löwisbdec50f2004-06-08 08:29:33 +000015 - os.devnull is the file path of the null device ('/dev/null', etc.)
Guido van Rossum31104f41992-01-14 18:28:36 +000016
Guido van Rossum54f22ed2000-02-04 15:10:34 +000017Programs that import and use 'os' stand a better chance of being
18portable between different platforms. Of course, they must then
19only use functions that are defined by all platforms (e.g., unlink
20and opendir), and leave all pathname manipulation to os.path
21(e.g., split and join).
22"""
Guido van Rossum31104f41992-01-14 18:28:36 +000023
Skip Montanaro269b83b2001-02-06 01:07:02 +000024#'
25
Christian Heimes45f9af32007-11-27 21:50:00 +000026import sys, errno
Charles-François Natali7372b062012-02-05 15:15:38 +010027import stat as st
Guido van Rossuma28dab51997-08-29 22:36:47 +000028
29_names = sys.builtin_module_names
30
Tim Petersc4e09402003-04-25 07:11:48 +000031# Note: more names are added to __all__ later.
Brett Cannon13962fc2008-08-18 01:45:29 +000032__all__ = ["altsep", "curdir", "pardir", "sep", "pathsep", "linesep",
Martin v. Löwis22b457e2005-01-16 08:40:58 +000033 "defpath", "name", "path", "devnull",
34 "SEEK_SET", "SEEK_CUR", "SEEK_END"]
Skip Montanaro269b83b2001-02-06 01:07:02 +000035
Charles-François Natali7372b062012-02-05 15:15:38 +010036def _exists(name):
37 return name in globals()
38
Skip Montanaro269b83b2001-02-06 01:07:02 +000039def _get_exports_list(module):
40 try:
41 return list(module.__all__)
42 except AttributeError:
43 return [n for n in dir(module) if n[0] != '_']
44
Brett Cannonfd074152012-04-14 14:10:13 -040045# Any new dependencies of the os module and/or changes in path separator
46# requires updating importlib as well.
Guido van Rossuma28dab51997-08-29 22:36:47 +000047if 'posix' in _names:
Guido van Rossum61de0ac1997-12-05 21:24:30 +000048 name = 'posix'
Guido van Rossume9387ea1998-05-22 15:26:04 +000049 linesep = '\n'
Guido van Rossum61de0ac1997-12-05 21:24:30 +000050 from posix import *
51 try:
52 from posix import _exit
53 except ImportError:
54 pass
Skip Montanaro117910d2003-02-14 19:35:31 +000055 import posixpath as path
Tim Petersf2715e02003-02-19 02:35:07 +000056
Skip Montanaro269b83b2001-02-06 01:07:02 +000057 import posix
58 __all__.extend(_get_exports_list(posix))
59 del posix
60
Guido van Rossuma28dab51997-08-29 22:36:47 +000061elif 'nt' in _names:
Guido van Rossum61de0ac1997-12-05 21:24:30 +000062 name = 'nt'
Guido van Rossume9387ea1998-05-22 15:26:04 +000063 linesep = '\r\n'
Guido van Rossum61de0ac1997-12-05 21:24:30 +000064 from nt import *
Tim Peters6757c1e2003-01-08 21:20:57 +000065 try:
66 from nt import _exit
67 except ImportError:
68 pass
Skip Montanaro117910d2003-02-14 19:35:31 +000069 import ntpath as path
Tim Petersf2715e02003-02-19 02:35:07 +000070
Skip Montanaro269b83b2001-02-06 01:07:02 +000071 import nt
72 __all__.extend(_get_exports_list(nt))
73 del nt
74
Guido van Rossum8e9ebfd1997-11-22 21:53:48 +000075elif 'os2' in _names:
Guido van Rossum61de0ac1997-12-05 21:24:30 +000076 name = 'os2'
Guido van Rossume9387ea1998-05-22 15:26:04 +000077 linesep = '\r\n'
Guido van Rossum61de0ac1997-12-05 21:24:30 +000078 from os2 import *
79 try:
80 from os2 import _exit
81 except ImportError:
82 pass
Andrew MacIntyre5cef5712002-02-24 05:32:32 +000083 if sys.version.find('EMX GCC') == -1:
Skip Montanaro117910d2003-02-14 19:35:31 +000084 import ntpath as path
Andrew MacIntyre5cef5712002-02-24 05:32:32 +000085 else:
Skip Montanaro117910d2003-02-14 19:35:31 +000086 import os2emxpath as path
Andrew MacIntyre89f98652003-12-02 12:33:01 +000087 from _emx_link import link
Tim Petersf2715e02003-02-19 02:35:07 +000088
Skip Montanaro269b83b2001-02-06 01:07:02 +000089 import os2
90 __all__.extend(_get_exports_list(os2))
91 del os2
92
Guido van Rossum18df5d41999-06-11 01:37:27 +000093elif 'ce' in _names:
94 name = 'ce'
95 linesep = '\r\n'
Guido van Rossum18df5d41999-06-11 01:37:27 +000096 from ce import *
Tim Peters6757c1e2003-01-08 21:20:57 +000097 try:
98 from ce import _exit
99 except ImportError:
100 pass
Guido van Rossum18df5d41999-06-11 01:37:27 +0000101 # We can use the standard Windows path.
Skip Montanaro117910d2003-02-14 19:35:31 +0000102 import ntpath as path
Tim Petersf2715e02003-02-19 02:35:07 +0000103
Skip Montanaro269b83b2001-02-06 01:07:02 +0000104 import ce
105 __all__.extend(_get_exports_list(ce))
106 del ce
107
Guido van Rossum2979b011994-08-01 11:18:30 +0000108else:
Collin Winter828f04a2007-08-31 00:04:24 +0000109 raise ImportError('no os specific module found')
Guido van Rossume65cce51993-11-08 15:05:21 +0000110
Skip Montanaro117910d2003-02-14 19:35:31 +0000111sys.modules['os.path'] = path
Georg Brandled5b9b32008-12-05 07:45:54 +0000112from os.path import (curdir, pardir, sep, pathsep, defpath, extsep, altsep,
113 devnull)
Skip Montanaro269b83b2001-02-06 01:07:02 +0000114
Guido van Rossuma28dab51997-08-29 22:36:47 +0000115del _names
116
Martin v. Löwis22b457e2005-01-16 08:40:58 +0000117# Python uses fixed values for the SEEK_ constants; they are mapped
118# to native constants if necessary in posixmodule.c
119SEEK_SET = 0
120SEEK_CUR = 1
121SEEK_END = 2
122
Terry Reedy5a22b652010-12-02 07:05:56 +0000123
124def _get_masked_mode(mode):
125 mask = umask(0)
126 umask(mask)
127 return mode & ~mask
128
Guido van Rossum4def7de1998-07-24 20:48:03 +0000129# Super directory utilities.
130# (Inspired by Eric Raymond; the doc strings are mostly his)
131
Terry Reedy5a22b652010-12-02 07:05:56 +0000132def makedirs(name, mode=0o777, exist_ok=False):
133 """makedirs(path [, mode=0o777][, exist_ok=False])
Guido van Rossum4def7de1998-07-24 20:48:03 +0000134
135 Super-mkdir; create a leaf directory and all intermediate ones.
136 Works like mkdir, except that any intermediate path segment (not
Terry Reedy5a22b652010-12-02 07:05:56 +0000137 just the rightmost) will be created if it does not exist. If the
138 target directory with the same mode as we specified already exists,
139 raises an OSError if exist_ok is False, otherwise no exception is
140 raised. This is recursive.
Guido van Rossum4def7de1998-07-24 20:48:03 +0000141
142 """
143 head, tail = path.split(name)
Fred Drake9f2550f2000-07-25 15:16:40 +0000144 if not tail:
145 head, tail = path.split(head)
Guido van Rossum4def7de1998-07-24 20:48:03 +0000146 if head and tail and not path.exists(head):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000147 try:
Terry Reedy5a22b652010-12-02 07:05:56 +0000148 makedirs(head, mode, exist_ok)
Guido van Rossumb940e112007-01-10 16:19:56 +0000149 except OSError as e:
Thomas Wouters89f507f2006-12-13 04:49:30 +0000150 # be happy if someone already created the path
Christian Heimes45f9af32007-11-27 21:50:00 +0000151 if e.errno != errno.EEXIST:
Thomas Wouters89f507f2006-12-13 04:49:30 +0000152 raise
Andrew M. Kuchling6fccc8a2003-12-23 16:33:28 +0000153 if tail == curdir: # xxx/newdir/. exists if xxx/newdir exists
154 return
Terry Reedy5a22b652010-12-02 07:05:56 +0000155 try:
156 mkdir(name, mode)
157 except OSError as e:
Terry Reedy5a22b652010-12-02 07:05:56 +0000158 if not (e.errno == errno.EEXIST and exist_ok and path.isdir(name) and
159 st.S_IMODE(lstat(name).st_mode) == _get_masked_mode(mode)):
160 raise
Guido van Rossum4def7de1998-07-24 20:48:03 +0000161
162def removedirs(name):
Fred Drakecadb9eb2002-07-02 21:28:04 +0000163 """removedirs(path)
Guido van Rossum4def7de1998-07-24 20:48:03 +0000164
Fredrik Lundh96c1c7a2005-11-12 15:55:04 +0000165 Super-rmdir; remove a leaf directory and all empty intermediate
Guido van Rossum4def7de1998-07-24 20:48:03 +0000166 ones. Works like rmdir except that, if the leaf directory is
167 successfully removed, directories corresponding to rightmost path
Tim Petersc4e09402003-04-25 07:11:48 +0000168 segments will be pruned away until either the whole path is
Guido van Rossum4def7de1998-07-24 20:48:03 +0000169 consumed or an error occurs. Errors during this latter phase are
170 ignored -- they generally mean that a directory was not empty.
171
172 """
173 rmdir(name)
174 head, tail = path.split(name)
Fred Drake9f2550f2000-07-25 15:16:40 +0000175 if not tail:
176 head, tail = path.split(head)
Guido van Rossum4def7de1998-07-24 20:48:03 +0000177 while head and tail:
178 try:
179 rmdir(head)
180 except error:
181 break
182 head, tail = path.split(head)
183
184def renames(old, new):
Fred Drakecadb9eb2002-07-02 21:28:04 +0000185 """renames(old, new)
Guido van Rossum4def7de1998-07-24 20:48:03 +0000186
187 Super-rename; create directories as necessary and delete any left
188 empty. Works like rename, except creation of any intermediate
189 directories needed to make the new pathname good is attempted
190 first. After the rename, directories corresponding to rightmost
191 path segments of the old name will be pruned way until either the
192 whole path is consumed or a nonempty directory is found.
193
194 Note: this function can fail with the new directory structure made
195 if you lack permissions needed to unlink the leaf directory or
196 file.
197
198 """
199 head, tail = path.split(new)
200 if head and tail and not path.exists(head):
201 makedirs(head)
202 rename(old, new)
203 head, tail = path.split(old)
204 if head and tail:
205 try:
206 removedirs(head)
207 except error:
208 pass
209
Skip Montanaro269b83b2001-02-06 01:07:02 +0000210__all__.extend(["makedirs", "removedirs", "renames"])
211
Guido van Rossumd8faa362007-04-27 19:54:29 +0000212def walk(top, topdown=True, onerror=None, followlinks=False):
Tim Petersc4e09402003-04-25 07:11:48 +0000213 """Directory tree generator.
214
215 For each directory in the directory tree rooted at top (including top
216 itself, but excluding '.' and '..'), yields a 3-tuple
217
218 dirpath, dirnames, filenames
219
220 dirpath is a string, the path to the directory. dirnames is a list of
221 the names of the subdirectories in dirpath (excluding '.' and '..').
222 filenames is a list of the names of the non-directory files in dirpath.
223 Note that the names in the lists are just names, with no path components.
224 To get a full path (which begins with top) to a file or directory in
225 dirpath, do os.path.join(dirpath, name).
226
227 If optional arg 'topdown' is true or not specified, the triple for a
228 directory is generated before the triples for any of its subdirectories
229 (directories are generated top down). If topdown is false, the triple
230 for a directory is generated after the triples for all of its
231 subdirectories (directories are generated bottom up).
232
233 When topdown is true, the caller can modify the dirnames list in-place
234 (e.g., via del or slice assignment), and walk will only recurse into the
235 subdirectories whose names remain in dirnames; this can be used to prune
236 the search, or to impose a specific order of visiting. Modifying
237 dirnames when topdown is false is ineffective, since the directories in
238 dirnames have already been generated by the time dirnames itself is
239 generated.
240
Guido van Rossumbf1bef82003-05-13 18:01:19 +0000241 By default errors from the os.listdir() call are ignored. If
242 optional arg 'onerror' is specified, it should be a function; it
243 will be called with one argument, an os.error instance. It can
244 report the error to continue with the walk, or raise the exception
245 to abort the walk. Note that the filename is available as the
246 filename attribute of the exception object.
247
Guido van Rossumd8faa362007-04-27 19:54:29 +0000248 By default, os.walk does not follow symbolic links to subdirectories on
249 systems that support them. In order to get this functionality, set the
250 optional argument 'followlinks' to true.
251
Tim Petersc4e09402003-04-25 07:11:48 +0000252 Caution: if you pass a relative pathname for top, don't change the
253 current working directory between resumptions of walk. walk never
254 changes the current directory, and assumes that the client doesn't
255 either.
256
257 Example:
258
Christian Heimes5d8da202008-05-06 13:58:24 +0000259 import os
Tim Petersc4e09402003-04-25 07:11:48 +0000260 from os.path import join, getsize
Christian Heimes5d8da202008-05-06 13:58:24 +0000261 for root, dirs, files in os.walk('python/Lib/email'):
Neal Norwitz752abd02008-05-13 04:55:24 +0000262 print(root, "consumes", end="")
263 print(sum([getsize(join(root, name)) for name in files]), end="")
264 print("bytes in", len(files), "non-directory files")
Tim Petersc4e09402003-04-25 07:11:48 +0000265 if 'CVS' in dirs:
266 dirs.remove('CVS') # don't visit CVS directories
267 """
268
Benjamin Petersonf6489f92009-11-25 17:46:26 +0000269 islink, join, isdir = path.islink, path.join, path.isdir
Tim Petersc4e09402003-04-25 07:11:48 +0000270
271 # We may not have read permission for top, in which case we can't
Alexandre Vassalotti4e6531e2008-05-09 20:00:17 +0000272 # get a list of the files the directory contains. os.walk
Tim Petersc4e09402003-04-25 07:11:48 +0000273 # always suppressed the exception then, rather than blow up for a
274 # minor reason when (say) a thousand readable directories are still
275 # left to visit. That logic is copied here.
276 try:
277 # Note that listdir and error are globals in this module due
278 # to earlier import-*.
279 names = listdir(top)
Guido van Rossumb940e112007-01-10 16:19:56 +0000280 except error as err:
Guido van Rossumbf1bef82003-05-13 18:01:19 +0000281 if onerror is not None:
282 onerror(err)
Tim Petersc4e09402003-04-25 07:11:48 +0000283 return
284
285 dirs, nondirs = [], []
286 for name in names:
287 if isdir(join(top, name)):
288 dirs.append(name)
289 else:
290 nondirs.append(name)
291
292 if topdown:
293 yield top, dirs, nondirs
294 for name in dirs:
Benjamin Petersonf6489f92009-11-25 17:46:26 +0000295 new_path = join(top, name)
296 if followlinks or not islink(new_path):
Benjamin Peterson569d0872012-05-10 16:17:35 -0500297 yield from walk(new_path, topdown, onerror, followlinks)
Tim Petersc4e09402003-04-25 07:11:48 +0000298 if not topdown:
299 yield top, dirs, nondirs
300
301__all__.append("walk")
302
Charles-François Natali7372b062012-02-05 15:15:38 +0100303if _exists("openat"):
304
305 def fwalk(top, topdown=True, onerror=None, followlinks=False):
306 """Directory tree generator.
307
308 This behaves exactly like walk(), except that it yields a 4-tuple
309
310 dirpath, dirnames, filenames, dirfd
311
312 `dirpath`, `dirnames` and `filenames` are identical to walk() output,
313 and `dirfd` is a file descriptor referring to the directory `dirpath`.
314
315 The advantage of walkfd() over walk() is that it's safe against symlink
316 races (when followlinks is False).
317
318 Caution:
319 Since fwalk() yields file descriptors, those are only valid until the
320 next iteration step, so you should dup() them if you want to keep them
321 for a longer period.
322
323 Example:
324
325 import os
326 for root, dirs, files, rootfd in os.fwalk('python/Lib/email'):
327 print(root, "consumes", end="")
328 print(sum([os.fstatat(rootfd, name).st_size for name in files]),
329 end="")
330 print("bytes in", len(files), "non-directory files")
331 if 'CVS' in dirs:
332 dirs.remove('CVS') # don't visit CVS directories
333 """
334 # Note: To guard against symlink races, we use the standard
335 # lstat()/open()/fstat() trick.
336 orig_st = lstat(top)
337 topfd = open(top, O_RDONLY)
338 try:
339 if (followlinks or (st.S_ISDIR(orig_st.st_mode) and
Charles-François Natali84c0ca02012-04-22 15:55:43 +0200340 path.samestat(orig_st, fstat(topfd)))):
Benjamin Peterson569d0872012-05-10 16:17:35 -0500341 yield from _fwalk(topfd, top, topdown, onerror, followlinks)
Charles-François Natali7372b062012-02-05 15:15:38 +0100342 finally:
343 close(topfd)
344
345 def _fwalk(topfd, toppath, topdown, onerror, followlinks):
346 # Note: This uses O(depth of the directory tree) file descriptors: if
347 # necessary, it can be adapted to only require O(1) FDs, see issue
348 # #13734.
349
350 # whether to follow symlinks
351 flag = 0 if followlinks else AT_SYMLINK_NOFOLLOW
352
Charles-François Natali77940902012-02-06 19:54:48 +0100353 names = flistdir(topfd)
Charles-François Natali7372b062012-02-05 15:15:38 +0100354 dirs, nondirs = [], []
355 for name in names:
Hynek Schlawack66bfcc12012-05-15 16:32:21 +0200356 try:
357 # Here, we don't use AT_SYMLINK_NOFOLLOW to be consistent with
358 # walk() which reports symlinks to directories as directories.
359 # We do however check for symlinks before recursing into
360 # a subdirectory.
361 if st.S_ISDIR(fstatat(topfd, name).st_mode):
362 dirs.append(name)
363 else:
364 nondirs.append(name)
365 except FileNotFoundError:
366 try:
367 # Add dangling symlinks, ignore disappeared files
368 if st.S_ISLNK(fstatat(topfd, name, AT_SYMLINK_NOFOLLOW)
369 .st_mode):
370 nondirs.append(name)
371 except FileNotFoundError:
372 continue
Charles-François Natali7372b062012-02-05 15:15:38 +0100373
374 if topdown:
375 yield toppath, dirs, nondirs, topfd
376
377 for name in dirs:
378 try:
379 orig_st = fstatat(topfd, name, flag)
380 dirfd = openat(topfd, name, O_RDONLY)
381 except error as err:
382 if onerror is not None:
383 onerror(err)
384 return
385 try:
Charles-François Natali84c0ca02012-04-22 15:55:43 +0200386 if followlinks or path.samestat(orig_st, fstat(dirfd)):
Charles-François Natali7372b062012-02-05 15:15:38 +0100387 dirpath = path.join(toppath, name)
Benjamin Peterson569d0872012-05-10 16:17:35 -0500388 yield from _fwalk(dirfd, dirpath, topdown, onerror, followlinks)
Charles-François Natali7372b062012-02-05 15:15:38 +0100389 finally:
390 close(dirfd)
391
392 if not topdown:
393 yield toppath, dirs, nondirs, topfd
394
395 __all__.append("fwalk")
396
Guido van Rossuma28dab51997-08-29 22:36:47 +0000397# Make sure os.environ exists, at least
398try:
Guido van Rossum61de0ac1997-12-05 21:24:30 +0000399 environ
Guido van Rossuma28dab51997-08-29 22:36:47 +0000400except NameError:
Guido van Rossum61de0ac1997-12-05 21:24:30 +0000401 environ = {}
Guido van Rossuma28dab51997-08-29 22:36:47 +0000402
Guido van Rossume65cce51993-11-08 15:05:21 +0000403def execl(file, *args):
Guido van Rossum7da3cc52000-04-25 10:53:22 +0000404 """execl(file, *args)
405
406 Execute the executable file with argument list args, replacing the
407 current process. """
Guido van Rossum61de0ac1997-12-05 21:24:30 +0000408 execv(file, args)
Guido van Rossume65cce51993-11-08 15:05:21 +0000409
410def execle(file, *args):
Guido van Rossum7da3cc52000-04-25 10:53:22 +0000411 """execle(file, *args, env)
412
413 Execute the executable file with argument list args and
414 environment env, replacing the current process. """
Guido van Rossum61de0ac1997-12-05 21:24:30 +0000415 env = args[-1]
416 execve(file, args[:-1], env)
Guido van Rossume65cce51993-11-08 15:05:21 +0000417
418def execlp(file, *args):
Guido van Rossum7da3cc52000-04-25 10:53:22 +0000419 """execlp(file, *args)
420
421 Execute the executable file (which is searched for along $PATH)
422 with argument list args, replacing the current process. """
Guido van Rossum61de0ac1997-12-05 21:24:30 +0000423 execvp(file, args)
Guido van Rossume65cce51993-11-08 15:05:21 +0000424
Guido van Rossum030afb11995-03-14 17:27:18 +0000425def execlpe(file, *args):
Guido van Rossum7da3cc52000-04-25 10:53:22 +0000426 """execlpe(file, *args, env)
427
428 Execute the executable file (which is searched for along $PATH)
429 with argument list args and environment env, replacing the current
Tim Peters2344fae2001-01-15 00:50:52 +0000430 process. """
Guido van Rossum61de0ac1997-12-05 21:24:30 +0000431 env = args[-1]
432 execvpe(file, args[:-1], env)
Guido van Rossum030afb11995-03-14 17:27:18 +0000433
Guido van Rossume65cce51993-11-08 15:05:21 +0000434def execvp(file, args):
Matthias Klosea09c54f2010-01-31 16:48:44 +0000435 """execvp(file, args)
Guido van Rossum7da3cc52000-04-25 10:53:22 +0000436
437 Execute the executable file (which is searched for along $PATH)
438 with argument list args, replacing the current process.
Thomas Wouters7e474022000-07-16 12:04:32 +0000439 args may be a list or tuple of strings. """
Guido van Rossum61de0ac1997-12-05 21:24:30 +0000440 _execvpe(file, args)
Guido van Rossum030afb11995-03-14 17:27:18 +0000441
442def execvpe(file, args, env):
Guido van Rossum683c0fe2002-09-03 16:36:17 +0000443 """execvpe(file, args, env)
Guido van Rossum7da3cc52000-04-25 10:53:22 +0000444
445 Execute the executable file (which is searched for along $PATH)
446 with argument list args and environment env , replacing the
447 current process.
Tim Peters2344fae2001-01-15 00:50:52 +0000448 args may be a list or tuple of strings. """
Guido van Rossum61de0ac1997-12-05 21:24:30 +0000449 _execvpe(file, args, env)
Guido van Rossum030afb11995-03-14 17:27:18 +0000450
Skip Montanaro269b83b2001-02-06 01:07:02 +0000451__all__.extend(["execl","execle","execlp","execlpe","execvp","execvpe"])
452
Guido van Rossum5a2ca931999-11-02 13:27:32 +0000453def _execvpe(file, args, env=None):
454 if env is not None:
Gregory P. Smithb6e8c7e2010-02-27 07:22:22 +0000455 exec_func = execve
Guido van Rossum61de0ac1997-12-05 21:24:30 +0000456 argrest = (args, env)
457 else:
Gregory P. Smithb6e8c7e2010-02-27 07:22:22 +0000458 exec_func = execv
Guido van Rossum61de0ac1997-12-05 21:24:30 +0000459 argrest = (args,)
460 env = environ
Guido van Rossumaed51d82002-08-05 16:13:24 +0000461
Guido van Rossum61de0ac1997-12-05 21:24:30 +0000462 head, tail = path.split(file)
463 if head:
Gregory P. Smithb6e8c7e2010-02-27 07:22:22 +0000464 exec_func(file, *argrest)
Guido van Rossum61de0ac1997-12-05 21:24:30 +0000465 return
Guido van Rossume7ba4952007-06-06 23:52:48 +0000466 last_exc = saved_exc = None
Guido van Rossum683c0fe2002-09-03 16:36:17 +0000467 saved_tb = None
Victor Stinnerb745a742010-05-18 17:17:23 +0000468 path_list = get_exec_path(env)
469 if name != 'nt':
470 file = fsencode(file)
471 path_list = map(fsencode, path_list)
472 for dir in path_list:
Guido van Rossum61de0ac1997-12-05 21:24:30 +0000473 fullname = path.join(dir, file)
474 try:
Gregory P. Smithb6e8c7e2010-02-27 07:22:22 +0000475 exec_func(fullname, *argrest)
Guido van Rossumb940e112007-01-10 16:19:56 +0000476 except error as e:
Guido van Rossume7ba4952007-06-06 23:52:48 +0000477 last_exc = e
Guido van Rossum683c0fe2002-09-03 16:36:17 +0000478 tb = sys.exc_info()[2]
Christian Heimes45f9af32007-11-27 21:50:00 +0000479 if (e.errno != errno.ENOENT and e.errno != errno.ENOTDIR
Guido van Rossum683c0fe2002-09-03 16:36:17 +0000480 and saved_exc is None):
481 saved_exc = e
482 saved_tb = tb
483 if saved_exc:
Benjamin Peterson4b068192009-02-20 03:19:25 +0000484 raise saved_exc.with_traceback(saved_tb)
485 raise last_exc.with_traceback(tb)
Guido van Rossumd74fb6b2001-03-02 06:43:49 +0000486
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000487
Gregory P. Smithb6e8c7e2010-02-27 07:22:22 +0000488def get_exec_path(env=None):
489 """Returns the sequence of directories that will be searched for the
490 named executable (similar to a shell) when launching a process.
491
492 *env* must be an environment variable dict or None. If *env* is None,
493 os.environ will be used.
494 """
Victor Stinner273b7662010-11-06 12:59:33 +0000495 # Use a local import instead of a global import to limit the number of
496 # modules loaded at startup: the os module is always loaded at startup by
497 # Python. It may also avoid a bootstrap issue.
Victor Stinner6f35eda2010-10-29 00:38:58 +0000498 import warnings
499
Gregory P. Smithb6e8c7e2010-02-27 07:22:22 +0000500 if env is None:
501 env = environ
Victor Stinnerb745a742010-05-18 17:17:23 +0000502
Victor Stinnerbb4f2182010-11-07 15:43:39 +0000503 # {b'PATH': ...}.get('PATH') and {'PATH': ...}.get(b'PATH') emit a
504 # BytesWarning when using python -b or python -bb: ignore the warning
Victor Stinner273b7662010-11-06 12:59:33 +0000505 with warnings.catch_warnings():
506 warnings.simplefilter("ignore", BytesWarning)
Victor Stinnerb745a742010-05-18 17:17:23 +0000507
Victor Stinnerb745a742010-05-18 17:17:23 +0000508 try:
Victor Stinner273b7662010-11-06 12:59:33 +0000509 path_list = env.get('PATH')
510 except TypeError:
511 path_list = None
Victor Stinnerb745a742010-05-18 17:17:23 +0000512
Victor Stinner273b7662010-11-06 12:59:33 +0000513 if supports_bytes_environ:
514 try:
515 path_listb = env[b'PATH']
516 except (KeyError, TypeError):
517 pass
518 else:
519 if path_list is not None:
520 raise ValueError(
521 "env cannot contain 'PATH' and b'PATH' keys")
522 path_list = path_listb
523
524 if path_list is not None and isinstance(path_list, bytes):
525 path_list = fsdecode(path_list)
Victor Stinnerb745a742010-05-18 17:17:23 +0000526
527 if path_list is None:
528 path_list = defpath
529 return path_list.split(pathsep)
Gregory P. Smithb6e8c7e2010-02-27 07:22:22 +0000530
531
Skip Montanaro289bc052007-08-17 02:30:27 +0000532# Change environ to automatically call putenv(), unsetenv if they exist.
Raymond Hettinger158c9c22011-02-22 00:41:50 +0000533from collections.abc import MutableMapping
Skip Montanaro289bc052007-08-17 02:30:27 +0000534
535class _Environ(MutableMapping):
Victor Stinner84ae1182010-05-06 22:05:07 +0000536 def __init__(self, data, encodekey, decodekey, encodevalue, decodevalue, putenv, unsetenv):
537 self.encodekey = encodekey
538 self.decodekey = decodekey
539 self.encodevalue = encodevalue
540 self.decodevalue = decodevalue
Skip Montanaro289bc052007-08-17 02:30:27 +0000541 self.putenv = putenv
542 self.unsetenv = unsetenv
Victor Stinner3d75d0c2010-09-10 22:18:16 +0000543 self._data = data
Ezio Melotti19e4acf2010-02-22 15:59:01 +0000544
Skip Montanaro289bc052007-08-17 02:30:27 +0000545 def __getitem__(self, key):
Victor Stinner3d75d0c2010-09-10 22:18:16 +0000546 value = self._data[self.encodekey(key)]
Victor Stinner84ae1182010-05-06 22:05:07 +0000547 return self.decodevalue(value)
Ezio Melotti19e4acf2010-02-22 15:59:01 +0000548
Skip Montanaro289bc052007-08-17 02:30:27 +0000549 def __setitem__(self, key, value):
Victor Stinner84ae1182010-05-06 22:05:07 +0000550 key = self.encodekey(key)
551 value = self.encodevalue(value)
Skip Montanaro289bc052007-08-17 02:30:27 +0000552 self.putenv(key, value)
Victor Stinner3d75d0c2010-09-10 22:18:16 +0000553 self._data[key] = value
Ezio Melotti19e4acf2010-02-22 15:59:01 +0000554
Skip Montanaro289bc052007-08-17 02:30:27 +0000555 def __delitem__(self, key):
Victor Stinner84ae1182010-05-06 22:05:07 +0000556 key = self.encodekey(key)
Skip Montanaro289bc052007-08-17 02:30:27 +0000557 self.unsetenv(key)
Victor Stinner3d75d0c2010-09-10 22:18:16 +0000558 del self._data[key]
Ezio Melotti19e4acf2010-02-22 15:59:01 +0000559
Skip Montanaro289bc052007-08-17 02:30:27 +0000560 def __iter__(self):
Victor Stinner3d75d0c2010-09-10 22:18:16 +0000561 for key in self._data:
Victor Stinner84ae1182010-05-06 22:05:07 +0000562 yield self.decodekey(key)
Ezio Melotti19e4acf2010-02-22 15:59:01 +0000563
Skip Montanaro289bc052007-08-17 02:30:27 +0000564 def __len__(self):
Victor Stinner3d75d0c2010-09-10 22:18:16 +0000565 return len(self._data)
Ezio Melotti19e4acf2010-02-22 15:59:01 +0000566
567 def __repr__(self):
Victor Stinnerbed71172010-07-28 21:25:42 +0000568 return 'environ({{{}}})'.format(', '.join(
Victor Stinnerd73c1a32010-07-28 21:23:23 +0000569 ('{!r}: {!r}'.format(self.decodekey(key), self.decodevalue(value))
Victor Stinner3d75d0c2010-09-10 22:18:16 +0000570 for key, value in self._data.items())))
Ezio Melotti19e4acf2010-02-22 15:59:01 +0000571
Skip Montanaro289bc052007-08-17 02:30:27 +0000572 def copy(self):
573 return dict(self)
Ezio Melotti19e4acf2010-02-22 15:59:01 +0000574
Skip Montanaro289bc052007-08-17 02:30:27 +0000575 def setdefault(self, key, value):
576 if key not in self:
577 self[key] = value
578 return self[key]
579
580try:
581 _putenv = putenv
582except NameError:
583 _putenv = lambda key, value: None
Martin v. Löwisa90f4382001-03-07 09:05:45 +0000584else:
Skip Montanaro289bc052007-08-17 02:30:27 +0000585 __all__.append("putenv")
Guido van Rossum3b8e20d1996-07-24 00:55:17 +0000586
Skip Montanaro289bc052007-08-17 02:30:27 +0000587try:
588 _unsetenv = unsetenv
589except NameError:
590 _unsetenv = lambda key: _putenv(key, "")
591else:
592 __all__.append("unsetenv")
Guido van Rossumc524d952001-10-19 01:31:59 +0000593
Victor Stinner84ae1182010-05-06 22:05:07 +0000594def _createenviron():
595 if name in ('os2', 'nt'):
596 # Where Env Var Names Must Be UPPERCASE
597 def check_str(value):
598 if not isinstance(value, str):
599 raise TypeError("str expected, not %s" % type(value).__name__)
600 return value
601 encode = check_str
602 decode = str
603 def encodekey(key):
604 return encode(key).upper()
605 data = {}
606 for key, value in environ.items():
607 data[encodekey(key)] = value
608 else:
609 # Where Env Var Names Can Be Mixed Case
Victor Stinnerdf6d6cb2010-10-24 20:32:26 +0000610 encoding = sys.getfilesystemencoding()
Victor Stinner84ae1182010-05-06 22:05:07 +0000611 def encode(value):
612 if not isinstance(value, str):
613 raise TypeError("str expected, not %s" % type(value).__name__)
Victor Stinnerdf6d6cb2010-10-24 20:32:26 +0000614 return value.encode(encoding, 'surrogateescape')
Victor Stinner84ae1182010-05-06 22:05:07 +0000615 def decode(value):
Victor Stinnerdf6d6cb2010-10-24 20:32:26 +0000616 return value.decode(encoding, 'surrogateescape')
Victor Stinner84ae1182010-05-06 22:05:07 +0000617 encodekey = encode
618 data = environ
619 return _Environ(data,
620 encodekey, decode,
621 encode, decode,
622 _putenv, _unsetenv)
Guido van Rossumc524d952001-10-19 01:31:59 +0000623
Victor Stinner84ae1182010-05-06 22:05:07 +0000624# unicode environ
625environ = _createenviron()
626del _createenviron
Guido van Rossum61de0ac1997-12-05 21:24:30 +0000627
Guido van Rossum5a2ca931999-11-02 13:27:32 +0000628
Jack Jansenb11ce9b2003-01-08 16:33:40 +0000629def getenv(key, default=None):
Tim Peters2c60f7a2003-01-29 03:49:43 +0000630 """Get an environment variable, return None if it doesn't exist.
Victor Stinner84ae1182010-05-06 22:05:07 +0000631 The optional second argument can specify an alternate default.
632 key, default and the result are str."""
Tim Peters2c60f7a2003-01-29 03:49:43 +0000633 return environ.get(key, default)
Guido van Rossum5a2ca931999-11-02 13:27:32 +0000634
Victor Stinnerb745a742010-05-18 17:17:23 +0000635supports_bytes_environ = name not in ('os2', 'nt')
636__all__.extend(("getenv", "supports_bytes_environ"))
637
638if supports_bytes_environ:
Victor Stinner84ae1182010-05-06 22:05:07 +0000639 def _check_bytes(value):
640 if not isinstance(value, bytes):
641 raise TypeError("bytes expected, not %s" % type(value).__name__)
642 return value
643
644 # bytes environ
Victor Stinner3d75d0c2010-09-10 22:18:16 +0000645 environb = _Environ(environ._data,
Victor Stinner84ae1182010-05-06 22:05:07 +0000646 _check_bytes, bytes,
647 _check_bytes, bytes,
648 _putenv, _unsetenv)
649 del _check_bytes
650
651 def getenvb(key, default=None):
652 """Get an environment variable, return None if it doesn't exist.
653 The optional second argument can specify an alternate default.
654 key, default and the result are bytes."""
655 return environb.get(key, default)
Victor Stinner70120e22010-07-29 17:19:38 +0000656
657 __all__.extend(("environb", "getenvb"))
Victor Stinner84ae1182010-05-06 22:05:07 +0000658
Victor Stinnerdf6d6cb2010-10-24 20:32:26 +0000659def _fscodec():
660 encoding = sys.getfilesystemencoding()
661 if encoding == 'mbcs':
Victor Stinnere882aac2010-10-24 21:12:26 +0000662 errors = 'strict'
Victor Stinner313a1202010-06-11 23:56:51 +0000663 else:
Victor Stinnerdf6d6cb2010-10-24 20:32:26 +0000664 errors = 'surrogateescape'
Victor Stinnere8d51452010-08-19 01:05:19 +0000665
Victor Stinnerdf6d6cb2010-10-24 20:32:26 +0000666 def fsencode(filename):
667 """
668 Encode filename to the filesystem encoding with 'surrogateescape' error
669 handler, return bytes unchanged. On Windows, use 'strict' error handler if
670 the file system encoding is 'mbcs' (which is the default encoding).
671 """
672 if isinstance(filename, bytes):
673 return filename
674 elif isinstance(filename, str):
675 return filename.encode(encoding, errors)
Victor Stinnere8d51452010-08-19 01:05:19 +0000676 else:
Victor Stinnerdf6d6cb2010-10-24 20:32:26 +0000677 raise TypeError("expect bytes or str, not %s" % type(filename).__name__)
678
679 def fsdecode(filename):
680 """
681 Decode filename from the filesystem encoding with 'surrogateescape' error
682 handler, return str unchanged. On Windows, use 'strict' error handler if
683 the file system encoding is 'mbcs' (which is the default encoding).
684 """
685 if isinstance(filename, str):
686 return filename
687 elif isinstance(filename, bytes):
688 return filename.decode(encoding, errors)
689 else:
690 raise TypeError("expect bytes or str, not %s" % type(filename).__name__)
691
692 return fsencode, fsdecode
693
694fsencode, fsdecode = _fscodec()
695del _fscodec
Victor Stinner449c4662010-05-08 11:10:09 +0000696
Guido van Rossum5a2ca931999-11-02 13:27:32 +0000697# Supply spawn*() (probably only for Unix)
698if _exists("fork") and not _exists("spawnv") and _exists("execv"):
699
700 P_WAIT = 0
701 P_NOWAIT = P_NOWAITO = 1
702
703 # XXX Should we support P_DETACH? I suppose it could fork()**2
704 # and close the std I/O streams. Also, P_OVERLAY is the same
705 # as execv*()?
706
707 def _spawnvef(mode, file, args, env, func):
708 # Internal helper; func is the exec*() function to use
709 pid = fork()
710 if not pid:
711 # Child
712 try:
713 if env is None:
714 func(file, args)
715 else:
716 func(file, args, env)
717 except:
718 _exit(127)
719 else:
720 # Parent
721 if mode == P_NOWAIT:
722 return pid # Caller is responsible for waiting!
723 while 1:
724 wpid, sts = waitpid(pid, 0)
725 if WIFSTOPPED(sts):
726 continue
727 elif WIFSIGNALED(sts):
728 return -WTERMSIG(sts)
729 elif WIFEXITED(sts):
730 return WEXITSTATUS(sts)
731 else:
Collin Winter828f04a2007-08-31 00:04:24 +0000732 raise error("Not stopped, signaled or exited???")
Guido van Rossum5a2ca931999-11-02 13:27:32 +0000733
734 def spawnv(mode, file, args):
Guido van Rossume0cd2912000-04-21 18:35:36 +0000735 """spawnv(mode, file, args) -> integer
736
737Execute file with arguments from args in a subprocess.
738If mode == P_NOWAIT return the pid of the process.
739If mode == P_WAIT return the process's exit code if it exits normally;
Tim Peters2344fae2001-01-15 00:50:52 +0000740otherwise return -SIG, where SIG is the signal that killed it. """
Guido van Rossum5a2ca931999-11-02 13:27:32 +0000741 return _spawnvef(mode, file, args, None, execv)
742
743 def spawnve(mode, file, args, env):
Guido van Rossume0cd2912000-04-21 18:35:36 +0000744 """spawnve(mode, file, args, env) -> integer
745
746Execute file with arguments from args in a subprocess with the
747specified environment.
748If mode == P_NOWAIT return the pid of the process.
749If mode == P_WAIT return the process's exit code if it exits normally;
750otherwise return -SIG, where SIG is the signal that killed it. """
Guido van Rossum5a2ca931999-11-02 13:27:32 +0000751 return _spawnvef(mode, file, args, env, execve)
752
Guido van Rossumdd7cbbf1999-11-02 20:44:07 +0000753 # Note: spawnvp[e] is't currently supported on Windows
754
755 def spawnvp(mode, file, args):
Guido van Rossume0cd2912000-04-21 18:35:36 +0000756 """spawnvp(mode, file, args) -> integer
757
758Execute file (which is looked for along $PATH) with arguments from
759args in a subprocess.
760If mode == P_NOWAIT return the pid of the process.
761If mode == P_WAIT return the process's exit code if it exits normally;
762otherwise return -SIG, where SIG is the signal that killed it. """
Guido van Rossumdd7cbbf1999-11-02 20:44:07 +0000763 return _spawnvef(mode, file, args, None, execvp)
764
765 def spawnvpe(mode, file, args, env):
Guido van Rossume0cd2912000-04-21 18:35:36 +0000766 """spawnvpe(mode, file, args, env) -> integer
767
768Execute file (which is looked for along $PATH) with arguments from
769args in a subprocess with the supplied environment.
770If mode == P_NOWAIT return the pid of the process.
771If mode == P_WAIT return the process's exit code if it exits normally;
772otherwise return -SIG, where SIG is the signal that killed it. """
Guido van Rossumdd7cbbf1999-11-02 20:44:07 +0000773 return _spawnvef(mode, file, args, env, execvpe)
774
775if _exists("spawnv"):
776 # These aren't supplied by the basic Windows code
777 # but can be easily implemented in Python
Guido van Rossum5a2ca931999-11-02 13:27:32 +0000778
779 def spawnl(mode, file, *args):
Guido van Rossume0cd2912000-04-21 18:35:36 +0000780 """spawnl(mode, file, *args) -> integer
781
782Execute file with arguments from args in a subprocess.
783If mode == P_NOWAIT return the pid of the process.
784If mode == P_WAIT return the process's exit code if it exits normally;
785otherwise return -SIG, where SIG is the signal that killed it. """
Guido van Rossum5a2ca931999-11-02 13:27:32 +0000786 return spawnv(mode, file, args)
787
788 def spawnle(mode, file, *args):
Guido van Rossume0cd2912000-04-21 18:35:36 +0000789 """spawnle(mode, file, *args, env) -> integer
790
791Execute file with arguments from args in a subprocess with the
792supplied environment.
793If mode == P_NOWAIT return the pid of the process.
794If mode == P_WAIT return the process's exit code if it exits normally;
795otherwise return -SIG, where SIG is the signal that killed it. """
Guido van Rossum5a2ca931999-11-02 13:27:32 +0000796 env = args[-1]
797 return spawnve(mode, file, args[:-1], env)
798
Andrew MacIntyre69e18c92004-04-04 07:11:43 +0000799
800 __all__.extend(["spawnv", "spawnve", "spawnl", "spawnle",])
801
802
Guido van Rossumdd7cbbf1999-11-02 20:44:07 +0000803if _exists("spawnvp"):
804 # At the moment, Windows doesn't implement spawnvp[e],
805 # so it won't have spawnlp[e] either.
Guido van Rossum5a2ca931999-11-02 13:27:32 +0000806 def spawnlp(mode, file, *args):
Neal Norwitzb7f68102003-07-02 02:49:33 +0000807 """spawnlp(mode, file, *args) -> integer
Guido van Rossume0cd2912000-04-21 18:35:36 +0000808
809Execute file (which is looked for along $PATH) with arguments from
810args in a subprocess with the supplied environment.
811If mode == P_NOWAIT return the pid of the process.
812If mode == P_WAIT return the process's exit code if it exits normally;
813otherwise return -SIG, where SIG is the signal that killed it. """
Guido van Rossum5a2ca931999-11-02 13:27:32 +0000814 return spawnvp(mode, file, args)
815
816 def spawnlpe(mode, file, *args):
Guido van Rossume0cd2912000-04-21 18:35:36 +0000817 """spawnlpe(mode, file, *args, env) -> integer
818
819Execute file (which is looked for along $PATH) with arguments from
820args in a subprocess with the supplied environment.
821If mode == P_NOWAIT return the pid of the process.
822If mode == P_WAIT return the process's exit code if it exits normally;
823otherwise return -SIG, where SIG is the signal that killed it. """
Guido van Rossum5a2ca931999-11-02 13:27:32 +0000824 env = args[-1]
825 return spawnvpe(mode, file, args[:-1], env)
Guido van Rossume0cd2912000-04-21 18:35:36 +0000826
827
Andrew MacIntyre69e18c92004-04-04 07:11:43 +0000828 __all__.extend(["spawnvp", "spawnvpe", "spawnlp", "spawnlpe",])
Skip Montanaro269b83b2001-02-06 01:07:02 +0000829
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000830import copyreg as _copyreg
Michael W. Hudson0e025302002-03-06 17:11:18 +0000831
832def _make_stat_result(tup, dict):
833 return stat_result(tup, dict)
834
835def _pickle_stat_result(sr):
836 (type, args) = sr.__reduce__()
837 return (_make_stat_result, args)
838
Michael W. Hudsonce00b732002-03-15 10:18:58 +0000839try:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000840 _copyreg.pickle(stat_result, _pickle_stat_result, _make_stat_result)
Michael W. Hudsonce00b732002-03-15 10:18:58 +0000841except NameError: # stat_result may not exist
842 pass
Michael W. Hudson0e025302002-03-06 17:11:18 +0000843
844def _make_statvfs_result(tup, dict):
845 return statvfs_result(tup, dict)
846
847def _pickle_statvfs_result(sr):
848 (type, args) = sr.__reduce__()
849 return (_make_statvfs_result, args)
850
Michael W. Hudsonce00b732002-03-15 10:18:58 +0000851try:
Alexandre Vassalottif7fa63d2008-05-11 08:55:36 +0000852 _copyreg.pickle(statvfs_result, _pickle_statvfs_result,
Michael W. Hudsonce00b732002-03-15 10:18:58 +0000853 _make_statvfs_result)
Michael W. Hudsone5363b72002-03-15 10:21:59 +0000854except NameError: # statvfs_result may not exist
Michael W. Hudsonce00b732002-03-15 10:18:58 +0000855 pass
Martin v. Löwisdc3883f2004-08-29 15:46:35 +0000856
Guido van Rossumc2f93dc2007-05-24 00:50:02 +0000857# Supply os.popen()
Antoine Pitrou877766d2011-03-19 17:00:37 +0100858def popen(cmd, mode="r", buffering=-1):
Guido van Rossum3172c5d2007-10-16 18:12:55 +0000859 if not isinstance(cmd, str):
Guido van Rossumc2f93dc2007-05-24 00:50:02 +0000860 raise TypeError("invalid cmd type (%s, expected string)" % type(cmd))
861 if mode not in ("r", "w"):
862 raise ValueError("invalid mode %r" % mode)
Antoine Pitrou877766d2011-03-19 17:00:37 +0100863 if buffering == 0 or buffering == None:
864 raise ValueError("popen() does not support unbuffered streams")
Guido van Rossumc2f93dc2007-05-24 00:50:02 +0000865 import subprocess, io
866 if mode == "r":
867 proc = subprocess.Popen(cmd,
868 shell=True,
869 stdout=subprocess.PIPE,
870 bufsize=buffering)
871 return _wrap_close(io.TextIOWrapper(proc.stdout), proc)
872 else:
873 proc = subprocess.Popen(cmd,
874 shell=True,
875 stdin=subprocess.PIPE,
876 bufsize=buffering)
877 return _wrap_close(io.TextIOWrapper(proc.stdin), proc)
878
879# Helper for popen() -- a proxy for a file whose close waits for the process
880class _wrap_close:
881 def __init__(self, stream, proc):
882 self._stream = stream
883 self._proc = proc
884 def close(self):
885 self._stream.close()
Amaury Forgeot d'Arc97e5f282009-07-11 09:35:13 +0000886 returncode = self._proc.wait()
887 if returncode == 0:
888 return None
889 if name == 'nt':
890 return returncode
891 else:
892 return returncode << 8 # Shift left to match old behavior
Antoine Pitrouac625352009-12-09 00:01:27 +0000893 def __enter__(self):
894 return self
895 def __exit__(self, *args):
896 self.close()
Guido van Rossumc2f93dc2007-05-24 00:50:02 +0000897 def __getattr__(self, name):
898 return getattr(self._stream, name)
Thomas Heller476157b2007-09-04 11:27:47 +0000899 def __iter__(self):
900 return iter(self._stream)
Guido van Rossumc2f93dc2007-05-24 00:50:02 +0000901
Amaury Forgeot d'Arcbdbddf82008-08-01 00:06:49 +0000902# Supply os.fdopen()
903def fdopen(fd, *args, **kwargs):
Guido van Rossumc2f93dc2007-05-24 00:50:02 +0000904 if not isinstance(fd, int):
905 raise TypeError("invalid fd type (%s, expected integer)" % type(fd))
906 import io
Amaury Forgeot d'Arcbdbddf82008-08-01 00:06:49 +0000907 return io.open(fd, *args, **kwargs)