Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(11)

Delta Between Two Patch Sets: Lib/os.py

Issue 16353: add function to os module for getting path to default shell
Left Patch Set: Created 7 years, 4 months ago
Right Patch Set: Created 3 years, 10 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « no previous file | Modules/posixmodule.c » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 r"""OS routines for Mac, NT, or Posix depending on what system we're on. 1 r"""OS routines for NT or Posix depending on what system we're on.
2 2
3 This exports: 3 This exports:
4 - all functions from posix, nt or ce, e.g. unlink, stat, etc. 4 - all functions from posix, nt or ce, e.g. unlink, stat, etc.
5 - os.path is either posixpath or ntpath 5 - os.path is either posixpath or ntpath
6 - os.name is either 'posix', 'nt' or 'ce'. 6 - os.name is either 'posix', 'nt' or 'ce'.
7 - os.curdir is a string representing the current directory ('.' or ':') 7 - os.curdir is a string representing the current directory ('.' or ':')
8 - os.pardir is a string representing the parent 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 '\\') 9 - os.sep is the (or a most common) pathname separator ('/' or ':' or '\\')
10 - os.extsep is the extension separator (always '.') 10 - os.extsep is the extension separator (always '.')
11 - os.altsep is the alternate pathname separator (None or '/') 11 - os.altsep is the alternate pathname separator (None or '/')
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
53 from posix import _exit 53 from posix import _exit
54 __all__.append('_exit') 54 __all__.append('_exit')
55 except ImportError: 55 except ImportError:
56 pass 56 pass
57 import posixpath as path 57 import posixpath as path
58 58
59 try: 59 try:
60 from posix import _have_functions 60 from posix import _have_functions
61 except ImportError: 61 except ImportError:
62 pass 62 pass
63
64 import posix
65 __all__.extend(_get_exports_list(posix))
66 del posix
63 67
64 elif 'nt' in _names: 68 elif 'nt' in _names:
65 name = 'nt' 69 name = 'nt'
66 linesep = '\r\n' 70 linesep = '\r\n'
67 from nt import * 71 from nt import *
68 try: 72 try:
69 from nt import _exit 73 from nt import _exit
70 __all__.append('_exit') 74 __all__.append('_exit')
71 except ImportError: 75 except ImportError:
72 pass 76 pass
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 _add("HAVE_UTIMENSAT", "utime") 196 _add("HAVE_UTIMENSAT", "utime")
193 _add("MS_WINDOWS", "stat") 197 _add("MS_WINDOWS", "stat")
194 supports_follow_symlinks = _set 198 supports_follow_symlinks = _set
195 199
196 del _set 200 del _set
197 del _have_functions 201 del _have_functions
198 del _globals 202 del _globals
199 del _add 203 del _add
200 204
201 205
206 if sys.platform == 'win32':
207 default_shell = 'cmd.exe'
Michael.Felt 2016/07/29 14:40:15 Has cmd.exe moved around too much to not specify a
eryksun 2016/07/29 15:03:28 It should be environ['ComSpec'], for which the def
208 elif _exists('is_android') and is_android:
209 default_shell = '/system/bin/sh'
210 else:
211 default_shell = '/bin/sh'
212
202 # Python uses fixed values for the SEEK_ constants; they are mapped 213 # Python uses fixed values for the SEEK_ constants; they are mapped
203 # to native constants if necessary in posixmodule.c 214 # to native constants if necessary in posixmodule.c
204 # Other possible SEEK values are directly imported from posixmodule.c 215 # Other possible SEEK values are directly imported from posixmodule.c
205 SEEK_SET = 0 216 SEEK_SET = 0
206 SEEK_CUR = 1 217 SEEK_CUR = 1
207 SEEK_END = 2 218 SEEK_END = 2
208 219
209
210 def _get_masked_mode(mode):
211 mask = umask(0)
212 umask(mask)
213 return mode & ~mask
214
215 # Super directory utilities. 220 # Super directory utilities.
216 # (Inspired by Eric Raymond; the doc strings are mostly his) 221 # (Inspired by Eric Raymond; the doc strings are mostly his)
217 222
218 def makedirs(name, mode=0o777, exist_ok=False): 223 def makedirs(name, mode=0o777, exist_ok=False):
219 """makedirs(path [, mode=0o777][, exist_ok=False]) 224 """makedirs(name [, mode=0o777][, exist_ok=False])
220 225
221 Super-mkdir; create a leaf directory and all intermediate ones. 226 Super-mkdir; create a leaf directory and all intermediate ones. Works like
222 Works like mkdir, except that any intermediate path segment (not 227 mkdir, except that any intermediate path segment (not just the rightmost)
223 just the rightmost) will be created if it does not exist. If the 228 will be created if it does not exist. If the target directory already
224 target directory with the same mode as we specified already exists, 229 exists, raise an OSError if exist_ok is False. Otherwise no exception is
225 raises an OSError if exist_ok is False, otherwise no exception is
226 raised. This is recursive. 230 raised. This is recursive.
227 231
228 """ 232 """
229 head, tail = path.split(name) 233 head, tail = path.split(name)
230 if not tail: 234 if not tail:
231 head, tail = path.split(head) 235 head, tail = path.split(head)
232 if head and tail and not path.exists(head): 236 if head and tail and not path.exists(head):
233 try: 237 try:
234 makedirs(head, mode, exist_ok) 238 makedirs(head, mode, exist_ok)
235 except OSError as e: 239 except FileExistsError:
236 # be happy if someone already created the path 240 # Defeats race condition when another thread created the path
237 if e.errno != errno.EEXIST: 241 pass
238 raise 242 cdir = curdir
239 if tail == curdir: # xxx/newdir/. exists if xxx/newdir exists 243 if isinstance(tail, bytes):
244 cdir = bytes(curdir, 'ASCII')
245 if tail == cdir: # xxx/newdir/. exists if xxx/newdir exists
240 return 246 return
241 try: 247 try:
242 mkdir(name, mode) 248 mkdir(name, mode)
243 except OSError as e: 249 except OSError:
244 dir_exists = path.isdir(name) 250 # Cannot rely on checking for EEXIST, since the operating system
245 expected_mode = _get_masked_mode(mode) 251 # could give priority to other errors like EACCES or EROFS
246 if dir_exists: 252 if not exist_ok or not path.isdir(name):
247 # S_ISGID is automatically copied by the OS from parent to child
248 # directories on mkdir. Don't consider it being set to be a mode
249 # mismatch as mkdir does not unset it when not specified in mode.
250 actual_mode = st.S_IMODE(lstat(name).st_mode) & ~st.S_ISGID
251 else:
252 actual_mode = -1
253 if not (e.errno == errno.EEXIST and exist_ok and dir_exists and
254 actual_mode == expected_mode):
255 if dir_exists and actual_mode != expected_mode:
256 e.strerror += ' (mode %o != expected mode %o)' % (
257 actual_mode, expected_mode)
258 raise 253 raise
259 254
260 def removedirs(name): 255 def removedirs(name):
261 """removedirs(path) 256 """removedirs(name)
262 257
263 Super-rmdir; remove a leaf directory and all empty intermediate 258 Super-rmdir; remove a leaf directory and all empty intermediate
264 ones. Works like rmdir except that, if the leaf directory is 259 ones. Works like rmdir except that, if the leaf directory is
265 successfully removed, directories corresponding to rightmost path 260 successfully removed, directories corresponding to rightmost path
266 segments will be pruned away until either the whole path is 261 segments will be pruned away until either the whole path is
267 consumed or an error occurs. Errors during this latter phase are 262 consumed or an error occurs. Errors during this latter phase are
268 ignored -- they generally mean that a directory was not empty. 263 ignored -- they generally mean that a directory was not empty.
269 264
270 """ 265 """
271 rmdir(name) 266 rmdir(name)
272 head, tail = path.split(name) 267 head, tail = path.split(name)
273 if not tail: 268 if not tail:
274 head, tail = path.split(head) 269 head, tail = path.split(head)
275 while head and tail: 270 while head and tail:
276 try: 271 try:
277 rmdir(head) 272 rmdir(head)
278 except error: 273 except OSError:
279 break 274 break
280 head, tail = path.split(head) 275 head, tail = path.split(head)
281 276
282 def renames(old, new): 277 def renames(old, new):
283 """renames(old, new) 278 """renames(old, new)
284 279
285 Super-rename; create directories as necessary and delete any left 280 Super-rename; create directories as necessary and delete any left
286 empty. Works like rename, except creation of any intermediate 281 empty. Works like rename, except creation of any intermediate
287 directories needed to make the new pathname good is attempted 282 directories needed to make the new pathname good is attempted
288 first. After the rename, directories corresponding to rightmost 283 first. After the rename, directories corresponding to rightmost
289 path segments of the old name will be pruned way until either the 284 path segments of the old name will be pruned until either the
290 whole path is consumed or a nonempty directory is found. 285 whole path is consumed or a nonempty directory is found.
291 286
292 Note: this function can fail with the new directory structure made 287 Note: this function can fail with the new directory structure made
293 if you lack permissions needed to unlink the leaf directory or 288 if you lack permissions needed to unlink the leaf directory or
294 file. 289 file.
295 290
296 """ 291 """
297 head, tail = path.split(new) 292 head, tail = path.split(new)
298 if head and tail and not path.exists(head): 293 if head and tail and not path.exists(head):
299 makedirs(head) 294 makedirs(head)
300 rename(old, new) 295 rename(old, new)
301 head, tail = path.split(old) 296 head, tail = path.split(old)
302 if head and tail: 297 if head and tail:
303 try: 298 try:
304 removedirs(head) 299 removedirs(head)
305 except error: 300 except OSError:
306 pass 301 pass
307 302
308 __all__.extend(["makedirs", "removedirs", "renames"]) 303 __all__.extend(["makedirs", "removedirs", "renames"])
309 304
310 def walk(top, topdown=True, onerror=None, followlinks=False): 305 def walk(top, topdown=True, onerror=None, followlinks=False):
311 """Directory tree generator. 306 """Directory tree generator.
312 307
313 For each directory in the directory tree rooted at top (including top 308 For each directory in the directory tree rooted at top (including top
314 itself, but excluding '.' and '..'), yields a 3-tuple 309 itself, but excluding '.' and '..'), yields a 3-tuple
315 310
316 dirpath, dirnames, filenames 311 dirpath, dirnames, filenames
317 312
318 dirpath is a string, the path to the directory. dirnames is a list of 313 dirpath is a string, the path to the directory. dirnames is a list of
319 the names of the subdirectories in dirpath (excluding '.' and '..'). 314 the names of the subdirectories in dirpath (excluding '.' and '..').
320 filenames is a list of the names of the non-directory files in dirpath. 315 filenames is a list of the names of the non-directory files in dirpath.
321 Note that the names in the lists are just names, with no path components. 316 Note that the names in the lists are just names, with no path components.
322 To get a full path (which begins with top) to a file or directory in 317 To get a full path (which begins with top) to a file or directory in
323 dirpath, do os.path.join(dirpath, name). 318 dirpath, do os.path.join(dirpath, name).
324 319
325 If optional arg 'topdown' is true or not specified, the triple for a 320 If optional arg 'topdown' is true or not specified, the triple for a
326 directory is generated before the triples for any of its subdirectories 321 directory is generated before the triples for any of its subdirectories
327 (directories are generated top down). If topdown is false, the triple 322 (directories are generated top down). If topdown is false, the triple
328 for a directory is generated after the triples for all of its 323 for a directory is generated after the triples for all of its
329 subdirectories (directories are generated bottom up). 324 subdirectories (directories are generated bottom up).
330 325
331 When topdown is true, the caller can modify the dirnames list in-place 326 When topdown is true, the caller can modify the dirnames list in-place
332 (e.g., via del or slice assignment), and walk will only recurse into the 327 (e.g., via del or slice assignment), and walk will only recurse into the
333 subdirectories whose names remain in dirnames; this can be used to prune 328 subdirectories whose names remain in dirnames; this can be used to prune the
334 the search, or to impose a specific order of visiting. Modifying 329 search, or to impose a specific order of visiting. Modifying dirnames when
335 dirnames when topdown is false is ineffective, since the directories in 330 topdown is false is ineffective, since the directories in dirnames have
336 dirnames have already been generated by the time dirnames itself is 331 already been generated by the time dirnames itself is generated. No matter
337 generated. 332 the value of topdown, the list of subdirectories is retrieved before the
338 333 tuples for the directory and its subdirectories are generated.
339 By default errors from the os.listdir() call are ignored. If 334
335 By default errors from the os.scandir() call are ignored. If
340 optional arg 'onerror' is specified, it should be a function; it 336 optional arg 'onerror' is specified, it should be a function; it
341 will be called with one argument, an os.error instance. It can 337 will be called with one argument, an OSError instance. It can
342 report the error to continue with the walk, or raise the exception 338 report the error to continue with the walk, or raise the exception
343 to abort the walk. Note that the filename is available as the 339 to abort the walk. Note that the filename is available as the
344 filename attribute of the exception object. 340 filename attribute of the exception object.
345 341
346 By default, os.walk does not follow symbolic links to subdirectories on 342 By default, os.walk does not follow symbolic links to subdirectories on
347 systems that support them. In order to get this functionality, set the 343 systems that support them. In order to get this functionality, set the
348 optional argument 'followlinks' to true. 344 optional argument 'followlinks' to true.
349 345
350 Caution: if you pass a relative pathname for top, don't change the 346 Caution: if you pass a relative pathname for top, don't change the
351 current working directory between resumptions of walk. walk never 347 current working directory between resumptions of walk. walk never
352 changes the current directory, and assumes that the client doesn't 348 changes the current directory, and assumes that the client doesn't
353 either. 349 either.
354 350
355 Example: 351 Example:
356 352
357 import os 353 import os
358 from os.path import join, getsize 354 from os.path import join, getsize
359 for root, dirs, files in os.walk('python/Lib/email'): 355 for root, dirs, files in os.walk('python/Lib/email'):
360 print(root, "consumes", end="") 356 print(root, "consumes", end="")
361 print(sum([getsize(join(root, name)) for name in files]), end="") 357 print(sum([getsize(join(root, name)) for name in files]), end="")
362 print("bytes in", len(files), "non-directory files") 358 print("bytes in", len(files), "non-directory files")
363 if 'CVS' in dirs: 359 if 'CVS' in dirs:
364 dirs.remove('CVS') # don't visit CVS directories 360 dirs.remove('CVS') # don't visit CVS directories
361
365 """ 362 """
366 363
367 islink, join, isdir = path.islink, path.join, path.isdir 364 dirs = []
365 nondirs = []
366 walk_dirs = []
368 367
369 # We may not have read permission for top, in which case we can't 368 # We may not have read permission for top, in which case we can't
370 # get a list of the files the directory contains. os.walk 369 # get a list of the files the directory contains. os.walk
371 # always suppressed the exception then, rather than blow up for a 370 # always suppressed the exception then, rather than blow up for a
372 # minor reason when (say) a thousand readable directories are still 371 # minor reason when (say) a thousand readable directories are still
373 # left to visit. That logic is copied here. 372 # left to visit. That logic is copied here.
374 try: 373 try:
375 # Note that listdir and error are globals in this module due 374 if name == 'nt' and isinstance(top, bytes):
376 # to earlier import-*. 375 scandir_it = _dummy_scandir(top)
377 names = listdir(top) 376 else:
378 except error as err: 377 # Note that scandir is global in this module due
378 # to earlier import-*.
379 scandir_it = scandir(top)
380 except OSError as error:
379 if onerror is not None: 381 if onerror is not None:
380 onerror(err) 382 onerror(error)
381 return 383 return
382 384
383 dirs, nondirs = [], [] 385 with scandir_it:
384 for name in names: 386 while True:
385 if isdir(join(top, name)): 387 try:
386 dirs.append(name) 388 try:
387 else: 389 entry = next(scandir_it)
388 nondirs.append(name) 390 except StopIteration:
389 391 break
392 except OSError as error:
393 if onerror is not None:
394 onerror(error)
395 return
396
397 try:
398 is_dir = entry.is_dir()
399 except OSError:
400 # If is_dir() raises an OSError, consider that the entry is not
401 # a directory, same behaviour than os.path.isdir().
402 is_dir = False
403
404 if is_dir:
405 dirs.append(entry.name)
406 else:
407 nondirs.append(entry.name)
408
409 if not topdown and is_dir:
410 # Bottom-up: recurse into sub-directory, but exclude symlinks to
411 # directories if followlinks is False
412 if followlinks:
413 walk_into = True
414 else:
415 try:
416 is_symlink = entry.is_symlink()
417 except OSError:
418 # If is_symlink() raises an OSError, consider that the
419 # entry is not a symbolic link, same behaviour than
420 # os.path.islink().
421 is_symlink = False
422 walk_into = not is_symlink
423
424 if walk_into:
425 walk_dirs.append(entry.path)
426
427 # Yield before recursion if going top down
390 if topdown: 428 if topdown:
391 yield top, dirs, nondirs 429 yield top, dirs, nondirs
392 for name in dirs: 430
393 new_path = join(top, name) 431 # Recurse into sub-directories
394 if followlinks or not islink(new_path): 432 islink, join = path.islink, path.join
433 for dirname in dirs:
434 new_path = join(top, dirname)
435 # Issue #23605: os.path.islink() is used instead of caching
436 # entry.is_symlink() result during the loop on os.scandir() because
437 # the caller can replace the directory entry during the "yield"
438 # above.
439 if followlinks or not islink(new_path):
440 yield from walk(new_path, topdown, onerror, followlinks)
441 else:
442 # Recurse into sub-directories
443 for new_path in walk_dirs:
395 yield from walk(new_path, topdown, onerror, followlinks) 444 yield from walk(new_path, topdown, onerror, followlinks)
396 if not topdown: 445 # Yield after recursion if going bottom up
397 yield top, dirs, nondirs 446 yield top, dirs, nondirs
447
448 class _DummyDirEntry:
449 """Dummy implementation of DirEntry
450
451 Only used internally by os.walk(bytes). Since os.walk() doesn't need the
452 follow_symlinks parameter: don't implement it, always follow symbolic
453 links.
454 """
455
456 def __init__(self, dir, name):
457 self.name = name
458 self.path = path.join(dir, name)
459 # Mimick FindFirstFile/FindNextFile: we should get file attributes
460 # while iterating on a directory
461 self._stat = None
462 self._lstat = None
463 try:
464 self.stat(follow_symlinks=False)
465 except OSError:
466 pass
467
468 def stat(self, *, follow_symlinks=True):
469 if follow_symlinks:
470 if self._stat is None:
471 self._stat = stat(self.path)
472 return self._stat
473 else:
474 if self._lstat is None:
475 self._lstat = stat(self.path, follow_symlinks=False)
476 return self._lstat
477
478 def is_dir(self):
479 if self._lstat is not None and not self.is_symlink():
480 # use the cache lstat
481 stat = self.stat(follow_symlinks=False)
482 return st.S_ISDIR(stat.st_mode)
483
484 stat = self.stat()
485 return st.S_ISDIR(stat.st_mode)
486
487 def is_symlink(self):
488 stat = self.stat(follow_symlinks=False)
489 return st.S_ISLNK(stat.st_mode)
490
491 class _dummy_scandir:
492 # listdir-based implementation for bytes patches on Windows
493 def __init__(self, dir):
494 self.dir = dir
495 self.it = iter(listdir(dir))
496
497 def __iter__(self):
498 return self
499
500 def __next__(self):
501 return _DummyDirEntry(self.dir, next(self.it))
502
503 def __enter__(self):
504 return self
505
506 def __exit__(self, *args):
507 self.it = iter(())
398 508
399 __all__.append("walk") 509 __all__.append("walk")
400 510
401 if {open, stat} <= supports_dir_fd and {listdir, stat} <= supports_fd: 511 if {open, stat} <= supports_dir_fd and {listdir, stat} <= supports_fd:
402 512
403 def fwalk(top=".", topdown=True, onerror=None, *, follow_symlinks=False, dir _fd=None): 513 def fwalk(top=".", topdown=True, onerror=None, *, follow_symlinks=False, dir _fd=None):
404 """Directory tree generator. 514 """Directory tree generator.
405 515
406 This behaves exactly like walk(), except that it yields a 4-tuple 516 This behaves exactly like walk(), except that it yields a 4-tuple
407 517
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
470 except FileNotFoundError: 580 except FileNotFoundError:
471 continue 581 continue
472 582
473 if topdown: 583 if topdown:
474 yield toppath, dirs, nondirs, topfd 584 yield toppath, dirs, nondirs, topfd
475 585
476 for name in dirs: 586 for name in dirs:
477 try: 587 try:
478 orig_st = stat(name, dir_fd=topfd, follow_symlinks=follow_symlin ks) 588 orig_st = stat(name, dir_fd=topfd, follow_symlinks=follow_symlin ks)
479 dirfd = open(name, O_RDONLY, dir_fd=topfd) 589 dirfd = open(name, O_RDONLY, dir_fd=topfd)
480 except error as err: 590 except OSError as err:
481 if onerror is not None: 591 if onerror is not None:
482 onerror(err) 592 onerror(err)
483 return 593 continue
484 try: 594 try:
485 if follow_symlinks or path.samestat(orig_st, stat(dirfd)): 595 if follow_symlinks or path.samestat(orig_st, stat(dirfd)):
486 dirpath = path.join(toppath, name) 596 dirpath = path.join(toppath, name)
487 yield from _fwalk(dirfd, dirpath, topdown, onerror, follow_s ymlinks) 597 yield from _fwalk(dirfd, dirpath, topdown, onerror, follow_s ymlinks)
488 finally: 598 finally:
489 close(dirfd) 599 close(dirfd)
490 600
491 if not topdown: 601 if not topdown:
492 yield toppath, dirs, nondirs, topfd 602 yield toppath, dirs, nondirs, topfd
493 603
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
565 last_exc = saved_exc = None 675 last_exc = saved_exc = None
566 saved_tb = None 676 saved_tb = None
567 path_list = get_exec_path(env) 677 path_list = get_exec_path(env)
568 if name != 'nt': 678 if name != 'nt':
569 file = fsencode(file) 679 file = fsencode(file)
570 path_list = map(fsencode, path_list) 680 path_list = map(fsencode, path_list)
571 for dir in path_list: 681 for dir in path_list:
572 fullname = path.join(dir, file) 682 fullname = path.join(dir, file)
573 try: 683 try:
574 exec_func(fullname, *argrest) 684 exec_func(fullname, *argrest)
575 except error as e: 685 except OSError as e:
576 last_exc = e 686 last_exc = e
577 tb = sys.exc_info()[2] 687 tb = sys.exc_info()[2]
578 if (e.errno != errno.ENOENT and e.errno != errno.ENOTDIR 688 if (e.errno != errno.ENOENT and e.errno != errno.ENOTDIR
579 and saved_exc is None): 689 and saved_exc is None):
580 saved_exc = e 690 saved_exc = e
581 saved_tb = tb 691 saved_tb = tb
582 if saved_exc: 692 if saved_exc:
583 raise saved_exc.with_traceback(saved_tb) 693 raise saved_exc.with_traceback(saved_tb)
584 raise last_exc.with_traceback(tb) 694 raise last_exc.with_traceback(tb)
585 695
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
622 732
623 if path_list is not None and isinstance(path_list, bytes): 733 if path_list is not None and isinstance(path_list, bytes):
624 path_list = fsdecode(path_list) 734 path_list = fsdecode(path_list)
625 735
626 if path_list is None: 736 if path_list is None:
627 path_list = defpath 737 path_list = defpath
628 return path_list.split(pathsep) 738 return path_list.split(pathsep)
629 739
630 740
631 # Change environ to automatically call putenv(), unsetenv if they exist. 741 # Change environ to automatically call putenv(), unsetenv if they exist.
632 from collections.abc import MutableMapping 742 from _collections_abc import MutableMapping
633 743
634 class _Environ(MutableMapping): 744 class _Environ(MutableMapping):
635 def __init__(self, data, encodekey, decodekey, encodevalue, decodevalue, put env, unsetenv): 745 def __init__(self, data, encodekey, decodekey, encodevalue, decodevalue, put env, unsetenv):
636 self.encodekey = encodekey 746 self.encodekey = encodekey
637 self.decodekey = decodekey 747 self.decodekey = decodekey
638 self.encodevalue = encodevalue 748 self.encodevalue = encodevalue
639 self.decodevalue = decodevalue 749 self.decodevalue = decodevalue
640 self.putenv = putenv 750 self.putenv = putenv
641 self.unsetenv = unsetenv 751 self.unsetenv = unsetenv
642 self._data = data 752 self._data = data
643 753
644 def __getitem__(self, key): 754 def __getitem__(self, key):
645 value = self._data[self.encodekey(key)] 755 try:
756 value = self._data[self.encodekey(key)]
757 except KeyError:
758 # raise KeyError with the original key value
759 raise KeyError(key) from None
646 return self.decodevalue(value) 760 return self.decodevalue(value)
647 761
648 def __setitem__(self, key, value): 762 def __setitem__(self, key, value):
649 key = self.encodekey(key) 763 key = self.encodekey(key)
650 value = self.encodevalue(value) 764 value = self.encodevalue(value)
651 self.putenv(key, value) 765 self.putenv(key, value)
652 self._data[key] = value 766 self._data[key] = value
653 767
654 def __delitem__(self, key): 768 def __delitem__(self, key):
655 key = self.encodekey(key) 769 encodedkey = self.encodekey(key)
656 self.unsetenv(key) 770 self.unsetenv(encodedkey)
657 del self._data[key] 771 try:
772 del self._data[encodedkey]
773 except KeyError:
774 # raise KeyError with the original key value
775 raise KeyError(key) from None
658 776
659 def __iter__(self): 777 def __iter__(self):
660 for key in self._data: 778 for key in self._data:
661 yield self.decodekey(key) 779 yield self.decodekey(key)
662 780
663 def __len__(self): 781 def __len__(self):
664 return len(self._data) 782 return len(self._data)
665 783
666 def __repr__(self): 784 def __repr__(self):
667 return 'environ({{{}}})'.format(', '.join( 785 return 'environ({{{}}})'.format(', '.join(
668 ('{!r}: {!r}'.format(self.decodekey(key), self.decodevalue(value)) 786 ('{!r}: {!r}'.format(self.decodekey(key), self.decodevalue(value))
669 for key, value in self._data.items()))) 787 for key, value in self._data.items())))
670 788
671 def copy(self): 789 def copy(self):
672 return dict(self) 790 return dict(self)
673 791
674 def setdefault(self, key, value): 792 def setdefault(self, key, value):
675 if key not in self: 793 if key not in self:
676 self[key] = value 794 self[key] = value
677 return self[key] 795 return self[key]
678 796
679 try: 797 try:
680 _putenv = putenv 798 _putenv = putenv
681 except NameError: 799 except NameError:
682 _putenv = lambda key, value: None 800 _putenv = lambda key, value: None
683 else: 801 else:
684 __all__.append("putenv") 802 if "putenv" not in __all__:
803 __all__.append("putenv")
685 804
686 try: 805 try:
687 _unsetenv = unsetenv 806 _unsetenv = unsetenv
688 except NameError: 807 except NameError:
689 _unsetenv = lambda key: _putenv(key, "") 808 _unsetenv = lambda key: _putenv(key, "")
690 else: 809 else:
691 __all__.append("unsetenv") 810 if "unsetenv" not in __all__:
811 __all__.append("unsetenv")
692 812
693 def _createenviron(): 813 def _createenviron():
694 if name == 'nt': 814 if name == 'nt':
695 # Where Env Var Names Must Be UPPERCASE 815 # Where Env Var Names Must Be UPPERCASE
696 def check_str(value): 816 def check_str(value):
697 if not isinstance(value, str): 817 if not isinstance(value, str):
698 raise TypeError("str expected, not %s" % type(value).__name__) 818 raise TypeError("str expected, not %s" % type(value).__name__)
699 return value 819 return value
700 encode = check_str 820 encode = check_str
701 decode = str 821 decode = str
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
823 return pid # Caller is responsible for waiting! 943 return pid # Caller is responsible for waiting!
824 while 1: 944 while 1:
825 wpid, sts = waitpid(pid, 0) 945 wpid, sts = waitpid(pid, 0)
826 if WIFSTOPPED(sts): 946 if WIFSTOPPED(sts):
827 continue 947 continue
828 elif WIFSIGNALED(sts): 948 elif WIFSIGNALED(sts):
829 return -WTERMSIG(sts) 949 return -WTERMSIG(sts)
830 elif WIFEXITED(sts): 950 elif WIFEXITED(sts):
831 return WEXITSTATUS(sts) 951 return WEXITSTATUS(sts)
832 else: 952 else:
833 raise error("Not stopped, signaled or exited???") 953 raise OSError("Not stopped, signaled or exited???")
834 954
835 def spawnv(mode, file, args): 955 def spawnv(mode, file, args):
836 """spawnv(mode, file, args) -> integer 956 """spawnv(mode, file, args) -> integer
837 957
838 Execute file with arguments from args in a subprocess. 958 Execute file with arguments from args in a subprocess.
839 If mode == P_NOWAIT return the pid of the process. 959 If mode == P_NOWAIT return the pid of the process.
840 If mode == P_WAIT return the process's exit code if it exits normally; 960 If mode == P_WAIT return the process's exit code if it exits normally;
841 otherwise return -SIG, where SIG is the signal that killed it. """ 961 otherwise return -SIG, where SIG is the signal that killed it. """
842 return _spawnvef(mode, file, args, None, execv) 962 return _spawnvef(mode, file, args, None, execv)
843 963
(...skipping 21 matching lines...) Expand all
865 985
866 def spawnvpe(mode, file, args, env): 986 def spawnvpe(mode, file, args, env):
867 """spawnvpe(mode, file, args, env) -> integer 987 """spawnvpe(mode, file, args, env) -> integer
868 988
869 Execute file (which is looked for along $PATH) with arguments from 989 Execute file (which is looked for along $PATH) with arguments from
870 args in a subprocess with the supplied environment. 990 args in a subprocess with the supplied environment.
871 If mode == P_NOWAIT return the pid of the process. 991 If mode == P_NOWAIT return the pid of the process.
872 If mode == P_WAIT return the process's exit code if it exits normally; 992 If mode == P_WAIT return the process's exit code if it exits normally;
873 otherwise return -SIG, where SIG is the signal that killed it. """ 993 otherwise return -SIG, where SIG is the signal that killed it. """
874 return _spawnvef(mode, file, args, env, execvpe) 994 return _spawnvef(mode, file, args, env, execvpe)
995
996
997 __all__.extend(["spawnv", "spawnve", "spawnvp", "spawnvpe"])
998
875 999
876 if _exists("spawnv"): 1000 if _exists("spawnv"):
877 # These aren't supplied by the basic Windows code 1001 # These aren't supplied by the basic Windows code
878 # but can be easily implemented in Python 1002 # but can be easily implemented in Python
879 1003
880 def spawnl(mode, file, *args): 1004 def spawnl(mode, file, *args):
881 """spawnl(mode, file, *args) -> integer 1005 """spawnl(mode, file, *args) -> integer
882 1006
883 Execute file with arguments from args in a subprocess. 1007 Execute file with arguments from args in a subprocess.
884 If mode == P_NOWAIT return the pid of the process. 1008 If mode == P_NOWAIT return the pid of the process.
885 If mode == P_WAIT return the process's exit code if it exits normally; 1009 If mode == P_WAIT return the process's exit code if it exits normally;
886 otherwise return -SIG, where SIG is the signal that killed it. """ 1010 otherwise return -SIG, where SIG is the signal that killed it. """
887 return spawnv(mode, file, args) 1011 return spawnv(mode, file, args)
888 1012
889 def spawnle(mode, file, *args): 1013 def spawnle(mode, file, *args):
890 """spawnle(mode, file, *args, env) -> integer 1014 """spawnle(mode, file, *args, env) -> integer
891 1015
892 Execute file with arguments from args in a subprocess with the 1016 Execute file with arguments from args in a subprocess with the
893 supplied environment. 1017 supplied environment.
894 If mode == P_NOWAIT return the pid of the process. 1018 If mode == P_NOWAIT return the pid of the process.
895 If mode == P_WAIT return the process's exit code if it exits normally; 1019 If mode == P_WAIT return the process's exit code if it exits normally;
896 otherwise return -SIG, where SIG is the signal that killed it. """ 1020 otherwise return -SIG, where SIG is the signal that killed it. """
897 env = args[-1] 1021 env = args[-1]
898 return spawnve(mode, file, args[:-1], env) 1022 return spawnve(mode, file, args[:-1], env)
899 1023
900 1024
901 __all__.extend(["spawnv", "spawnve", "spawnl", "spawnle",]) 1025 __all__.extend(["spawnl", "spawnle"])
902 1026
903 1027
904 if _exists("spawnvp"): 1028 if _exists("spawnvp"):
905 # At the moment, Windows doesn't implement spawnvp[e], 1029 # At the moment, Windows doesn't implement spawnvp[e],
906 # so it won't have spawnlp[e] either. 1030 # so it won't have spawnlp[e] either.
907 def spawnlp(mode, file, *args): 1031 def spawnlp(mode, file, *args):
908 """spawnlp(mode, file, *args) -> integer 1032 """spawnlp(mode, file, *args) -> integer
909 1033
910 Execute file (which is looked for along $PATH) with arguments from 1034 Execute file (which is looked for along $PATH) with arguments from
911 args in a subprocess with the supplied environment. 1035 args in a subprocess with the supplied environment.
912 If mode == P_NOWAIT return the pid of the process. 1036 If mode == P_NOWAIT return the pid of the process.
913 If mode == P_WAIT return the process's exit code if it exits normally; 1037 If mode == P_WAIT return the process's exit code if it exits normally;
914 otherwise return -SIG, where SIG is the signal that killed it. """ 1038 otherwise return -SIG, where SIG is the signal that killed it. """
915 return spawnvp(mode, file, args) 1039 return spawnvp(mode, file, args)
916 1040
917 def spawnlpe(mode, file, *args): 1041 def spawnlpe(mode, file, *args):
918 """spawnlpe(mode, file, *args, env) -> integer 1042 """spawnlpe(mode, file, *args, env) -> integer
919 1043
920 Execute file (which is looked for along $PATH) with arguments from 1044 Execute file (which is looked for along $PATH) with arguments from
921 args in a subprocess with the supplied environment. 1045 args in a subprocess with the supplied environment.
922 If mode == P_NOWAIT return the pid of the process. 1046 If mode == P_NOWAIT return the pid of the process.
923 If mode == P_WAIT return the process's exit code if it exits normally; 1047 If mode == P_WAIT return the process's exit code if it exits normally;
924 otherwise return -SIG, where SIG is the signal that killed it. """ 1048 otherwise return -SIG, where SIG is the signal that killed it. """
925 env = args[-1] 1049 env = args[-1]
926 return spawnvpe(mode, file, args[:-1], env) 1050 return spawnvpe(mode, file, args[:-1], env)
927 1051
928 1052
929 __all__.extend(["spawnvp", "spawnvpe", "spawnlp", "spawnlpe",]) 1053 __all__.extend(["spawnlp", "spawnlpe"])
930 1054
931 import copyreg as _copyreg
932
933 def _make_stat_result(tup, dict):
934 return stat_result(tup, dict)
935
936 def _pickle_stat_result(sr):
937 (type, args) = sr.__reduce__()
938 return (_make_stat_result, args)
939
940 try:
941 _copyreg.pickle(stat_result, _pickle_stat_result, _make_stat_result)
942 except NameError: # stat_result may not exist
943 pass
944
945 def _make_statvfs_result(tup, dict):
946 return statvfs_result(tup, dict)
947
948 def _pickle_statvfs_result(sr):
949 (type, args) = sr.__reduce__()
950 return (_make_statvfs_result, args)
951
952 try:
953 _copyreg.pickle(statvfs_result, _pickle_statvfs_result,
954 _make_statvfs_result)
955 except NameError: # statvfs_result may not exist
956 pass
957 1055
958 # Supply os.popen() 1056 # Supply os.popen()
959 def popen(cmd, mode="r", buffering=-1): 1057 def popen(cmd, mode="r", buffering=-1):
960 if not isinstance(cmd, str): 1058 if not isinstance(cmd, str):
961 raise TypeError("invalid cmd type (%s, expected string)" % type(cmd)) 1059 raise TypeError("invalid cmd type (%s, expected string)" % type(cmd))
962 if mode not in ("r", "w"): 1060 if mode not in ("r", "w"):
963 raise ValueError("invalid mode %r" % mode) 1061 raise ValueError("invalid mode %r" % mode)
964 if buffering == 0 or buffering is None: 1062 if buffering == 0 or buffering is None:
965 raise ValueError("popen() does not support unbuffered streams") 1063 raise ValueError("popen() does not support unbuffered streams")
966 import subprocess, io 1064 import subprocess, io
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
999 return getattr(self._stream, name) 1097 return getattr(self._stream, name)
1000 def __iter__(self): 1098 def __iter__(self):
1001 return iter(self._stream) 1099 return iter(self._stream)
1002 1100
1003 # Supply os.fdopen() 1101 # Supply os.fdopen()
1004 def fdopen(fd, *args, **kwargs): 1102 def fdopen(fd, *args, **kwargs):
1005 if not isinstance(fd, int): 1103 if not isinstance(fd, int):
1006 raise TypeError("invalid fd type (%s, expected integer)" % type(fd)) 1104 raise TypeError("invalid fd type (%s, expected integer)" % type(fd))
1007 import io 1105 import io
1008 return io.open(fd, *args, **kwargs) 1106 return io.open(fd, *args, **kwargs)
1009
1010 if name == "posix":
1011 def get_shell():
1012 """Return the path to default shell for Unix."""
1013 for path in confstr("CS_PATH").split(pathsep):
1014 sh = sep.join((path, "sh"))
1015 try:
1016 mode = stat(sh).st_mode
1017 except OSError:
1018 pass
1019 else:
1020 if st.S_ISREG(mode):
1021 return sh
1022 raise FileNotFound("sh")
1023 elif name in {"nt", "ce"}:
1024 def get_shell():
1025 """Return the path to default shell for Windows."""
1026 return environ.get("COMSPEC", "cmd.exe")
LEFTRIGHT

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+