##// END OF EJS Templates
Update bundled copy of pexpect to 3.3...
Thomas Kluyver -
Show More
@@ -80,6 +80,7 b' try:'
80 import traceback
80 import traceback
81 import signal
81 import signal
82 import codecs
82 import codecs
83 import stat
83 except ImportError: # pragma: no cover
84 except ImportError: # pragma: no cover
84 err = sys.exc_info()[1]
85 err = sys.exc_info()[1]
85 raise ImportError(str(err) + '''
86 raise ImportError(str(err) + '''
@@ -87,7 +88,7 b' except ImportError: # pragma: no cover'
87 A critical module was not found. Probably this operating system does not
88 A critical module was not found. Probably this operating system does not
88 support it. Pexpect is intended for UNIX-like operating systems.''')
89 support it. Pexpect is intended for UNIX-like operating systems.''')
89
90
90 __version__ = '3.2'
91 __version__ = '3.3'
91 __revision__ = ''
92 __revision__ = ''
92 __all__ = ['ExceptionPexpect', 'EOF', 'TIMEOUT', 'spawn', 'spawnu', 'run', 'runu',
93 __all__ = ['ExceptionPexpect', 'EOF', 'TIMEOUT', 'spawn', 'spawnu', 'run', 'runu',
93 'which', 'split_command_line', '__version__', '__revision__']
94 'which', 'split_command_line', '__version__', '__revision__']
@@ -284,6 +285,7 b' class spawn(object):'
284 def _chr(c):
285 def _chr(c):
285 return bytes([c])
286 return bytes([c])
286 linesep = os.linesep.encode('ascii')
287 linesep = os.linesep.encode('ascii')
288 crlf = '\r\n'.encode('ascii')
287
289
288 @staticmethod
290 @staticmethod
289 def write_to_stdout(b):
291 def write_to_stdout(b):
@@ -296,13 +298,14 b' class spawn(object):'
296 allowed_string_types = (basestring,) # analysis:ignore
298 allowed_string_types = (basestring,) # analysis:ignore
297 _chr = staticmethod(chr)
299 _chr = staticmethod(chr)
298 linesep = os.linesep
300 linesep = os.linesep
301 crlf = '\r\n'
299 write_to_stdout = sys.stdout.write
302 write_to_stdout = sys.stdout.write
300
303
301 encoding = None
304 encoding = None
302
305
303 def __init__(self, command, args=[], timeout=30, maxread=2000,
306 def __init__(self, command, args=[], timeout=30, maxread=2000,
304 searchwindowsize=None, logfile=None, cwd=None, env=None,
307 searchwindowsize=None, logfile=None, cwd=None, env=None,
305 ignore_sighup=True):
308 ignore_sighup=True, echo=True):
306
309
307 '''This is the constructor. The command parameter may be a string that
310 '''This is the constructor. The command parameter may be a string that
308 includes a command and any arguments to the command. For example::
311 includes a command and any arguments to the command. For example::
@@ -415,7 +418,16 b' class spawn(object):'
415 signalstatus will store the signal value and exitstatus will be None.
418 signalstatus will store the signal value and exitstatus will be None.
416 If you need more detail you can also read the self.status member which
419 If you need more detail you can also read the self.status member which
417 stores the status returned by os.waitpid. You can interpret this using
420 stores the status returned by os.waitpid. You can interpret this using
418 os.WIFEXITED/os.WEXITSTATUS or os.WIFSIGNALED/os.TERMSIG. '''
421 os.WIFEXITED/os.WEXITSTATUS or os.WIFSIGNALED/os.TERMSIG.
422
423 The echo attribute may be set to False to disable echoing of input.
424 As a pseudo-terminal, all input echoed by the "keyboard" (send()
425 or sendline()) will be repeated to output. For many cases, it is
426 not desirable to have echo enabled, and it may be later disabled
427 using setecho(False) followed by waitnoecho(). However, for some
428 platforms such as Solaris, this is not possible, and should be
429 disabled immediately on spawn.
430 '''
419
431
420 self.STDIN_FILENO = pty.STDIN_FILENO
432 self.STDIN_FILENO = pty.STDIN_FILENO
421 self.STDOUT_FILENO = pty.STDOUT_FILENO
433 self.STDOUT_FILENO = pty.STDOUT_FILENO
@@ -437,7 +449,7 b' class spawn(object):'
437 self.status = None
449 self.status = None
438 self.flag_eof = False
450 self.flag_eof = False
439 self.pid = None
451 self.pid = None
440 # the chile filedescriptor is initially closed
452 # the child file descriptor is initially closed
441 self.child_fd = -1
453 self.child_fd = -1
442 self.timeout = timeout
454 self.timeout = timeout
443 self.delimiter = EOF
455 self.delimiter = EOF
@@ -466,16 +478,30 b' class spawn(object):'
466 self.closed = True
478 self.closed = True
467 self.cwd = cwd
479 self.cwd = cwd
468 self.env = env
480 self.env = env
481 self.echo = echo
469 self.ignore_sighup = ignore_sighup
482 self.ignore_sighup = ignore_sighup
483 _platform = sys.platform.lower()
470 # This flags if we are running on irix
484 # This flags if we are running on irix
471 self.__irix_hack = (sys.platform.lower().find('irix') >= 0)
485 self.__irix_hack = _platform.startswith('irix')
472 # Solaris uses internal __fork_pty(). All others use pty.fork().
486 # Solaris uses internal __fork_pty(). All others use pty.fork().
473 if ((sys.platform.lower().find('solaris') >= 0)
487 self.use_native_pty_fork = not (
474 or (sys.platform.lower().find('sunos5') >= 0)):
488 _platform.startswith('solaris') or
475 self.use_native_pty_fork = False
489 _platform.startswith('sunos'))
476 else:
490 # inherit EOF and INTR definitions from controlling process.
477 self.use_native_pty_fork = True
491 try:
478
492 from termios import VEOF, VINTR
493 fd = sys.__stdin__.fileno()
494 self._INTR = ord(termios.tcgetattr(fd)[6][VINTR])
495 self._EOF = ord(termios.tcgetattr(fd)[6][VEOF])
496 except (ImportError, OSError, IOError, termios.error):
497 # unless the controlling process is also not a terminal,
498 # such as cron(1). Fall-back to using CEOF and CINTR.
499 try:
500 from termios import CEOF, CINTR
501 (self._INTR, self._EOF) = (CINTR, CEOF)
502 except ImportError:
503 # ^C, ^D
504 (self._INTR, self._EOF) = (3, 4)
479 # Support subclasses that do not use command or args.
505 # Support subclasses that do not use command or args.
480 if command is None:
506 if command is None:
481 self.command = None
507 self.command = None
@@ -599,33 +625,39 b' class spawn(object):'
599 if self.use_native_pty_fork:
625 if self.use_native_pty_fork:
600 try:
626 try:
601 self.pid, self.child_fd = pty.fork()
627 self.pid, self.child_fd = pty.fork()
602 except OSError:
628 except OSError: # pragma: no cover
603 err = sys.exc_info()[1]
629 err = sys.exc_info()[1]
604 raise ExceptionPexpect('pty.fork() failed: ' + str(err))
630 raise ExceptionPexpect('pty.fork() failed: ' + str(err))
605 else:
631 else:
606 # Use internal __fork_pty
632 # Use internal __fork_pty
607 self.pid, self.child_fd = self.__fork_pty()
633 self.pid, self.child_fd = self.__fork_pty()
608
634
609 if self.pid == 0:
635 # Some platforms must call setwinsize() and setecho() from the
636 # child process, and others from the master process. We do both,
637 # allowing IOError for either.
638
639 if self.pid == pty.CHILD:
610 # Child
640 # Child
641 self.child_fd = self.STDIN_FILENO
642
643 # set default window size of 24 rows by 80 columns
611 try:
644 try:
612 # used by setwinsize()
613 self.child_fd = sys.stdout.fileno()
614 self.setwinsize(24, 80)
645 self.setwinsize(24, 80)
615 # which exception, shouldnt' we catch explicitly .. ?
646 except IOError as err:
616 except:
647 if err.args[0] not in (errno.EINVAL, errno.ENOTTY):
617 # Some platforms do not like setwinsize (Cygwin).
648 raise
618 # This will cause problem when running applications that
649
619 # are very picky about window size.
650 # disable echo if spawn argument echo was unset
620 # This is a serious limitation, but not a show stopper.
651 if not self.echo:
621 pass
652 try:
653 self.setecho(self.echo)
654 except (IOError, termios.error) as err:
655 if err.args[0] not in (errno.EINVAL, errno.ENOTTY):
656 raise
657
622 # Do not allow child to inherit open file descriptors from parent.
658 # Do not allow child to inherit open file descriptors from parent.
623 max_fd = resource.getrlimit(resource.RLIMIT_NOFILE)[0]
659 max_fd = resource.getrlimit(resource.RLIMIT_NOFILE)[0]
624 for i in range(3, max_fd):
660 os.closerange(3, max_fd)
625 try:
626 os.close(i)
627 except OSError:
628 pass
629
661
630 if self.ignore_sighup:
662 if self.ignore_sighup:
631 signal.signal(signal.SIGHUP, signal.SIG_IGN)
663 signal.signal(signal.SIGHUP, signal.SIG_IGN)
@@ -638,6 +670,13 b' class spawn(object):'
638 os.execvpe(self.command, self.args, self.env)
670 os.execvpe(self.command, self.args, self.env)
639
671
640 # Parent
672 # Parent
673 try:
674 self.setwinsize(24, 80)
675 except IOError as err:
676 if err.args[0] not in (errno.EINVAL, errno.ENOTTY):
677 raise
678
679
641 self.terminated = False
680 self.terminated = False
642 self.closed = False
681 self.closed = False
643
682
@@ -660,19 +699,15 b' class spawn(object):'
660 raise ExceptionPexpect("Could not open with os.openpty().")
699 raise ExceptionPexpect("Could not open with os.openpty().")
661
700
662 pid = os.fork()
701 pid = os.fork()
663 if pid < 0:
702 if pid == pty.CHILD:
664 raise ExceptionPexpect("Failed os.fork().")
665 elif pid == 0:
666 # Child.
703 # Child.
667 os.close(parent_fd)
704 os.close(parent_fd)
668 self.__pty_make_controlling_tty(child_fd)
705 self.__pty_make_controlling_tty(child_fd)
669
706
670 os.dup2(child_fd, 0)
707 os.dup2(child_fd, self.STDIN_FILENO)
671 os.dup2(child_fd, 1)
708 os.dup2(child_fd, self.STDOUT_FILENO)
672 os.dup2(child_fd, 2)
709 os.dup2(child_fd, self.STDERR_FILENO)
673
710
674 if child_fd > 2:
675 os.close(child_fd)
676 else:
711 else:
677 # Parent.
712 # Parent.
678 os.close(child_fd)
713 os.close(child_fd)
@@ -686,44 +721,36 b' class spawn(object):'
686
721
687 child_name = os.ttyname(tty_fd)
722 child_name = os.ttyname(tty_fd)
688
723
689 # Disconnect from controlling tty. Harmless if not already connected.
724 # Disconnect from controlling tty, if any. Raises OSError of ENXIO
725 # if there was no controlling tty to begin with, such as when
726 # executed by a cron(1) job.
690 try:
727 try:
691 fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY)
728 fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY)
692 if fd >= 0:
729 os.close(fd)
693 os.close(fd)
730 except OSError as err:
694 # which exception, shouldnt' we catch explicitly .. ?
731 if err.errno != errno.ENXIO:
695 except:
732 raise
696 # Already disconnected. This happens if running inside cron.
697 pass
698
733
699 os.setsid()
734 os.setsid()
700
735
701 # Verify we are disconnected from controlling tty
736 # Verify we are disconnected from controlling tty by attempting to open
702 # by attempting to open it again.
737 # it again. We expect that OSError of ENXIO should always be raised.
703 try:
738 try:
704 fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY)
739 fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY)
705 if fd >= 0:
740 os.close(fd)
706 os.close(fd)
741 raise ExceptionPexpect("OSError of errno.ENXIO should be raised.")
707 raise ExceptionPexpect('Failed to disconnect from ' +
742 except OSError as err:
708 'controlling tty. It is still possible to open /dev/tty.')
743 if err.errno != errno.ENXIO:
709 # which exception, shouldnt' we catch explicitly .. ?
744 raise
710 except:
711 # Good! We are disconnected from a controlling tty.
712 pass
713
745
714 # Verify we can open child pty.
746 # Verify we can open child pty.
715 fd = os.open(child_name, os.O_RDWR)
747 fd = os.open(child_name, os.O_RDWR)
716 if fd < 0:
748 os.close(fd)
717 raise ExceptionPexpect("Could not open child pty, " + child_name)
718 else:
719 os.close(fd)
720
749
721 # Verify we now have a controlling tty.
750 # Verify we now have a controlling tty.
722 fd = os.open("/dev/tty", os.O_WRONLY)
751 fd = os.open("/dev/tty", os.O_WRONLY)
723 if fd < 0:
752 os.close(fd)
724 raise ExceptionPexpect("Could not open controlling tty, /dev/tty")
753
725 else:
726 os.close(fd)
727
754
728 def fileno(self):
755 def fileno(self):
729 '''This returns the file descriptor of the pty for the child.
756 '''This returns the file descriptor of the pty for the child.
@@ -757,7 +784,12 b' class spawn(object):'
757
784
758 def isatty(self):
785 def isatty(self):
759 '''This returns True if the file descriptor is open and connected to a
786 '''This returns True if the file descriptor is open and connected to a
760 tty(-like) device, else False. '''
787 tty(-like) device, else False.
788
789 On SVR4-style platforms implementing streams, such as SunOS and HP-UX,
790 the child pty may not appear as a terminal device. This means
791 methods such as setecho(), setwinsize(), getwinsize() may raise an
792 IOError. '''
761
793
762 return os.isatty(self.child_fd)
794 return os.isatty(self.child_fd)
763
795
@@ -794,12 +826,20 b' class spawn(object):'
794 def getecho(self):
826 def getecho(self):
795 '''This returns the terminal echo mode. This returns True if echo is
827 '''This returns the terminal echo mode. This returns True if echo is
796 on or False if echo is off. Child applications that are expecting you
828 on or False if echo is off. Child applications that are expecting you
797 to enter a password often set ECHO False. See waitnoecho(). '''
829 to enter a password often set ECHO False. See waitnoecho().
798
830
799 attr = termios.tcgetattr(self.child_fd)
831 Not supported on platforms where ``isatty()`` returns False. '''
800 if attr[3] & termios.ECHO:
832
801 return True
833 try:
802 return False
834 attr = termios.tcgetattr(self.child_fd)
835 except termios.error as err:
836 errmsg = 'getecho() may not be called on this platform'
837 if err.args[0] == errno.EINVAL:
838 raise IOError(err.args[0], '%s: %s.' % (err.args[1], errmsg))
839 raise
840
841 self.echo = bool(attr[3] & termios.ECHO)
842 return self.echo
803
843
804 def setecho(self, state):
844 def setecho(self, state):
805 '''This sets the terminal echo mode on or off. Note that anything the
845 '''This sets the terminal echo mode on or off. Note that anything the
@@ -829,18 +869,35 b' class spawn(object):'
829 p.expect(['1234'])
869 p.expect(['1234'])
830 p.expect(['abcd'])
870 p.expect(['abcd'])
831 p.expect(['wxyz'])
871 p.expect(['wxyz'])
872
873
874 Not supported on platforms where ``isatty()`` returns False.
832 '''
875 '''
833
876
834 self.child_fd
877 errmsg = 'setecho() may not be called on this platform'
835 attr = termios.tcgetattr(self.child_fd)
878
879 try:
880 attr = termios.tcgetattr(self.child_fd)
881 except termios.error as err:
882 if err.args[0] == errno.EINVAL:
883 raise IOError(err.args[0], '%s: %s.' % (err.args[1], errmsg))
884 raise
885
836 if state:
886 if state:
837 attr[3] = attr[3] | termios.ECHO
887 attr[3] = attr[3] | termios.ECHO
838 else:
888 else:
839 attr[3] = attr[3] & ~termios.ECHO
889 attr[3] = attr[3] & ~termios.ECHO
840 # I tried TCSADRAIN and TCSAFLUSH, but
890
841 # these were inconsistent and blocked on some platforms.
891 try:
842 # TCSADRAIN would probably be ideal if it worked.
892 # I tried TCSADRAIN and TCSAFLUSH, but these were inconsistent and
843 termios.tcsetattr(self.child_fd, termios.TCSANOW, attr)
893 # blocked on some platforms. TCSADRAIN would probably be ideal.
894 termios.tcsetattr(self.child_fd, termios.TCSANOW, attr)
895 except IOError as err:
896 if err.args[0] == errno.EINVAL:
897 raise IOError(err.args[0], '%s: %s.' % (err.args[1], errmsg))
898 raise
899
900 self.echo = state
844
901
845 def _log(self, s, direction):
902 def _log(self, s, direction):
846 if self.logfile is not None:
903 if self.logfile is not None:
@@ -913,12 +970,14 b' class spawn(object):'
913 if self.child_fd in r:
970 if self.child_fd in r:
914 try:
971 try:
915 s = os.read(self.child_fd, size)
972 s = os.read(self.child_fd, size)
916 except OSError:
973 except OSError as err:
917 # Linux does this
974 if err.args[0] == errno.EIO:
918 self.flag_eof = True
975 # Linux-style EOF
919 raise EOF('End Of File (EOF). Exception style platform.')
976 self.flag_eof = True
977 raise EOF('End Of File (EOF). Exception style platform.')
978 raise
920 if s == b'':
979 if s == b'':
921 # BSD style
980 # BSD-style EOF
922 self.flag_eof = True
981 self.flag_eof = True
923 raise EOF('End Of File (EOF). Empty string style platform.')
982 raise EOF('End Of File (EOF). Empty string style platform.')
924
983
@@ -926,7 +985,7 b' class spawn(object):'
926 self._log(s, 'read')
985 self._log(s, 'read')
927 return s
986 return s
928
987
929 raise ExceptionPexpect('Reached an unexpected state.')
988 raise ExceptionPexpect('Reached an unexpected state.') # pragma: no cover
930
989
931 def read(self, size=-1):
990 def read(self, size=-1):
932 '''This reads at most "size" bytes from the file (less if the read hits
991 '''This reads at most "size" bytes from the file (less if the read hits
@@ -972,9 +1031,9 b' class spawn(object):'
972 if size == 0:
1031 if size == 0:
973 return self.string_type()
1032 return self.string_type()
974 # delimiter default is EOF
1033 # delimiter default is EOF
975 index = self.expect([b'\r\n', self.delimiter])
1034 index = self.expect([self.crlf, self.delimiter])
976 if index == 0:
1035 if index == 0:
977 return self.before + b'\r\n'
1036 return self.before + self.crlf
978 else:
1037 else:
979 return self.before
1038 return self.before
980
1039
@@ -1075,40 +1134,14 b' class spawn(object):'
1075 It is the responsibility of the caller to ensure the eof is sent at the
1134 It is the responsibility of the caller to ensure the eof is sent at the
1076 beginning of a line. '''
1135 beginning of a line. '''
1077
1136
1078 ### Hmmm... how do I send an EOF?
1137 self.send(self._chr(self._EOF))
1079 ###C if ((m = write(pty, *buf, p - *buf)) < 0)
1080 ###C return (errno == EWOULDBLOCK) ? n : -1;
1081 #fd = sys.stdin.fileno()
1082 #old = termios.tcgetattr(fd) # remember current state
1083 #attr = termios.tcgetattr(fd)
1084 #attr[3] = attr[3] | termios.ICANON # ICANON must be set to see EOF
1085 #try: # use try/finally to ensure state gets restored
1086 # termios.tcsetattr(fd, termios.TCSADRAIN, attr)
1087 # if hasattr(termios, 'CEOF'):
1088 # os.write(self.child_fd, '%c' % termios.CEOF)
1089 # else:
1090 # # Silly platform does not define CEOF so assume CTRL-D
1091 # os.write(self.child_fd, '%c' % 4)
1092 #finally: # restore state
1093 # termios.tcsetattr(fd, termios.TCSADRAIN, old)
1094 if hasattr(termios, 'VEOF'):
1095 char = ord(termios.tcgetattr(self.child_fd)[6][termios.VEOF])
1096 else:
1097 # platform does not define VEOF so assume CTRL-D
1098 char = 4
1099 self.send(self._chr(char))
1100
1138
1101 def sendintr(self):
1139 def sendintr(self):
1102
1140
1103 '''This sends a SIGINT to the child. It does not require
1141 '''This sends a SIGINT to the child. It does not require
1104 the SIGINT to be the first character on a line. '''
1142 the SIGINT to be the first character on a line. '''
1105
1143
1106 if hasattr(termios, 'VINTR'):
1144 self.send(self._chr(self._INTR))
1107 char = ord(termios.tcgetattr(self.child_fd)[6][termios.VINTR])
1108 else:
1109 # platform does not define VINTR so assume CTRL-C
1110 char = 3
1111 self.send(self._chr(char))
1112
1145
1113 def eof(self):
1146 def eof(self):
1114
1147
@@ -1181,7 +1214,7 b' class spawn(object):'
1181 self.exitstatus = None
1214 self.exitstatus = None
1182 self.signalstatus = os.WTERMSIG(status)
1215 self.signalstatus = os.WTERMSIG(status)
1183 self.terminated = True
1216 self.terminated = True
1184 elif os.WIFSTOPPED(status):
1217 elif os.WIFSTOPPED(status): # pragma: no cover
1185 # You can't call wait() on a child process in the stopped state.
1218 # You can't call wait() on a child process in the stopped state.
1186 raise ExceptionPexpect('Called wait() on a stopped child ' +
1219 raise ExceptionPexpect('Called wait() on a stopped child ' +
1187 'process. This is not supported. Is some other ' +
1220 'process. This is not supported. Is some other ' +
@@ -1201,7 +1234,7 b' class spawn(object):'
1201
1234
1202 if self.flag_eof:
1235 if self.flag_eof:
1203 # This is for Linux, which requires the blocking form
1236 # This is for Linux, which requires the blocking form
1204 # of waitpid to # get status of a defunct process.
1237 # of waitpid to get the status of a defunct process.
1205 # This is super-lame. The flag_eof would have been set
1238 # This is super-lame. The flag_eof would have been set
1206 # in read_nonblocking(), so this should be safe.
1239 # in read_nonblocking(), so this should be safe.
1207 waitpid_options = 0
1240 waitpid_options = 0
@@ -1229,7 +1262,7 b' class spawn(object):'
1229 try:
1262 try:
1230 ### os.WNOHANG) # Solaris!
1263 ### os.WNOHANG) # Solaris!
1231 pid, status = os.waitpid(self.pid, waitpid_options)
1264 pid, status = os.waitpid(self.pid, waitpid_options)
1232 except OSError as e:
1265 except OSError as e: # pragma: no cover
1233 # This should never happen...
1266 # This should never happen...
1234 if e.errno == errno.ECHILD:
1267 if e.errno == errno.ECHILD:
1235 raise ExceptionPexpect('isalive() encountered condition ' +
1268 raise ExceptionPexpect('isalive() encountered condition ' +
@@ -1643,10 +1676,14 b' class spawn(object):'
1643 if self.child_fd in r:
1676 if self.child_fd in r:
1644 try:
1677 try:
1645 data = self.__interact_read(self.child_fd)
1678 data = self.__interact_read(self.child_fd)
1646 except OSError as e:
1679 except OSError as err:
1647 # The subprocess may have closed before we get to reading it
1680 if err.args[0] == errno.EIO:
1648 if e.errno != errno.EIO:
1681 # Linux-style EOF
1649 raise
1682 break
1683 raise
1684 if data == b'':
1685 # BSD-style EOF
1686 break
1650 if output_filter:
1687 if output_filter:
1651 data = output_filter(data)
1688 data = output_filter(data)
1652 if self.logfile is not None:
1689 if self.logfile is not None:
@@ -1695,7 +1732,7 b' class spawn(object):'
1695 ##############################################################################
1732 ##############################################################################
1696 # The following methods are no longer supported or allowed.
1733 # The following methods are no longer supported or allowed.
1697
1734
1698 def setmaxread(self, maxread):
1735 def setmaxread(self, maxread): # pragma: no cover
1699
1736
1700 '''This method is no longer supported or allowed. I don't like getters
1737 '''This method is no longer supported or allowed. I don't like getters
1701 and setters without a good reason. '''
1738 and setters without a good reason. '''
@@ -1704,7 +1741,7 b' class spawn(object):'
1704 'or allowed. Just assign a value to the ' +
1741 'or allowed. Just assign a value to the ' +
1705 'maxread member variable.')
1742 'maxread member variable.')
1706
1743
1707 def setlog(self, fileobject):
1744 def setlog(self, fileobject): # pragma: no cover
1708
1745
1709 '''This method is no longer supported or allowed.
1746 '''This method is no longer supported or allowed.
1710 '''
1747 '''
@@ -1732,11 +1769,13 b' class spawnu(spawn):'
1732 allowed_string_types = (str, )
1769 allowed_string_types = (str, )
1733 _chr = staticmethod(chr)
1770 _chr = staticmethod(chr)
1734 linesep = os.linesep
1771 linesep = os.linesep
1772 crlf = '\r\n'
1735 else:
1773 else:
1736 string_type = unicode
1774 string_type = unicode
1737 allowed_string_types = (unicode, )
1775 allowed_string_types = (unicode, )
1738 _chr = staticmethod(unichr)
1776 _chr = staticmethod(unichr)
1739 linesep = os.linesep.decode('ascii')
1777 linesep = os.linesep.decode('ascii')
1778 crlf = '\r\n'.decode('ascii')
1740 # This can handle unicode in both Python 2 and 3
1779 # This can handle unicode in both Python 2 and 3
1741 write_to_stdout = sys.stdout.write
1780 write_to_stdout = sys.stdout.write
1742
1781
@@ -1959,16 +1998,56 b' class searcher_re(object):'
1959 return best_index
1998 return best_index
1960
1999
1961
2000
1962 def which(filename):
2001 def is_executable_file(path):
2002 """Checks that path is an executable regular file (or a symlink to a file).
2003
2004 This is roughly ``os.path isfile(path) and os.access(path, os.X_OK)``, but
2005 on some platforms :func:`os.access` gives us the wrong answer, so this
2006 checks permission bits directly.
2007 """
2008 # follow symlinks,
2009 fpath = os.path.realpath(path)
1963
2010
2011 # return False for non-files (directories, fifo, etc.)
2012 if not os.path.isfile(fpath):
2013 return False
2014
2015 # On Solaris, etc., "If the process has appropriate privileges, an
2016 # implementation may indicate success for X_OK even if none of the
2017 # execute file permission bits are set."
2018 #
2019 # For this reason, it is necessary to explicitly check st_mode
2020
2021 # get file mode using os.stat, and check if `other',
2022 # that is anybody, may read and execute.
2023 mode = os.stat(fpath).st_mode
2024 if mode & stat.S_IROTH and mode & stat.S_IXOTH:
2025 return True
2026
2027 # get current user's group ids, and check if `group',
2028 # when matching ours, may read and execute.
2029 user_gids = os.getgroups() + [os.getgid()]
2030 if (os.stat(fpath).st_gid in user_gids and
2031 mode & stat.S_IRGRP and mode & stat.S_IXGRP):
2032 return True
2033
2034 # finally, if file owner matches our effective userid,
2035 # check if `user', may read and execute.
2036 user_gids = os.getgroups() + [os.getgid()]
2037 if (os.stat(fpath).st_uid == os.geteuid() and
2038 mode & stat.S_IRUSR and mode & stat.S_IXUSR):
2039 return True
2040
2041 return False
2042
2043 def which(filename):
1964 '''This takes a given filename; tries to find it in the environment path;
2044 '''This takes a given filename; tries to find it in the environment path;
1965 then checks if it is executable. This returns the full path to the filename
2045 then checks if it is executable. This returns the full path to the filename
1966 if found and executable. Otherwise this returns None.'''
2046 if found and executable. Otherwise this returns None.'''
1967
2047
1968 # Special case where filename contains an explicit path.
2048 # Special case where filename contains an explicit path.
1969 if os.path.dirname(filename) != '':
2049 if os.path.dirname(filename) != '' and is_executable_file(filename):
1970 if os.access(filename, os.X_OK):
2050 return filename
1971 return filename
1972 if 'PATH' not in os.environ or os.environ['PATH'] == '':
2051 if 'PATH' not in os.environ or os.environ['PATH'] == '':
1973 p = os.defpath
2052 p = os.defpath
1974 else:
2053 else:
@@ -1976,7 +2055,7 b' def which(filename):'
1976 pathlist = p.split(os.pathsep)
2055 pathlist = p.split(os.pathsep)
1977 for path in pathlist:
2056 for path in pathlist:
1978 ff = os.path.join(path, filename)
2057 ff = os.path.join(path, filename)
1979 if os.access(ff, os.X_OK):
2058 if is_executable_file(ff):
1980 return ff
2059 return ff
1981 return None
2060 return None
1982
2061
@@ -2041,4 +2120,4 b' def split_command_line(command_line):'
2041 arg_list.append(arg)
2120 arg_list.append(arg)
2042 return arg_list
2121 return arg_list
2043
2122
2044 # vi:set sr et ts=4 sw=4 ft=python :
2123 # vim: set shiftround expandtab tabstop=4 shiftwidth=4 ft=python autoindent :
General Comments 0
You need to be logged in to leave comments. Login now