Index: third_party/Python/module/pexpect-2.4/ANSI.py
===================================================================
--- third_party/Python/module/pexpect-2.4/ANSI.py
+++ third_party/Python/module/pexpect-2.4/ANSI.py
@@ -1,370 +0,0 @@
-"""This implements an ANSI terminal emulator as a subclass of screen.
-
-$Id: ANSI.py 491 2007-12-16 20:04:57Z noah $
-"""
-# references:
-# http://www.retards.org/terminals/vt102.html
-# http://vt100.net/docs/vt102-ug/contents.html
-# http://vt100.net/docs/vt220-rm/
-# http://www.termsys.demon.co.uk/vtansi.htm
-
-import screen
-import FSM
-import copy
-import string
-
-
-def Emit(fsm):
-
- screen = fsm.memory[0]
- screen.write_ch(fsm.input_symbol)
-
-
-def StartNumber(fsm):
-
- fsm.memory.append(fsm.input_symbol)
-
-
-def BuildNumber(fsm):
-
- ns = fsm.memory.pop()
- ns = ns + fsm.input_symbol
- fsm.memory.append(ns)
-
-
-def DoBackOne(fsm):
-
- screen = fsm.memory[0]
- screen.cursor_back()
-
-
-def DoBack(fsm):
-
- count = int(fsm.memory.pop())
- screen = fsm.memory[0]
- screen.cursor_back(count)
-
-
-def DoDownOne(fsm):
-
- screen = fsm.memory[0]
- screen.cursor_down()
-
-
-def DoDown(fsm):
-
- count = int(fsm.memory.pop())
- screen = fsm.memory[0]
- screen.cursor_down(count)
-
-
-def DoForwardOne(fsm):
-
- screen = fsm.memory[0]
- screen.cursor_forward()
-
-
-def DoForward(fsm):
-
- count = int(fsm.memory.pop())
- screen = fsm.memory[0]
- screen.cursor_forward(count)
-
-
-def DoUpReverse(fsm):
-
- screen = fsm.memory[0]
- screen.cursor_up_reverse()
-
-
-def DoUpOne(fsm):
-
- screen = fsm.memory[0]
- screen.cursor_up()
-
-
-def DoUp(fsm):
-
- count = int(fsm.memory.pop())
- screen = fsm.memory[0]
- screen.cursor_up(count)
-
-
-def DoHome(fsm):
-
- c = int(fsm.memory.pop())
- r = int(fsm.memory.pop())
- screen = fsm.memory[0]
- screen.cursor_home(r, c)
-
-
-def DoHomeOrigin(fsm):
-
- c = 1
- r = 1
- screen = fsm.memory[0]
- screen.cursor_home(r, c)
-
-
-def DoEraseDown(fsm):
-
- screen = fsm.memory[0]
- screen.erase_down()
-
-
-def DoErase(fsm):
-
- arg = int(fsm.memory.pop())
- screen = fsm.memory[0]
- if arg == 0:
- screen.erase_down()
- elif arg == 1:
- screen.erase_up()
- elif arg == 2:
- screen.erase_screen()
-
-
-def DoEraseEndOfLine(fsm):
-
- screen = fsm.memory[0]
- screen.erase_end_of_line()
-
-
-def DoEraseLine(fsm):
-
- screen = fsm.memory[0]
- if arg == 0:
- screen.end_of_line()
- elif arg == 1:
- screen.start_of_line()
- elif arg == 2:
- screen.erase_line()
-
-
-def DoEnableScroll(fsm):
-
- screen = fsm.memory[0]
- screen.scroll_screen()
-
-
-def DoCursorSave(fsm):
-
- screen = fsm.memory[0]
- screen.cursor_save_attrs()
-
-
-def DoCursorRestore(fsm):
-
- screen = fsm.memory[0]
- screen.cursor_restore_attrs()
-
-
-def DoScrollRegion(fsm):
-
- screen = fsm.memory[0]
- r2 = int(fsm.memory.pop())
- r1 = int(fsm.memory.pop())
- screen.scroll_screen_rows(r1, r2)
-
-
-def DoMode(fsm):
-
- screen = fsm.memory[0]
- mode = fsm.memory.pop() # Should be 4
- # screen.setReplaceMode ()
-
-
-def Log(fsm):
-
- screen = fsm.memory[0]
- fsm.memory = [screen]
- fout = open('log', 'a')
- fout.write(fsm.input_symbol + ',' + fsm.current_state + '\n')
- fout.close()
-
-
-class term (screen.screen):
- """This is a placeholder.
- In theory I might want to add other terminal types.
- """
-
- def __init__(self, r=24, c=80):
- screen.screen.__init__(self, r, c)
-
-
-class ANSI (term):
-
- """This class encapsulates a generic terminal. It filters a stream and
- maintains the state of a screen object. """
-
- def __init__(self, r=24, c=80):
-
- term.__init__(self, r, c)
-
- #self.screen = screen (24,80)
- self.state = FSM.FSM('INIT', [self])
- self.state.set_default_transition(Log, 'INIT')
- self.state.add_transition_any('INIT', Emit, 'INIT')
- self.state.add_transition('\x1b', 'INIT', None, 'ESC')
- self.state.add_transition_any('ESC', Log, 'INIT')
- self.state.add_transition('(', 'ESC', None, 'G0SCS')
- self.state.add_transition(')', 'ESC', None, 'G1SCS')
- self.state.add_transition_list('AB012', 'G0SCS', None, 'INIT')
- self.state.add_transition_list('AB012', 'G1SCS', None, 'INIT')
- self.state.add_transition('7', 'ESC', DoCursorSave, 'INIT')
- self.state.add_transition('8', 'ESC', DoCursorRestore, 'INIT')
- self.state.add_transition('M', 'ESC', DoUpReverse, 'INIT')
- self.state.add_transition('>', 'ESC', DoUpReverse, 'INIT')
- self.state.add_transition('<', 'ESC', DoUpReverse, 'INIT')
- # Selects application keypad.
- self.state.add_transition('=', 'ESC', None, 'INIT')
- self.state.add_transition('#', 'ESC', None, 'GRAPHICS_POUND')
- self.state.add_transition_any('GRAPHICS_POUND', None, 'INIT')
- self.state.add_transition('[', 'ESC', None, 'ELB')
- # ELB means Escape Left Bracket. That is ^[[
- self.state.add_transition('H', 'ELB', DoHomeOrigin, 'INIT')
- self.state.add_transition('D', 'ELB', DoBackOne, 'INIT')
- self.state.add_transition('B', 'ELB', DoDownOne, 'INIT')
- self.state.add_transition('C', 'ELB', DoForwardOne, 'INIT')
- self.state.add_transition('A', 'ELB', DoUpOne, 'INIT')
- self.state.add_transition('J', 'ELB', DoEraseDown, 'INIT')
- self.state.add_transition('K', 'ELB', DoEraseEndOfLine, 'INIT')
- self.state.add_transition('r', 'ELB', DoEnableScroll, 'INIT')
- self.state.add_transition('m', 'ELB', None, 'INIT')
- self.state.add_transition('?', 'ELB', None, 'MODECRAP')
- self.state.add_transition_list(
- string.digits, 'ELB', StartNumber, 'NUMBER_1')
- self.state.add_transition_list(
- string.digits, 'NUMBER_1', BuildNumber, 'NUMBER_1')
- self.state.add_transition('D', 'NUMBER_1', DoBack, 'INIT')
- self.state.add_transition('B', 'NUMBER_1', DoDown, 'INIT')
- self.state.add_transition('C', 'NUMBER_1', DoForward, 'INIT')
- self.state.add_transition('A', 'NUMBER_1', DoUp, 'INIT')
- self.state.add_transition('J', 'NUMBER_1', DoErase, 'INIT')
- self.state.add_transition('K', 'NUMBER_1', DoEraseLine, 'INIT')
- self.state.add_transition('l', 'NUMBER_1', DoMode, 'INIT')
- # It gets worse... the 'm' code can have infinite number of
- # number;number;number before it. I've never seen more than two,
- # but the specs say it's allowed. crap!
- self.state.add_transition('m', 'NUMBER_1', None, 'INIT')
- # LED control. Same problem as 'm' code.
- self.state.add_transition('q', 'NUMBER_1', None, 'INIT')
-
- # \E[?47h appears to be "switch to alternate screen"
- # \E[?47l restores alternate screen... I think.
- self.state.add_transition_list(
- string.digits, 'MODECRAP', StartNumber, 'MODECRAP_NUM')
- self.state.add_transition_list(
- string.digits,
- 'MODECRAP_NUM',
- BuildNumber,
- 'MODECRAP_NUM')
- self.state.add_transition('l', 'MODECRAP_NUM', None, 'INIT')
- self.state.add_transition('h', 'MODECRAP_NUM', None, 'INIT')
-
-# RM Reset Mode Esc [ Ps l none
- self.state.add_transition(';', 'NUMBER_1', None, 'SEMICOLON')
- self.state.add_transition_any('SEMICOLON', Log, 'INIT')
- self.state.add_transition_list(
- string.digits, 'SEMICOLON', StartNumber, 'NUMBER_2')
- self.state.add_transition_list(
- string.digits, 'NUMBER_2', BuildNumber, 'NUMBER_2')
- self.state.add_transition_any('NUMBER_2', Log, 'INIT')
- self.state.add_transition('H', 'NUMBER_2', DoHome, 'INIT')
- self.state.add_transition('f', 'NUMBER_2', DoHome, 'INIT')
- self.state.add_transition('r', 'NUMBER_2', DoScrollRegion, 'INIT')
- # It gets worse... the 'm' code can have infinite number of
- # number;number;number before it. I've never seen more than two,
- # but the specs say it's allowed. crap!
- self.state.add_transition('m', 'NUMBER_2', None, 'INIT')
- # LED control. Same problem as 'm' code.
- self.state.add_transition('q', 'NUMBER_2', None, 'INIT')
-
- def process(self, c):
-
- self.state.process(c)
-
- def process_list(self, l):
-
- self.write(l)
-
- def write(self, s):
-
- for c in s:
- self.process(c)
-
- def flush(self):
-
- pass
-
- def write_ch(self, ch):
- """This puts a character at the current cursor position. cursor
- position if moved forward with wrap-around, but no scrolling is done if
- the cursor hits the lower-right corner of the screen. """
-
- #\r and \n both produce a call to crlf().
- ch = ch[0]
-
- if ch == '\r':
- # self.crlf()
- return
- if ch == '\n':
- self.crlf()
- return
- if ch == chr(screen.BS):
- self.cursor_back()
- self.put_abs(self.cur_r, self.cur_c, ' ')
- return
-
- if ch not in string.printable:
- fout = open('log', 'a')
- fout.write('Nonprint: ' + str(ord(ch)) + '\n')
- fout.close()
- return
- self.put_abs(self.cur_r, self.cur_c, ch)
- old_r = self.cur_r
- old_c = self.cur_c
- self.cursor_forward()
- if old_c == self.cur_c:
- self.cursor_down()
- if old_r != self.cur_r:
- self.cursor_home(self.cur_r, 1)
- else:
- self.scroll_up()
- self.cursor_home(self.cur_r, 1)
- self.erase_line()
-
-# def test (self):
-#
-# import sys
-# write_text = 'I\'ve got a ferret sticking up my nose.\n' + \
-# '(He\'s got a ferret sticking up his nose.)\n' + \
-# 'How it got there I can\'t tell\n' + \
-# 'But now it\'s there it hurts like hell\n' + \
-# 'And what is more it radically affects my sense of smell.\n' + \
-# '(His sense of smell.)\n' + \
-# 'I can see a bare-bottomed mandril.\n' + \
-# '(Slyly eyeing his other nostril.)\n' + \
-# 'If it jumps inside there too I really don\'t know what to do\n' + \
-# 'I\'ll be the proud posessor of a kind of nasal zoo.\n' + \
-# '(A nasal zoo.)\n' + \
-# 'I\'ve got a ferret sticking up my nose.\n' + \
-# '(And what is worst of all it constantly explodes.)\n' + \
-# '"Ferrets don\'t explode," you say\n' + \
-# 'But it happened nine times yesterday\n' + \
-# 'And I should know for each time I was standing in the way.\n' + \
-# 'I\'ve got a ferret sticking up my nose.\n' + \
-# '(He\'s got a ferret sticking up his nose.)\n' + \
-# 'How it got there I can\'t tell\n' + \
-# 'But now it\'s there it hurts like hell\n' + \
-# 'And what is more it radically affects my sense of smell.\n' + \
-# '(His sense of smell.)'
-# self.fill('.')
-# self.cursor_home()
-# for c in write_text:
-# self.write_ch (c)
-# print str(self)
-#
-# if __name__ == '__main__':
-# t = ANSI(6,65)
-# t.test()
Index: third_party/Python/module/pexpect-2.4/FSM.py
===================================================================
--- third_party/Python/module/pexpect-2.4/FSM.py
+++ third_party/Python/module/pexpect-2.4/FSM.py
@@ -1,370 +0,0 @@
-#!/usr/bin/env python
-
-"""This module implements a Finite State Machine (FSM). In addition to state
-this FSM also maintains a user defined "memory". So this FSM can be used as a
-Push-down Automata (PDA) since a PDA is a FSM + memory.
-
-The following describes how the FSM works, but you will probably also need to
-see the example function to understand how the FSM is used in practice.
-
-You define an FSM by building tables of transitions. For a given input symbol
-the process() method uses these tables to decide what action to call and what
-the next state will be. The FSM has a table of transitions that associate:
-
- (input_symbol, current_state) --> (action, next_state)
-
-Where "action" is a function you define. The symbols and states can be any
-objects. You use the add_transition() and add_transition_list() methods to add
-to the transition table. The FSM also has a table of transitions that
-associate:
-
- (current_state) --> (action, next_state)
-
-You use the add_transition_any() method to add to this transition table. The
-FSM also has one default transition that is not associated with any specific
-input_symbol or state. You use the set_default_transition() method to set the
-default transition.
-
-When an action function is called it is passed a reference to the FSM. The
-action function may then access attributes of the FSM such as input_symbol,
-current_state, or "memory". The "memory" attribute can be any object that you
-want to pass along to the action functions. It is not used by the FSM itself.
-For parsing you would typically pass a list to be used as a stack.
-
-The processing sequence is as follows. The process() method is given an
-input_symbol to process. The FSM will search the table of transitions that
-associate:
-
- (input_symbol, current_state) --> (action, next_state)
-
-If the pair (input_symbol, current_state) is found then process() will call the
-associated action function and then set the current state to the next_state.
-
-If the FSM cannot find a match for (input_symbol, current_state) it will then
-search the table of transitions that associate:
-
- (current_state) --> (action, next_state)
-
-If the current_state is found then the process() method will call the
-associated action function and then set the current state to the next_state.
-Notice that this table lacks an input_symbol. It lets you define transitions
-for a current_state and ANY input_symbol. Hence, it is called the "any" table.
-Remember, it is always checked after first searching the table for a specific
-(input_symbol, current_state).
-
-For the case where the FSM did not match either of the previous two cases the
-FSM will try to use the default transition. If the default transition is
-defined then the process() method will call the associated action function and
-then set the current state to the next_state. This lets you define a default
-transition as a catch-all case. You can think of it as an exception handler.
-There can be only one default transition.
-
-Finally, if none of the previous cases are defined for an input_symbol and
-current_state then the FSM will raise an exception. This may be desirable, but
-you can always prevent this just by defining a default transition.
-
-Noah Spurrier 20020822
-"""
-
-
-class ExceptionFSM(Exception):
-
- """This is the FSM Exception class."""
-
- def __init__(self, value):
- self.value = value
-
- def __str__(self):
- return repr(self.value)
-
-
-class FSM:
-
- """This is a Finite State Machine (FSM).
- """
-
- def __init__(self, initial_state, memory=None):
- """This creates the FSM. You set the initial state here. The "memory"
- attribute is any object that you want to pass along to the action
- functions. It is not used by the FSM. For parsing you would typically
- pass a list to be used as a stack. """
-
- # Map (input_symbol, current_state) --> (action, next_state).
- self.state_transitions = {}
- # Map (current_state) --> (action, next_state).
- self.state_transitions_any = {}
- self.default_transition = None
-
- self.input_symbol = None
- self.initial_state = initial_state
- self.current_state = self.initial_state
- self.next_state = None
- self.action = None
- self.memory = memory
-
- def reset(self):
- """This sets the current_state to the initial_state and sets
- input_symbol to None. The initial state was set by the constructor
- __init__(). """
-
- self.current_state = self.initial_state
- self.input_symbol = None
-
- def add_transition(
- self,
- input_symbol,
- state,
- action=None,
- next_state=None):
- """This adds a transition that associates:
-
- (input_symbol, current_state) --> (action, next_state)
-
- The action may be set to None in which case the process() method will
- ignore the action and only set the next_state. The next_state may be
- set to None in which case the current state will be unchanged.
-
- You can also set transitions for a list of symbols by using
- add_transition_list(). """
-
- if next_state is None:
- next_state = state
- self.state_transitions[(input_symbol, state)] = (action, next_state)
-
- def add_transition_list(
- self,
- list_input_symbols,
- state,
- action=None,
- next_state=None):
- """This adds the same transition for a list of input symbols.
- You can pass a list or a string. Note that it is handy to use
- string.digits, string.whitespace, string.letters, etc. to add
- transitions that match character classes.
-
- The action may be set to None in which case the process() method will
- ignore the action and only set the next_state. The next_state may be
- set to None in which case the current state will be unchanged. """
-
- if next_state is None:
- next_state = state
- for input_symbol in list_input_symbols:
- self.add_transition(input_symbol, state, action, next_state)
-
- def add_transition_any(self, state, action=None, next_state=None):
- """This adds a transition that associates:
-
- (current_state) --> (action, next_state)
-
- That is, any input symbol will match the current state.
- The process() method checks the "any" state associations after it first
- checks for an exact match of (input_symbol, current_state).
-
- The action may be set to None in which case the process() method will
- ignore the action and only set the next_state. The next_state may be
- set to None in which case the current state will be unchanged. """
-
- if next_state is None:
- next_state = state
- self.state_transitions_any[state] = (action, next_state)
-
- def set_default_transition(self, action, next_state):
- """This sets the default transition. This defines an action and
- next_state if the FSM cannot find the input symbol and the current
- state in the transition list and if the FSM cannot find the
- current_state in the transition_any list. This is useful as a final
- fall-through state for catching errors and undefined states.
-
- The default transition can be removed by setting the attribute
- default_transition to None. """
-
- self.default_transition = (action, next_state)
-
- def get_transition(self, input_symbol, state):
- """This returns (action, next state) given an input_symbol and state.
- This does not modify the FSM state, so calling this method has no side
- effects. Normally you do not call this method directly. It is called by
- process().
-
- The sequence of steps to check for a defined transition goes from the
- most specific to the least specific.
-
- 1. Check state_transitions[] that match exactly the tuple,
- (input_symbol, state)
-
- 2. Check state_transitions_any[] that match (state)
- In other words, match a specific state and ANY input_symbol.
-
- 3. Check if the default_transition is defined.
- This catches any input_symbol and any state.
- This is a handler for errors, undefined states, or defaults.
-
- 4. No transition was defined. If we get here then raise an exception.
- """
-
- if (input_symbol, state) in self.state_transitions:
- return self.state_transitions[(input_symbol, state)]
- elif state in self.state_transitions_any:
- return self.state_transitions_any[state]
- elif self.default_transition is not None:
- return self.default_transition
- else:
- raise ExceptionFSM('Transition is undefined: (%s, %s).' %
- (str(input_symbol), str(state)))
-
- def process(self, input_symbol):
- """This is the main method that you call to process input. This may
- cause the FSM to change state and call an action. This method calls
- get_transition() to find the action and next_state associated with the
- input_symbol and current_state. If the action is None then the action
- is not called and only the current state is changed. This method
- processes one complete input symbol. You can process a list of symbols
- (or a string) by calling process_list(). """
-
- self.input_symbol = input_symbol
- (self.action, self.next_state) = self.get_transition(
- self.input_symbol, self.current_state)
- if self.action is not None:
- self.action(self)
- self.current_state = self.next_state
- self.next_state = None
-
- def process_list(self, input_symbols):
- """This takes a list and sends each element to process(). The list may
- be a string or any iterable object. """
-
- for s in input_symbols:
- self.process(s)
-
-##############################################################################
-# The following is an example that demonstrates the use of the FSM class to
-# process an RPN expression. Run this module from the command line. You will
-# get a prompt > for input. Enter an RPN Expression. Numbers may be integers.
-# Operators are * / + - Use the = sign to evaluate and print the expression.
-# For example:
-#
-# 167 3 2 2 * * * 1 - =
-#
-# will print:
-#
-# 2003
-##############################################################################
-
-import sys
-import os
-import traceback
-import optparse
-import time
-import string
-
-#
-# These define the actions.
-# Note that "memory" is a list being used as a stack.
-#
-
-
-def BeginBuildNumber(fsm):
- fsm.memory.append(fsm.input_symbol)
-
-
-def BuildNumber(fsm):
- s = fsm.memory.pop()
- s = s + fsm.input_symbol
- fsm.memory.append(s)
-
-
-def EndBuildNumber(fsm):
- s = fsm.memory.pop()
- fsm.memory.append(int(s))
-
-
-def DoOperator(fsm):
- ar = fsm.memory.pop()
- al = fsm.memory.pop()
- if fsm.input_symbol == '+':
- fsm.memory.append(al + ar)
- elif fsm.input_symbol == '-':
- fsm.memory.append(al - ar)
- elif fsm.input_symbol == '*':
- fsm.memory.append(al * ar)
- elif fsm.input_symbol == '/':
- fsm.memory.append(al / ar)
-
-
-def DoEqual(fsm):
- print str(fsm.memory.pop())
-
-
-def Error(fsm):
- print 'That does not compute.'
- print str(fsm.input_symbol)
-
-
-def main():
- """This is where the example starts and the FSM state transitions are
- defined. Note that states are strings (such as 'INIT'). This is not
- necessary, but it makes the example easier to read. """
-
- f = FSM('INIT', []) # "memory" will be used as a stack.
- f.set_default_transition(Error, 'INIT')
- f.add_transition_any('INIT', None, 'INIT')
- f.add_transition('=', 'INIT', DoEqual, 'INIT')
- f.add_transition_list(
- string.digits,
- 'INIT',
- BeginBuildNumber,
- 'BUILDING_NUMBER')
- f.add_transition_list(
- string.digits,
- 'BUILDING_NUMBER',
- BuildNumber,
- 'BUILDING_NUMBER')
- f.add_transition_list(
- string.whitespace,
- 'BUILDING_NUMBER',
- EndBuildNumber,
- 'INIT')
- f.add_transition_list('+-*/', 'INIT', DoOperator, 'INIT')
-
- print
- print 'Enter an RPN Expression.'
- print 'Numbers may be integers. Operators are * / + -'
- print 'Use the = sign to evaluate and print the expression.'
- print 'For example: '
- print ' 167 3 2 2 * * * 1 - ='
- inputstr = raw_input('> ')
- f.process_list(inputstr)
-
-if __name__ == '__main__':
- try:
- start_time = time.time()
- parser = optparse.OptionParser(
- formatter=optparse.TitledHelpFormatter(),
- usage=globals()['__doc__'],
- version='$Id: FSM.py 490 2007-12-07 15:46:24Z noah $')
- parser.add_option(
- '-v',
- '--verbose',
- action='store_true',
- default=False,
- help='verbose output')
- (options, args) = parser.parse_args()
- if options.verbose:
- print time.asctime()
- main()
- if options.verbose:
- print time.asctime()
- if options.verbose:
- print 'TOTAL TIME IN MINUTES:',
- if options.verbose:
- print (time.time() - start_time) / 60.0
- sys.exit(0)
- except KeyboardInterrupt as e: # Ctrl-C
- raise e
- except SystemExit as e: # sys.exit()
- raise e
- except Exception as e:
- print 'ERROR, UNEXPECTED EXCEPTION'
- print str(e)
- traceback.print_exc()
- os._exit(1)
Index: third_party/Python/module/pexpect-2.4/INSTALL
===================================================================
--- third_party/Python/module/pexpect-2.4/INSTALL
+++ third_party/Python/module/pexpect-2.4/INSTALL
@@ -1,31 +0,0 @@
-Installation
-------------
-This is a standard Python Distutil distribution. To install simply run:
-
- python setup.py install
-
-This makes Pexpect available to any script on the machine. You need
-root access to install it this way. If you do not have root access or
-if you do not wish to install Pexpect so that is available to any script
-then you can just copy the pexpect.py file to same directory as your script.
-
-Trouble on Debian and Ubuntu
-----------------------------
-For some stupid reason Debian Linux does not include the distutils module
-in the standard 'python' package. Instead, the distutils module is packaged
-separately in the 'python-dev' package. So to add distutils back
-into Python, simply use aptitude or apt-get to install 'python-dev'.
-As root, run this command:
- apt-get install python-dev
-Why they do this is mysterious because:
- - It breaks the Python model of "batteries included".
- 'distutils' isn't an extra or optional module --
- it's parts of the Standard Python Library.
- - The Debian 'python-dev' package is a microscopic 50K installed.
- So what are they saving?
- - Distutils is not only interesting to developers. Many non-development
- oriented Python packages use 'distutils' to install applications.
- - As far as I can tell, the package maintainers must go through
- more trouble to remove 'distutils' from the standard Python
- distribution than it would take just to leave it in.
-
Index: third_party/Python/module/pexpect-2.4/LICENSE
===================================================================
--- third_party/Python/module/pexpect-2.4/LICENSE
+++ third_party/Python/module/pexpect-2.4/LICENSE
@@ -1,21 +0,0 @@
-Free, open source, and all that good stuff.
-Pexpect Copyright (c) 2008 Noah Spurrier
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-USE OR OTHER DEALINGS IN THE SOFTWARE.
-
Index: third_party/Python/module/pexpect-2.4/PKG-INFO
===================================================================
--- third_party/Python/module/pexpect-2.4/PKG-INFO
+++ third_party/Python/module/pexpect-2.4/PKG-INFO
@@ -1,10 +0,0 @@
-Metadata-Version: 1.0
-Name: pexpect
-Version: 2.4
-Summary: Pexpect is a pure Python Expect. It allows easy control of other applications.
-Home-page: http://pexpect.sourceforge.net/
-Author: Noah Spurrier
-Author-email: noah@noah.org
-License: MIT license
-Description: UNKNOWN
-Platform: UNIX
Index: third_party/Python/module/pexpect-2.4/README
===================================================================
--- third_party/Python/module/pexpect-2.4/README
+++ third_party/Python/module/pexpect-2.4/README
@@ -1,45 +0,0 @@
-Pexpect is a Pure Python Expect-like module
-
-Pexpect makes Python a better tool for controlling other applications.
-
-Pexpect is a pure Python module for spawning child applications; controlling
-them; and responding to expected patterns in their output. Pexpect works like
-Don Libes' Expect. Pexpect allows your script to spawn a child application and
-control it as if a human were typing commands.
-
-Pexpect can be used for automating interactive applications such as ssh, ftp,
-passwd, telnet, etc. It can be used to a automate setup scripts for
-duplicating software package installations on different servers. It can be
-used for automated software testing. Pexpect is in the spirit of Don Libes'
-Expect, but Pexpect is pure Python. Unlike other Expect-like modules for
-Python, Pexpect does not require TCL or Expect nor does it require C
-extensions to be compiled. It should work on any platform that supports the
-standard Python pty module. The Pexpect interface was designed to be easy to use.
-
-If you want to work with the development version of the source code then please
-read the DEVELOPERS document in the root of the source code tree.
-
-Free, open source, and all that good stuff.
-Pexpect Copyright (c) 2008 Noah Spurrier
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Noah Spurrier
-http://pexpect.sourceforge.net/
-
Index: third_party/Python/module/pexpect-2.4/doc/clean.css
===================================================================
--- third_party/Python/module/pexpect-2.4/doc/clean.css
+++ third_party/Python/module/pexpect-2.4/doc/clean.css
@@ -1,103 +0,0 @@
-
-body {
- margin:0px;
- padding:0px;
- font-family:verdana, arial, helvetica, sans-serif;
- color:#333;
- background-color:white;
- }
-pre {
- background: #eeeeee;
- border: 1px solid #888888;
- color: black;
- padding: 1em;
- white-space: pre;
-}
-h1 {
- margin:5px 0px 5px 0px;
- padding:0px;
- font-size:20px;
- line-height:28px;
- font-weight:900;
- color:#44f;
- }
-h2 {
- margin:5px 0px 5px 0px;
- padding:0px;
- font-size:17px;
- line-height:28px;
- font-weight:900;
- color:#226;
- }
-h3 {
- margin:5px 0px 5px 0px;
- padding:0px;
- font-size:15px;
- line-height:28px;
- font-weight:900;
- }
-p
-{
- margin:0px 0px 16px 0px;
- font:11px/20px verdana, arial, helvetica, sans-serif;
- padding:0px;
-}
-table
-{
- font-size: 10pt;
- color: #000000;
-}
-td{border:1px solid #999;}
-
-table.pymenu {color: #000000; background-color: #99ccff}
-th.pymenu {color: #ffffff; background-color: #003366}
-
-.code
-{
- font-family: "Lucida Console", monospace; font-weight: bold;
- color: #007700; background-color: #eeeeee
-}
-
-#Content>p {margin:0px;}
-#Content>p+p {text-indent:30px;}
-
-a {
- text-decoration:none;
- font-weight:600;
- font-family:verdana, arial, helvetica, sans-serif;
- color: #900;
-}
-//a:link {color:#09c;}
-//a x:visited {color:#07a;}
-a:hover {background-color:#ee0;}
-
-#Header {
- margin:10px 0px 10px 0px;
- padding:10px 0px 10px 20px;
- /* For IE5/Win's benefit height = [correct height] + [top padding] + [top and bottom border widths] */
- height:33px; /* 14px + 17px + 2px = 33px */
- border-style:solid;
- border-color:black;
- border-width:1px 0px; /* top and bottom borders: 1px; left and right borders: 0px */
- line-height:33px;
- background-color:#eee;
- height:66px; /* the correct height */
- }
-
-#Content {
- margin:0px 210px 50px 10px;
- padding:10px;
- }
-
-#Menu {
- position:absolute;
- top:100px;
- right:20px;
- width:172px;
- padding:10px;
- background-color:#eee;
- border:1px solid #999; // dashed #999;
- line-height:17px;
- width:150px;
- font-size:11px;
- }
Index: third_party/Python/module/pexpect-2.4/doc/examples.html
===================================================================
--- third_party/Python/module/pexpect-2.4/doc/examples.html
+++ third_party/Python/module/pexpect-2.4/doc/examples.html
@@ -1,135 +0,0 @@
-
-
-
-Pexpect - Examples
-
-
-
-
-
-
-
-
-
Pexpect Examples
-
-
-
-
hive.py
-
-This script creates SSH connections to a list of hosts that
-you provide. Then you are given a command line prompt. Each
-shell command that you enter is sent to all the hosts. The
-response from each host is collected and printed. For example,
-you could connect to a dozen different machines and reboot
-them all at once.
-
-
-
script.py
-
- This implements a command similar to the classic BSD
-"script" command.
- This will start a subshell and log all input and
-output to a file.
- This demonstrates the interact() method of Pexpect.
-
-
-
fix_cvs_files.py
-
- This is for cleaning up binary files improperly
-added to CVS.
- This script scans the given path to find binary
-files;
- checks with CVS to see if the sticky options are set
-to -kb;
- finally if sticky options are not -kb then uses 'cvs
-admin' to
- set the -kb option.
-
-
-
ftp.py
-
- This demonstrates an FTP "bookmark".
- This connects to an ftp site; does a few ftp stuff;
-and then gives the user
- interactive control over the session. In this case
-the "bookmark" is to a
- directory on the OpenBSD ftp server. It puts you in
-the i386 packages
- directory. You can easily modify this for other
-sites.
- This demonstrates the interact() method of Pexpect.
-
-
-
monitor.py
-
- This runs a sequence of commands on a remote host
-using SSH.
- It runs a simple system checks such as uptime and
-free to monitor
- the state of the remote host.
-
-
-
passmass.py
-
- This will login to each given server and change the
-password of the
- given user. This demonstrates scripting logins and
-passwords.
-
-
-
python.py
-
- This starts the python interpreter and prints the
-greeting message backwards.
- It then gives the user iteractive control of Python.
-It's pretty useless!
-
-
-
rippy.py
-
- This is a wizard for mencoder. It greatly simplifies
-the process of
- ripping a DVD to Divx (mpeg4) format. It can
-transcode from any
- video file to another. It has options for resampling
-the audio stream;
- removing interlace artifacts, fitting to a target
-file size, etc.
- There are lots of options, but the process is simple
-and easy to use.
-
-
-
sshls.py
-
- This lists a directory on a remote machine.
-
-
ssh_tunnel.py
-
- This starts an SSH tunnel to a remote machine. It
-monitors the connection
- and restarts the tunnel if it goes down.
-
-
uptime.py
-
- This will run the uptime command and parse the
-output into variables.
- This demonstrates using a single regular expression
-to match the output
- of a command and capturing different variable in
-match groups.
- The grouping regular expression handles a wide variety of different
-uptime formats.
-
Pexpect version 2.4
-a Pure Python Expect-like module
-
-
-
-
Pexpect makes Python a better tool for controlling other
-applications.
-
Pexpect is a pure Python module for spawning child applications;
-controlling them; and responding to expected patterns in their output.
-Pexpect works like Don Libes' Expect. Pexpect allows your script to
-spawn a child application and control it as if a human were typing
-commands.
-
Pexpect can be used for automating interactive applications such as
-ssh, ftp, passwd, telnet, etc. It can be used to a automate setup
-scripts for duplicating software package installations on different
-servers. It can be used for automated software testing. Pexpect is in
-the spirit of Don Libes' Expect, but Pexpect is pure Python. Unlike
-other Expect-like modules for Python, Pexpect does not require TCL or
-Expect nor does it require C extensions to be compiled. It should work
-on any platform that supports the standard Python pty module. The
-Pexpect interface was designed to be easy to use.
-
-
-
-
Send questions to:
-
-
-
-
-
-
License: MIT style
-
-Free, open source, and all that good stuff.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Pexpect Copyright (c) 2008 Noah Spurrier
-http://pexpect.sourceforge.net/
-
Download the
-current version here from the SourceForge site. Grab the current Pexpect tarball.
-
-
Installing Pexpect
-
The Pexpect tarball is a standard Python Distutil distribution.
-
-
download pexpect-2.4.tar.gz
-
tar zxf pexpect-2.4.tar.gz
-
cd pexpect-2.4
-
python setup.py installdo this as root
-
-
Examples
-
-Under the pexpect-2.4 directory you should find
-the examples directory.
-This is the best way to learn to use Pexpect.
-See the descriptions of Pexpect Examples.
-
-
API Documentation
-
-
-pexpect This is the main module that you want.
-pxssh Pexpect SSH is an extension of 'pexpect.spawn' that specializes in SSH.
-
-the following are experimental extensions to Pexpect
-
-fdpexpect fdpexpect extension of 'pexpect.spawn' that uses an open file descriptor.
-SCREEN This represents a virtual 'screen'.
-ANSI This parses ANSI/VT-100 terminal escape codes.
-FSM This is a finite state machine used by ANSI.
-
-
-
-
Project Status
-
Automated pyunit tests reach over 80%
-code coverage on pexpect.py. I regularly test on Linux and BSD
-platforms. I try to test on Solaris and Irix.
-
-
-
Requirements for use of Pexpect
-
Python
-
-
Pexpect was written and tested with Python 2.4. It should work on
-earlier versions that have the pty module. I
-sometimes even manually test it with Python 1.5.2, but I can't easily
-run the PyUnit test framework against Python 1.5.2, so I have less
-confidence in Pexpect on Python 1.5.2.
-
-
pty module
-
-
Any POSIX system (UNIX) with a working pty
-module should be able to run Pexpect. The pty
-module is part of the Standard Python Library, so if you are running on
-a POSIX system you should have it. The pty
-module does not run the same on all platforms. It should be solid on Linux
-and BSD systems. I have taken effort to try to smooth the wrinkles out of the different platforms. To learn more
-about the wrinkles see Bugs and Testing.
-
-
Pexpect does not currently work on the standard Windows Python (see
-the pty requirement); however, it seems to work fine using Cygwin. It is possible to build
-something like a pty for Windows, but it would have to use a different
-technique that I am still investigating. I know it's possible because
-Libes' Expect was ported to Windows. If you have any ideas or
-skills to contribute in this area then I would really appreciate some
-tips on how to approach this problem.
-
-
Overview
-
Pexpect can be used for automating interactive applications such as
-ssh, ftp, mencoder, passwd, etc. The Pexpect interface was designed to be
-easy to use. Here is an example of Pexpect in action:
-
-
# This connects to the openbsd ftp site and # downloads the recursive directory listing. import pexpect child = pexpect.spawn ('ftp ftp.openbsd.org') child.expect ('Name .*: ') child.sendline ('anonymous') child.expect ('Password:') child.sendline ('noah@example.com') child.expect ('ftp> ') child.sendline ('cd pub') child.expect('ftp> ') child.sendline ('get ls-lR.gz') child.expect('ftp> ') child.sendline ('bye')
-
-
Obviously you could write an ftp client using Python's own ftplib module, but this is just a demonstration.
-You can use this technique with any application. This is especially
-handy if you are writing automated test tools.
-
-
There are two important methods in Pexpect -- expect()
-and send() (or sendline()
-which is like send() with a linefeed).
-The expect() method waits for the child application
-to return a given string. The string you specify is a regular expression, so
-you can match complicated patterns. The send() method
-writes a string to the child application. From the child's point of
-view it looks just like someone typed the text from a terminal. After
-each call to expect() the before and after
-properties will be set to the text printed by child application. The before property will contain all text up to
-the expected string pattern. The after string
-will contain the text that was matched by the expected pattern.
-The match property is set to the re MatchObject.
-
-
-
An example of Pexpect in action may make things more clear. This example uses
-ftp to login to the OpenBSD site; list files
-in a directory; and then pass interactive control of the ftp session to
-the human user.
-
-
import pexpect child = pexpect.spawn ('ftp ftp.openbsd.org') child.expect ('Name .*: ') child.sendline ('anonymous') child.expect ('Password:') child.sendline ('noah@example.com') child.expect ('ftp> ') child.sendline ('ls /pub/OpenBSD/') child.expect ('ftp> ') print child.before # Print the result of the ls command. child.interact() # Give control of the child to the user.
-
-
Special EOF and TIMEOUT patterns
-
-There are two special patterns to match the End Of File or a Timeout condition.
-You you can pass these patterns to expect().
-These patterns are not regular expressions. Use them like predefined constants.
-
-
If the child has died and you have read all the child's output then ordinarily
-expect() will raise an EOF
-exception. You can read everything up to the EOF without generating an
-exception by using the EOF pattern expect(pexpect.EOF).
-In this case everything the child has output will be available in the before property.
-
The pattern given to expect() may be a
-regular expression or it may also be a list of regular expressions.
-This allows you to match multiple optional responses. The expect()
-method returns the index of the pattern that was matched. For example,
-say you wanted to login to a server. After entering a password you
-could get various responses from the server -- your password could be
-rejected; or you could be allowed in and asked for your terminal type;
-or you could be let right in and given a command prompt. The following
-code fragment gives an example of this:
-
-
child.expect('password:') child.sendline (my_secret_password) # We expect any of these three patterns... i = child.expect (['Permission denied', 'Terminal type', '[#\$] ']) if i==0: print 'Permission denied on host. Can't login' child.kill(0) elif i==2: print 'Login OK... need to send terminal type.' child.sendline('vt100') child.expect ('[#\$] ') elif i==3: print 'Login OK.' print 'Shell command prompt', child.after
-
-
If nothing matches an expected pattern then expect will eventually
-raise a TIMEOUT exception. The default time is 30 seconds, but you can
-change this by passing a timeout argument to expect():
-
-
# Wait no more than 2 minutes (120 seconds) for password prompt. child.expect('password:', timeout=120)
-
-
Find the end of line -- CR/LF conventions
-Matching at the end of a line can be tricky
-$ regex pattern is useless.
-
-
Pexpect matches regular expressions a little differently than what
-you might be used to.
-
-
The $ pattern for end of line match is useless.
-The $ matches the end of string, but Pexpect reads from the child
-one character at a time, so each character looks like the end of a line.
-Pexpect can't do a look-ahead into the child's output stream.
-In general you would have this situation when using regular expressions
-with any stream.
-Note, pexpect does have an internal buffer, so reads are faster
-than one character at a time, but from the user's perspective the regex
-patterns test happens one character at a time.
-
The best way to match the end of a line is to look for the
-newline: "\r\n" (CR/LF). Yes, that does appear to be DOS-style.
-It may surprise some UNIX people to learn that terminal TTY device drivers
-(dumb, vt100, ANSI, xterm, etc.) all use the CR/LF combination to signify
-the end of line. Pexpect uses a Pseudo-TTY device to talk to the child application, so
-when the child app prints "\n" you actually see "\r\n".
-
-
UNIX uses just linefeeds to end lines of text, but not when it
-comes to TTY devices! TTY devices are more like the Windows world.
-Each line of text end with a CR/LF combination. When you intercept data
-from a UNIX command from a TTY device you will find that the TTY device
-outputs a CR/LF combination. A UNIX command may only write a linefeed
-(\n), but the TTY device driver converts it to CR/LF. This means that
-your terminal will see lines end with CR/LF (hex 0D 0A).
-Since Pexpect emulates a terminal, to match ends of lines you have to
-expect the CR/LF combination.
-
-
child.expect ('\r\n')
-
-
If you just need to skip past a new line then expect
-('\n') by itself will work, but if you are expecting a specific
-pattern before the end of line then you need to explicitly look for the
-\r. For example the following expects a word at the end of a line:
-
-
child.expect ('\w+\r\n')
-
-
But the following would both fail:
-
-
child.expect ('\w+\n')
-
-
And as explained before, trying to use '$' to match the end of line
-would not work either:
-
-
child.expect ('\w+$')
-
-
So if you need to explicitly look for the END OF LINE, you want to
-look for the CR/LF combination -- not just the LF and not the $ pattern.
-
This problem is not limited to Pexpect. This problem happens any
-time you try to perform a regular expression match on a stream. Regular
-expressions need to look ahead. With a stream it is hard to look ahead
-because the process generating the stream may not be finished. There is no
-way to know if the process has paused momentarily or is finished and
-waiting for you. Pexpect must implicitly always
-do a NON greedy match (minimal) at the end of a input {### already said
-this}.
-
Pexpect compiles all regular expressions with the DOTALL flag. With
-the DOTALL flag a "." will match a newline. See the Python documentation
-
Beware of + and * at the end of input.
-
Remember that any time you try to match a pattern that needs
-look-ahead that you will always get a minimal match (non greedy). For
-example, the following will always return just one character:
-
-
child.expect ('.+')
-
-
This example will match successfully, but will always return no
-characters:
-
-
child.expect ('.*')
-
-
Generally any star * expression will match as little as possible
-
One thing you can do is to try to force a non-ambiguous character at
-the end of your \d+ pattern. Expect that
-character to delimit the string. For example, you might try making the
-end of your pattrn be \D+ instead of \D*. That means number digits alone would not
-satisfy the (\d+) pattern. You would need
-some number(s) and at least one \D at the
-end.
-
Matching groups
-
You can group regular expression using parenthesis. After a match,
-the match parameter of the spawn object will
-contain the Python Match object.
-
Examples
-
Using "match" and groups...
-
Debugging
-
If you get the string value of a pexpect.spawn object you will get
-lots of useful debugging information. For debugging it's very useful to
-use the following pattern:
It is also useful to log the child's input and out to a file or the
-screen. The following will turn on logging and send output to stdout
-(the screen).
-
Note that two flavors of EOF Exception may be thrown. They are
-virtually identical except for the message string. For practical
-purposes you should have no need to distinguish between them, but they
-do give a little extra information about what type of platform you are
-running. The two messages are:
-
-
End Of File (EOF) in read(). Exception style platform.
-
End Of File (EOF) in read(). Empty string style
-platform.
-
-
Some UNIX platforms will throw an exception when you try to read
-from a file descriptor in the EOF state. Other UNIX platforms instead
-quietly return an empty string to indicate that the EOF state has been
-reached.
-
Expecting EOF
-
If you wish to read up to the end of the child's output without
-generating an EOF exception then use the expect(pexpect.EOF) method.
-
TIMEOUT
-
The expect() and read()
-methods will also timeout if the child does not generate any output for
-a given amount of time. If this happens they will raise a TIMEOUT exception. You can have these method
-ignore a timeout and block indefinitely by passing None for the timeout
-parameter.
-
-
child.expect(pexpect.EOF, timeout=None)
-
-
-
FAQ
-
Q: Why don't shell pipe and redirect (| and >) work when I
-spawn a command?
-
-
-A: Remember that Pexpect does NOT interpret shell meta characters such as
-redirect, pipe, or wild cards (>, |, or *). That's done by a shell not the
-command you are spawning. This is a common mistake. If you want to run a
-command and pipe it through another command then you must also start a shell.
-For example:
-
-
-
-The second form of spawn (where you pass a list of arguments) is useful in
-situations where you wish to spawn a command and pass it its own argument list.
-This can make syntax more clear. For example, the following is equivalent to
-the previous example:
-
-
A: Yes, there are several of them. They usually require you to
-compile C. I wanted something that was pure Python and preferably a
-single module that was simple to install. I also wanted something that
-was easy to use. This pure Python expect only recently became possible
-with the introduction of the pty module in the standard Python library.
-Previously C extensions were required.
-
-
Q: The before and after properties sound weird.
-
Originally I was going to model Pexpect more after Expect, but then
-I found that I could never remember how to get the context of the stuff
-I was trying to parse. I hate having to read my own documentation. I
-decided that it was easier for me to remember what before and after
-was. It just so happens that this is how the -B and -A options in grep
-works, so that made it even easier for me to remember. Whatever makes
-my life easier is what's best.
-
-
Q: Why not just use Expect?
-
A: I love it. It's great. I has bailed me out of some real jams, but
-I wanted something that would do 90% of what I need from Expect; be 10%
-of the size; and allow me to write my code in Python instead of TCL.
-Pexpect is not nearly as big as Expect, but Pexpect does everything I
-have ever used Expect for.
-
-
-
Q: Why not just use a pipe (popen())?
-
A: A pipe works fine for getting the output to non-interactive
-programs. If you just want to get the output from ls,
-uname, or ping
-then this works. Pipes do not work very well for interactive programs
-and pipes will almost certainly fail for most applications that ask for
-passwords such as telnet, ftp, or ssh.
-
There are two reasons for this.
-
First an application may bypass stdout and print directly to its
-controlling TTY. Something like SSH will do this when it asks you for a
-password. This is why you cannot redirect the password prompt because
-it does not go through stdout or stderr.
-
The second reason is because most applications are built using the C
-Standard IO Library (anything that uses #include
-<stdio.h>). One of the features of the stdio library is
-that it buffers all input and output. Normally output is line
-buffered when a program is printing to a TTY (your terminal
-screen). Every time the program prints a line-feed the currently
-buffered data will get printed to your screen. The problem comes when
-you connect a pipe. The stdio library is smart and can tell that it is
-printing to a pipe instead of a TTY. In that case it switches from line
-buffer mode to block buffered. In this mode the
-currently buffered data is flushed when the buffer is full. This causes
-most interactive programs to deadlock. Block buffering is more
-efficient when writing to disks and pipes. Take the situation where a
-program prints a message "Enter your user name:\n" and then waits for
-you type type something. In block buffered mode, the stdio library will
-not put the message into the pipe even though a linefeed is printed.
-The result is that you never receive the message, yet the child
-application will sit and wait for you to type a response. Don't confuse
-the stdio lib's buffer with the pipe's buffer. The pipe buffer is
-another area that can cause problems. You could flush the input side of
-a pipe, whereas you have no control over the stdio library buffer.
-
More information: the Standard IO library has three states for a
-FILE *. These are: _IOFBF for block buffered; _IOLBF for line buffered;
-and _IONBF for unbuffered. The STDIO lib will use block buffering when
-talking to a block file descriptor such as a pipe. This is usually not
-helpful for interactive programs. Short of recompiling your program to
-include fflush() everywhere or recompiling a custom stdio library there
-is not much a controlling application can do about this if talking over
-a pipe.
-
The program may have put data in its output that remains unflushed
-because the output buffer is not full; then the program will go and
-deadlock while waiting for input -- because you never send it any
-because you are still waiting for its output (still stuck in the
-STDIO's output buffer).
-
The answer is to use a pseudo-tty. A TTY device will force line
-buffering (as opposed to block buffering). Line buffering means that
-you will get each line when the child program sends a line feed. This
-corresponds to the way most interactive programs operate -- send a line
-of output then wait for a line of input.
-
I put "answer" in quotes because it's ugly solution and because
-there is no POSIX standard for pseudo-TTY devices (even though they
-have a TTY standard...). What would make more sense to me would be to
-have some way to set a mode on a file descriptor so that it will tell
-the STDIO to be line-buffered. I have investigated, and I don't think
-there is a way to set the buffered state of a child process. The STDIO
-Library does not maintain any external state in the kernel or whatnot,
-so I don't think there is any way for you to alter it. I'm not quite
-sure how this line-buffered/block-buffered state change happens
-internally in the STDIO library. I think the STDIO lib looks at the
-file descriptor and decides to change behavior based on whether it's a
-TTY or a block file (see isatty()).
-
I hope that this qualifies as helpful.
-
-
Don't use a pipe to control another application...
-
Pexpect may seem similar to os.popen() or
-commands module. The main difference is that
-Pexpect (like Expect) uses a pseudo-TTY to talk to the child
-application. Most applications do no work well through the system()
-call or through pipes. And probably all applications that ask a user to
-type in a password will fail. These applications bypass the stdin and
-read directly from the TTY device. Many applications do not explicitly
-flush their output buffers. This causes deadlocks if you try to control
-an interactive application using a pipe. What happens is that most UNIX
-applications use the stdio (#include <stdio.h>) for input and
-output. The stdio library behaves differently depending on where the
-output is going. There is no way to control this behavior from the
-client end.
-
-
-
Q: Can I do screen scraping with this thing?
-
A: That depends. If your application just does line-oriented output
-then this is easy. If it does screen-oriented output then it may work,
-but it could be hard. For example, trying to scrape data from the 'top'
-command would be hard. The top command repaints the text window.
-
I am working on an ANSI / VT100 terminal emulator that will have
-methods to get characters from an arbitrary X,Y coordinate of the
-virtual screen. It works and you can play with it, but I have no
-working examples at this time.
-
-
Bugs
-
Threads
-
On Linux (RH 8) you cannot spawn a child from a different thread and
-pass the handle back to a worker thread. The child is successfully
-spawned but you can't interact with it. The only way to make it work is
-to spawn and interact with the child all in the same thread. [Adam
-Kerrison]
-
Timing issue with send() and sendline()
-
This problem has been addressed and should not effect most users.
-
It is sometimes possible to read an echo of the string sent with send() and sendline().
-If you call sendline() and then immediately
-call readline() you may get part of your
-output echoed back. You may read back what you just wrote even if the
-child application does not explicitly echo it. Timing is critical. This
-could be a security issue when talking to an application that asks for
-a password; otherwise, this does not seem like a big deal. But why
-do TTYs do this?
-
People usually report this when they are trying to control SSH or
-some other login. For example, if your code looks something like this:
-1. SSH prints "password:" prompt to the user.
-2. SSH turns off echo on the TTY device.
-3. SSH waits for user to enter a password.
-
-When scripting with Pexpect what can happen is that Pexpect will response to the "password:" prompt
-before SSH has had time to turn off TTY echo. In other words, Pexpect sends the password between
-steps 1. and 2., so the password gets echoed back to the TTY. I would call this an SSH bug.
-
-
-Pexpect now automatically adds a short delay before sending data to a child process.
-This more closely mimics what happens in the usual human-to-app interaction.
-The delay can be tuned with the 'delaybeforesend' attribute of the spawn class.
-In general, this fixes the problem for everyone and so this should not be an issue
-for most users. For some applications you might with to turn it off.
- child = pexpect.spawn ("ssh user@example.com")
- child.delaybeforesend = 0
-
-
-
-
Try changing it to look like the following. I know that this fix
-does not look correct, but it works. I have not figured out exactly
-what is happening. You would think that the sleep should be after the
-sendline(). The fact that the sleep helps when it's between the
-expect() and the sendline() must be a clue.
Reading the state of isalive() immediately after a child exits may
-sometimes return 1. This is a race condition. The child has closed its
-file descriptor, but has not yet fully exited before Pexpect's
-isalive() executes. Addings a slight delay before the isalive() will
-help. In the following example isalive()
-sometimes returns 1:
So far I have seen this only on older versions of Apple's MacOS X.
-If the child application quits it may not flush its output buffer. This
-means that your Pexpect application will receive an EOF even though it
-should have received a little more data before the child died. This is
-not generally a problem when talking to interactive child applications.
-One example where it is a problem is when trying to read output from a
-program like 'ls'. You may receive most of
-the directory listing, but the last few lines will get lost before you
-receive an EOF. The reason for this is that 'ls'
-runs; completes its task; and then exits. The buffer is not flushed
-before exit so the last few lines are lost. The following example
-demonstrates the problem:
Pexpect does not yet work perfectly on Solaris.
-One common problem is that SSH sometimes will not allow TTY password
-authentication. For example, you may expect SSH to ask you for a
-password using code like this:
-
-This means that SSH thinks it can't access the TTY to ask you for your
-password.
-The only solution I have found is to use public key authentication with
-SSH.
-This bypasses the need for a password. I'm not happy with this
-solution.
-The problem is due to poor support for Solaris Pseudo TTYs in the
-Python
-Standard Library.
-
-
CHANGES
-
Current Release
-
Fixed OSError exception when a pexpect object is cleaned up.
-Previously you might have seen this exception:
-
-
Exception exceptions.OSError: (10, 'No child processes') in <bound method spawn.__del__ of <pexpect.spawn instance at 0xd248c>> ignored
-
-
You should not see that anymore. Thanks to Michael Surette.
-
Added support for buffering reads. This greatly improves speed when
-trying to match long output from a child process. When you create an
-instance of the spawn object you can then set a buffer size. For now
-you MUST do the following to turn on buffering -- it may be on by
-default in future version.
I made a subtle change to the way TIMEOUT and EOF exceptions behave.
-Previously you could either expect these states in which case pexpect
-will not raise an exception, or you could just let pexpect raise an
-exception when these states were encountered. If you expected the
-states then the 'before' property was set to everything before the
-state was encountered, but if you let pexpect raise the exception then
-'before' was not set. Now the 'before' property will get set either way
-you choose to handle these states.
-
Older changes...
-
The spawn object now provides iterators for a file-like interface.
-This makes Pexpect a more complete file-like object. You can now write
-code like this:
-
-
child = pexpect.spawn ('ls -l') for line in child: print line
-
-
I added the attribute exitstatus. This
-will give the exit code returned by the child process. This will be set
-to None while the child is still alive. When
-isalive() returns 0 then exitstatus
-will be set.
-
I made a few more tweaks to isalive() so
-that it will operate more consistently on different platforms. Solaris
-is the most difficult to support.
-
-
You can now put TIMEOUT in a list of
-expected patterns. This is just like putting EOF
-in the pattern list. Expecting for a TIMEOUT
-may not be used as often as EOF, but this
-makes Pexpect more consitent.
-
Thanks to a suggestion and sample code from Chad J. Schroeder I
-added the ability for Pexpect to operate on a file descriptor that is
-already open. This means that Pexpect can be used to control streams
-such as those from serial port devices. Now you just pass the integer
-file descriptor as the "command" when contsructing a spawn open. For
-example on a Linux box with a modem on ttyS1:
-
-
fd = os.open("/dev/ttyS1", os.O_RDWR|os.O_NONBLOCK|os.O_NOCTTY) m = pexpect.spawn(fd) # Note integer fd is used instead of usual string. m.send("+++") # Escape sequence m.send("ATZ0\r") # Reset modem to profile 0 rval = m.expect(["OK", "ERROR"])
-
-
Pexpect now tests itself on Compile Farm!
-
I wrote a nice script that uses ssh to connect to each machine on
-Source Forge's Compile Farm and then run the testall.py script for each
-platform. The result of the test is then recorded for each platform.
-Now it's easy to run regression tests across multiple platforms.
-
Pexpect is a file-like object
-
The spawn object now provides a file-like interface. It
-supports most of the methods and attributes defined for Python File
-Objects.
-
I changed write and writelines() so that they no longer return a
-value. Use send() if you need that functionality. I did this to make
-the Spawn object more closely match a file-like object.
-
read() was renamed to read_nonblocking(). I added a new read()
-method that matches file-like object interface. In general, you should
-not notice the difference except that read() no longer allows you to
-directly set the timeout value. I hope this will not effect any
-existing code. Switching to read_nonblocking() should fix existing code.
-
I changed the name of set_echo() to setecho().
-
I changed the name of send_eof() to sendeof().
-
I modified kill() so that it checks to
-make sure the pid isalive().
-
I modified spawn() (really called from __spawn())so that it does not raise an expection
-if setwinsize() fails. Some platforms such
-as Cygwin do not like setwinsize. This was a constant problem and since
-it is not a critical feature I decided to just silence the error.
-Normally I don't like to do that, but in this case I'm making an
-exception.
-
Added a method close() that does what you
-think. It closes the file descriptor of the child application. It makes
-no attempt to actually kill the child or wait for its status.
-
Add variables __version__ and __revision__ (from cvs) to the pexpect modules.
-This is mainly helpful to me so that I can make sure that I'm testing
-with the right version instead of one already installed.
-
Logging changes
-
-
log_open() and log_close()
-have been removed. Now use setlog(). The setlog() method takes a file object. This is far
-more flexible than the previous log method. Each time data is written
-to the file object it will be flushed. To turn logging off simply call setlog() with None.
-
-
isalive changes
-
-
I renamed the isAlive() method to isalive() to match the more typical naming style
-in Python. Also the technique used to detect child process status has
-been drastically modified. Previously I did some funky stuff with
-signals which caused indigestion in other Python modules on some
-platforms. It's was a big headache. It still is, but I think it works
-better now.
-
-
attribute name changes
-
-
The names of some attributes have been changed. This effects the
-names of the attributes that are set after called the expect() method.
-
-
-
-
NEW NAME
-
OLD NAME
-
-
-
before
- Everything before the match.
-
before
-
-
-
after
- Everything after and including the first character of the
-match
-
matched
-
-
-
match
- This is the re MatchObject from the match.
-You can get groups() from this.
-See 'uptime.py' in the examples tar ball.
-
New -- Did not exist
-
-
-
-
-
EOF changes
-
-
The expect_eof() method is gone. You
-can now simply use the expect() method to
-look for EOF.
Pexpect version VERSION
-a Pure Python Expect-like module
-
-
-
-
Pexpect makes Python a better tool for controlling other
-applications.
-
Pexpect is a pure Python module for spawning child applications;
-controlling them; and responding to expected patterns in their output.
-Pexpect works like Don Libes' Expect. Pexpect allows your script to
-spawn a child application and control it as if a human were typing
-commands.
-
Pexpect can be used for automating interactive applications such as
-ssh, ftp, passwd, telnet, etc. It can be used to a automate setup
-scripts for duplicating software package installations on different
-servers. It can be used for automated software testing. Pexpect is in
-the spirit of Don Libes' Expect, but Pexpect is pure Python. Unlike
-other Expect-like modules for Python, Pexpect does not require TCL or
-Expect nor does it require C extensions to be compiled. It should work
-on any platform that supports the standard Python pty module. The
-Pexpect interface was designed to be easy to use.
-
-
-
-
Send questions to:
-
-
-
-
-
-
License: MIT style
-
-Free, open source, and all that good stuff.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Pexpect Copyright (c) 2008 Noah Spurrier
-http://pexpect.sourceforge.net/
-
Download the
-current version here from the SourceForge site. Grab the current Pexpect tarball.
-
-
Installing Pexpect
-
The Pexpect tarball is a standard Python Distutil distribution.
-
-
download pexpect-VERSION.tar.gz
-
tar zxf pexpect-VERSION.tar.gz
-
cd pexpect-VERSION
-
python setup.py installdo this as root
-
-
Examples
-
-Under the pexpect-VERSION directory you should find
-the examples directory.
-This is the best way to learn to use Pexpect.
-See the descriptions of Pexpect Examples.
-
-
API Documentation
-
-
-pexpect This is the main module that you want.
-pxssh Pexpect SSH is an extension of 'pexpect.spawn' that specializes in SSH.
-
-the following are experimental extensions to Pexpect
-
-fdpexpect fdpexpect extension of 'pexpect.spawn' that uses an open file descriptor.
-SCREEN This represents a virtual 'screen'.
-ANSI This parses ANSI/VT-100 terminal escape codes.
-FSM This is a finite state machine used by ANSI.
-
-
-
-
Project Status
-
Automated pyunit tests reach over 80%
-code coverage on pexpect.py. I regularly test on Linux and BSD
-platforms. I try to test on Solaris and Irix.
-
-
-
Requirements for use of Pexpect
-
Python
-
-
Pexpect was written and tested with Python 2.4. It should work on
-earlier versions that have the pty module. I
-sometimes even manually test it with Python 1.5.2, but I can't easily
-run the PyUnit test framework against Python 1.5.2, so I have less
-confidence in Pexpect on Python 1.5.2.
-
-
pty module
-
-
Any POSIX system (UNIX) with a working pty
-module should be able to run Pexpect. The pty
-module is part of the Standard Python Library, so if you are running on
-a POSIX system you should have it. The pty
-module does not run the same on all platforms. It should be solid on Linux
-and BSD systems. I have taken effort to try to smooth the wrinkles out of the different platforms. To learn more
-about the wrinkles see Bugs and Testing.
-
-
Pexpect does not currently work on the standard Windows Python (see
-the pty requirement); however, it seems to work fine using Cygwin. It is possible to build
-something like a pty for Windows, but it would have to use a different
-technique that I am still investigating. I know it's possible because
-Libes' Expect was ported to Windows. If you have any ideas or
-skills to contribute in this area then I would really appreciate some
-tips on how to approach this problem.
-
-
Overview
-
Pexpect can be used for automating interactive applications such as
-ssh, ftp, mencoder, passwd, etc. The Pexpect interface was designed to be
-easy to use. Here is an example of Pexpect in action:
-
-
# This connects to the openbsd ftp site and # downloads the recursive directory listing. import pexpect child = pexpect.spawn ('ftp ftp.openbsd.org') child.expect ('Name .*: ') child.sendline ('anonymous') child.expect ('Password:') child.sendline ('noah@example.com') child.expect ('ftp> ') child.sendline ('cd pub') child.expect('ftp> ') child.sendline ('get ls-lR.gz') child.expect('ftp> ') child.sendline ('bye')
-
-
Obviously you could write an ftp client using Python's own ftplib module, but this is just a demonstration.
-You can use this technique with any application. This is especially
-handy if you are writing automated test tools.
-
-
There are two important methods in Pexpect -- expect()
-and send() (or sendline()
-which is like send() with a linefeed).
-The expect() method waits for the child application
-to return a given string. The string you specify is a regular expression, so
-you can match complicated patterns. The send() method
-writes a string to the child application. From the child's point of
-view it looks just like someone typed the text from a terminal. After
-each call to expect() the before and after
-properties will be set to the text printed by child application. The before property will contain all text up to
-the expected string pattern. The after string
-will contain the text that was matched by the expected pattern.
-The match property is set to the re MatchObject.
-
-
-
An example of Pexpect in action may make things more clear. This example uses
-ftp to login to the OpenBSD site; list files
-in a directory; and then pass interactive control of the ftp session to
-the human user.
-
-
import pexpect child = pexpect.spawn ('ftp ftp.openbsd.org') child.expect ('Name .*: ') child.sendline ('anonymous') child.expect ('Password:') child.sendline ('noah@example.com') child.expect ('ftp> ') child.sendline ('ls /pub/OpenBSD/') child.expect ('ftp> ') print child.before # Print the result of the ls command. child.interact() # Give control of the child to the user.
-
-
Special EOF and TIMEOUT patterns
-
-There are two special patterns to match the End Of File or a Timeout condition.
-You you can pass these patterns to expect().
-These patterns are not regular expressions. Use them like predefined constants.
-
-
If the child has died and you have read all the child's output then ordinarily
-expect() will raise an EOF
-exception. You can read everything up to the EOF without generating an
-exception by using the EOF pattern expect(pexpect.EOF).
-In this case everything the child has output will be available in the before property.
-
The pattern given to expect() may be a
-regular expression or it may also be a list of regular expressions.
-This allows you to match multiple optional responses. The expect()
-method returns the index of the pattern that was matched. For example,
-say you wanted to login to a server. After entering a password you
-could get various responses from the server -- your password could be
-rejected; or you could be allowed in and asked for your terminal type;
-or you could be let right in and given a command prompt. The following
-code fragment gives an example of this:
-
-
child.expect('password:') child.sendline (my_secret_password) # We expect any of these three patterns... i = child.expect (['Permission denied', 'Terminal type', '[#\$] ']) if i==0: print 'Permission denied on host. Can't login' child.kill(0) elif i==2: print 'Login OK... need to send terminal type.' child.sendline('vt100') child.expect ('[#\$] ') elif i==3: print 'Login OK.' print 'Shell command prompt', child.after
-
-
If nothing matches an expected pattern then expect will eventually
-raise a TIMEOUT exception. The default time is 30 seconds, but you can
-change this by passing a timeout argument to expect():
-
-
# Wait no more than 2 minutes (120 seconds) for password prompt. child.expect('password:', timeout=120)
-
-
Find the end of line -- CR/LF conventions
-Matching at the end of a line can be tricky
-$ regex pattern is useless.
-
-
Pexpect matches regular expressions a little differently than what
-you might be used to.
-
-
The $ pattern for end of line match is useless.
-The $ matches the end of string, but Pexpect reads from the child
-one character at a time, so each character looks like the end of a line.
-Pexpect can't do a look-ahead into the child's output stream.
-In general you would have this situation when using regular expressions
-with any stream.
-Note, pexpect does have an internal buffer, so reads are faster
-than one character at a time, but from the user's perspective the regex
-patterns test happens one character at a time.
-
The best way to match the end of a line is to look for the
-newline: "\r\n" (CR/LF). Yes, that does appear to be DOS-style.
-It may surprise some UNIX people to learn that terminal TTY device drivers
-(dumb, vt100, ANSI, xterm, etc.) all use the CR/LF combination to signify
-the end of line. Pexpect uses a Pseudo-TTY device to talk to the child application, so
-when the child app prints "\n" you actually see "\r\n".
-
-
UNIX uses just linefeeds to end lines of text, but not when it
-comes to TTY devices! TTY devices are more like the Windows world.
-Each line of text end with a CR/LF combination. When you intercept data
-from a UNIX command from a TTY device you will find that the TTY device
-outputs a CR/LF combination. A UNIX command may only write a linefeed
-(\n), but the TTY device driver converts it to CR/LF. This means that
-your terminal will see lines end with CR/LF (hex 0D 0A).
-Since Pexpect emulates a terminal, to match ends of lines you have to
-expect the CR/LF combination.
-
-
child.expect ('\r\n')
-
-
If you just need to skip past a new line then expect
-('\n') by itself will work, but if you are expecting a specific
-pattern before the end of line then you need to explicitly look for the
-\r. For example the following expects a word at the end of a line:
-
-
child.expect ('\w+\r\n')
-
-
But the following would both fail:
-
-
child.expect ('\w+\n')
-
-
And as explained before, trying to use '$' to match the end of line
-would not work either:
-
-
child.expect ('\w+$')
-
-
So if you need to explicitly look for the END OF LINE, you want to
-look for the CR/LF combination -- not just the LF and not the $ pattern.
-
This problem is not limited to Pexpect. This problem happens any
-time you try to perform a regular expression match on a stream. Regular
-expressions need to look ahead. With a stream it is hard to look ahead
-because the process generating the stream may not be finished. There is no
-way to know if the process has paused momentarily or is finished and
-waiting for you. Pexpect must implicitly always
-do a NON greedy match (minimal) at the end of a input {### already said
-this}.
-
Pexpect compiles all regular expressions with the DOTALL flag. With
-the DOTALL flag a "." will match a newline. See the Python documentation
-
Beware of + and * at the end of input.
-
Remember that any time you try to match a pattern that needs
-look-ahead that you will always get a minimal match (non greedy). For
-example, the following will always return just one character:
-
-
child.expect ('.+')
-
-
This example will match successfully, but will always return no
-characters:
-
-
child.expect ('.*')
-
-
Generally any star * expression will match as little as possible
-
One thing you can do is to try to force a non-ambiguous character at
-the end of your \d+ pattern. Expect that
-character to delimit the string. For example, you might try making the
-end of your pattrn be \D+ instead of \D*. That means number digits alone would not
-satisfy the (\d+) pattern. You would need
-some number(s) and at least one \D at the
-end.
-
Matching groups
-
You can group regular expression using parenthesis. After a match,
-the match parameter of the spawn object will
-contain the Python Match object.
-
Examples
-
Using "match" and groups...
-
Debugging
-
If you get the string value of a pexpect.spawn object you will get
-lots of useful debugging information. For debugging it's very useful to
-use the following pattern:
It is also useful to log the child's input and out to a file or the
-screen. The following will turn on logging and send output to stdout
-(the screen).
-
Note that two flavors of EOF Exception may be thrown. They are
-virtually identical except for the message string. For practical
-purposes you should have no need to distinguish between them, but they
-do give a little extra information about what type of platform you are
-running. The two messages are:
-
-
End Of File (EOF) in read(). Exception style platform.
-
End Of File (EOF) in read(). Empty string style
-platform.
-
-
Some UNIX platforms will throw an exception when you try to read
-from a file descriptor in the EOF state. Other UNIX platforms instead
-quietly return an empty string to indicate that the EOF state has been
-reached.
-
Expecting EOF
-
If you wish to read up to the end of the child's output without
-generating an EOF exception then use the expect(pexpect.EOF) method.
-
TIMEOUT
-
The expect() and read()
-methods will also timeout if the child does not generate any output for
-a given amount of time. If this happens they will raise a TIMEOUT exception. You can have these method
-ignore a timeout and block indefinitely by passing None for the timeout
-parameter.
-
-
child.expect(pexpect.EOF, timeout=None)
-
-
-
FAQ
-
Q: Why don't shell pipe and redirect (| and >) work when I
-spawn a command?
-
-
-A: Remember that Pexpect does NOT interpret shell meta characters such as
-redirect, pipe, or wild cards (>, |, or *). That's done by a shell not the
-command you are spawning. This is a common mistake. If you want to run a
-command and pipe it through another command then you must also start a shell.
-For example:
-
-
-
-The second form of spawn (where you pass a list of arguments) is useful in
-situations where you wish to spawn a command and pass it its own argument list.
-This can make syntax more clear. For example, the following is equivalent to
-the previous example:
-
-
A: Yes, there are several of them. They usually require you to
-compile C. I wanted something that was pure Python and preferably a
-single module that was simple to install. I also wanted something that
-was easy to use. This pure Python expect only recently became possible
-with the introduction of the pty module in the standard Python library.
-Previously C extensions were required.
-
-
Q: The before and after properties sound weird.
-
Originally I was going to model Pexpect more after Expect, but then
-I found that I could never remember how to get the context of the stuff
-I was trying to parse. I hate having to read my own documentation. I
-decided that it was easier for me to remember what before and after
-was. It just so happens that this is how the -B and -A options in grep
-works, so that made it even easier for me to remember. Whatever makes
-my life easier is what's best.
-
-
Q: Why not just use Expect?
-
A: I love it. It's great. I has bailed me out of some real jams, but
-I wanted something that would do 90% of what I need from Expect; be 10%
-of the size; and allow me to write my code in Python instead of TCL.
-Pexpect is not nearly as big as Expect, but Pexpect does everything I
-have ever used Expect for.
-
-
-
Q: Why not just use a pipe (popen())?
-
A: A pipe works fine for getting the output to non-interactive
-programs. If you just want to get the output from ls,
-uname, or ping
-then this works. Pipes do not work very well for interactive programs
-and pipes will almost certainly fail for most applications that ask for
-passwords such as telnet, ftp, or ssh.
-
There are two reasons for this.
-
First an application may bypass stdout and print directly to its
-controlling TTY. Something like SSH will do this when it asks you for a
-password. This is why you cannot redirect the password prompt because
-it does not go through stdout or stderr.
-
The second reason is because most applications are built using the C
-Standard IO Library (anything that uses #include
-<stdio.h>). One of the features of the stdio library is
-that it buffers all input and output. Normally output is line
-buffered when a program is printing to a TTY (your terminal
-screen). Every time the program prints a line-feed the currently
-buffered data will get printed to your screen. The problem comes when
-you connect a pipe. The stdio library is smart and can tell that it is
-printing to a pipe instead of a TTY. In that case it switches from line
-buffer mode to block buffered. In this mode the
-currently buffered data is flushed when the buffer is full. This causes
-most interactive programs to deadlock. Block buffering is more
-efficient when writing to disks and pipes. Take the situation where a
-program prints a message "Enter your user name:\n" and then waits for
-you type type something. In block buffered mode, the stdio library will
-not put the message into the pipe even though a linefeed is printed.
-The result is that you never receive the message, yet the child
-application will sit and wait for you to type a response. Don't confuse
-the stdio lib's buffer with the pipe's buffer. The pipe buffer is
-another area that can cause problems. You could flush the input side of
-a pipe, whereas you have no control over the stdio library buffer.
-
More information: the Standard IO library has three states for a
-FILE *. These are: _IOFBF for block buffered; _IOLBF for line buffered;
-and _IONBF for unbuffered. The STDIO lib will use block buffering when
-talking to a block file descriptor such as a pipe. This is usually not
-helpful for interactive programs. Short of recompiling your program to
-include fflush() everywhere or recompiling a custom stdio library there
-is not much a controlling application can do about this if talking over
-a pipe.
-
The program may have put data in its output that remains unflushed
-because the output buffer is not full; then the program will go and
-deadlock while waiting for input -- because you never send it any
-because you are still waiting for its output (still stuck in the
-STDIO's output buffer).
-
The answer is to use a pseudo-tty. A TTY device will force line
-buffering (as opposed to block buffering). Line buffering means that
-you will get each line when the child program sends a line feed. This
-corresponds to the way most interactive programs operate -- send a line
-of output then wait for a line of input.
-
I put "answer" in quotes because it's ugly solution and because
-there is no POSIX standard for pseudo-TTY devices (even though they
-have a TTY standard...). What would make more sense to me would be to
-have some way to set a mode on a file descriptor so that it will tell
-the STDIO to be line-buffered. I have investigated, and I don't think
-there is a way to set the buffered state of a child process. The STDIO
-Library does not maintain any external state in the kernel or whatnot,
-so I don't think there is any way for you to alter it. I'm not quite
-sure how this line-buffered/block-buffered state change happens
-internally in the STDIO library. I think the STDIO lib looks at the
-file descriptor and decides to change behavior based on whether it's a
-TTY or a block file (see isatty()).
-
I hope that this qualifies as helpful.
-
-
Don't use a pipe to control another application...
-
Pexpect may seem similar to os.popen() or
-commands module. The main difference is that
-Pexpect (like Expect) uses a pseudo-TTY to talk to the child
-application. Most applications do no work well through the system()
-call or through pipes. And probably all applications that ask a user to
-type in a password will fail. These applications bypass the stdin and
-read directly from the TTY device. Many applications do not explicitly
-flush their output buffers. This causes deadlocks if you try to control
-an interactive application using a pipe. What happens is that most UNIX
-applications use the stdio (#include <stdio.h>) for input and
-output. The stdio library behaves differently depending on where the
-output is going. There is no way to control this behavior from the
-client end.
-
-
-
Q: Can I do screen scraping with this thing?
-
A: That depends. If your application just does line-oriented output
-then this is easy. If it does screen-oriented output then it may work,
-but it could be hard. For example, trying to scrape data from the 'top'
-command would be hard. The top command repaints the text window.
-
I am working on an ANSI / VT100 terminal emulator that will have
-methods to get characters from an arbitrary X,Y coordinate of the
-virtual screen. It works and you can play with it, but I have no
-working examples at this time.
-
-
Bugs
-
Threads
-
On Linux (RH 8) you cannot spawn a child from a different thread and
-pass the handle back to a worker thread. The child is successfully
-spawned but you can't interact with it. The only way to make it work is
-to spawn and interact with the child all in the same thread. [Adam
-Kerrison]
-
Timing issue with send() and sendline()
-
This problem has been addressed and should not effect most users.
-
It is sometimes possible to read an echo of the string sent with send() and sendline().
-If you call sendline() and then immediately
-call readline() you may get part of your
-output echoed back. You may read back what you just wrote even if the
-child application does not explicitly echo it. Timing is critical. This
-could be a security issue when talking to an application that asks for
-a password; otherwise, this does not seem like a big deal. But why
-do TTYs do this?
-
People usually report this when they are trying to control SSH or
-some other login. For example, if your code looks something like this:
-1. SSH prints "password:" prompt to the user.
-2. SSH turns off echo on the TTY device.
-3. SSH waits for user to enter a password.
-
-When scripting with Pexpect what can happen is that Pexpect will response to the "password:" prompt
-before SSH has had time to turn off TTY echo. In other words, Pexpect sends the password between
-steps 1. and 2., so the password gets echoed back to the TTY. I would call this an SSH bug.
-
-
-Pexpect now automatically adds a short delay before sending data to a child process.
-This more closely mimics what happens in the usual human-to-app interaction.
-The delay can be tuned with the 'delaybeforesend' attribute of the spawn class.
-In general, this fixes the problem for everyone and so this should not be an issue
-for most users. For some applications you might with to turn it off.
- child = pexpect.spawn ("ssh user@example.com")
- child.delaybeforesend = 0
-
-
-
-
Try changing it to look like the following. I know that this fix
-does not look correct, but it works. I have not figured out exactly
-what is happening. You would think that the sleep should be after the
-sendline(). The fact that the sleep helps when it's between the
-expect() and the sendline() must be a clue.
Reading the state of isalive() immediately after a child exits may
-sometimes return 1. This is a race condition. The child has closed its
-file descriptor, but has not yet fully exited before Pexpect's
-isalive() executes. Addings a slight delay before the isalive() will
-help. In the following example isalive()
-sometimes returns 1:
So far I have seen this only on older versions of Apple's MacOS X.
-If the child application quits it may not flush its output buffer. This
-means that your Pexpect application will receive an EOF even though it
-should have received a little more data before the child died. This is
-not generally a problem when talking to interactive child applications.
-One example where it is a problem is when trying to read output from a
-program like 'ls'. You may receive most of
-the directory listing, but the last few lines will get lost before you
-receive an EOF. The reason for this is that 'ls'
-runs; completes its task; and then exits. The buffer is not flushed
-before exit so the last few lines are lost. The following example
-demonstrates the problem:
Pexpect does not yet work perfectly on Solaris.
-One common problem is that SSH sometimes will not allow TTY password
-authentication. For example, you may expect SSH to ask you for a
-password using code like this:
-
-This means that SSH thinks it can't access the TTY to ask you for your
-password.
-The only solution I have found is to use public key authentication with
-SSH.
-This bypasses the need for a password. I'm not happy with this
-solution.
-The problem is due to poor support for Solaris Pseudo TTYs in the
-Python
-Standard Library.
-
-
CHANGES
-
Current Release
-
Fixed OSError exception when a pexpect object is cleaned up.
-Previously you might have seen this exception:
-
-
Exception exceptions.OSError: (10, 'No child processes') in <bound method spawn.__del__ of <pexpect.spawn instance at 0xd248c>> ignored
-
-
You should not see that anymore. Thanks to Michael Surette.
-
Added support for buffering reads. This greatly improves speed when
-trying to match long output from a child process. When you create an
-instance of the spawn object you can then set a buffer size. For now
-you MUST do the following to turn on buffering -- it may be on by
-default in future version.
I made a subtle change to the way TIMEOUT and EOF exceptions behave.
-Previously you could either expect these states in which case pexpect
-will not raise an exception, or you could just let pexpect raise an
-exception when these states were encountered. If you expected the
-states then the 'before' property was set to everything before the
-state was encountered, but if you let pexpect raise the exception then
-'before' was not set. Now the 'before' property will get set either way
-you choose to handle these states.
-
Older changes...
-
The spawn object now provides iterators for a file-like interface.
-This makes Pexpect a more complete file-like object. You can now write
-code like this:
-
-
child = pexpect.spawn ('ls -l') for line in child: print line
-
-
I added the attribute exitstatus. This
-will give the exit code returned by the child process. This will be set
-to None while the child is still alive. When
-isalive() returns 0 then exitstatus
-will be set.
-
I made a few more tweaks to isalive() so
-that it will operate more consistently on different platforms. Solaris
-is the most difficult to support.
-
-
You can now put TIMEOUT in a list of
-expected patterns. This is just like putting EOF
-in the pattern list. Expecting for a TIMEOUT
-may not be used as often as EOF, but this
-makes Pexpect more consitent.
-
Thanks to a suggestion and sample code from Chad J. Schroeder I
-added the ability for Pexpect to operate on a file descriptor that is
-already open. This means that Pexpect can be used to control streams
-such as those from serial port devices. Now you just pass the integer
-file descriptor as the "command" when contsructing a spawn open. For
-example on a Linux box with a modem on ttyS1:
-
-
fd = os.open("/dev/ttyS1", os.O_RDWR|os.O_NONBLOCK|os.O_NOCTTY) m = pexpect.spawn(fd) # Note integer fd is used instead of usual string. m.send("+++") # Escape sequence m.send("ATZ0\r") # Reset modem to profile 0 rval = m.expect(["OK", "ERROR"])
-
-
Pexpect now tests itself on Compile Farm!
-
I wrote a nice script that uses ssh to connect to each machine on
-Source Forge's Compile Farm and then run the testall.py script for each
-platform. The result of the test is then recorded for each platform.
-Now it's easy to run regression tests across multiple platforms.
-
Pexpect is a file-like object
-
The spawn object now provides a file-like interface. It
-supports most of the methods and attributes defined for Python File
-Objects.
-
I changed write and writelines() so that they no longer return a
-value. Use send() if you need that functionality. I did this to make
-the Spawn object more closely match a file-like object.
-
read() was renamed to read_nonblocking(). I added a new read()
-method that matches file-like object interface. In general, you should
-not notice the difference except that read() no longer allows you to
-directly set the timeout value. I hope this will not effect any
-existing code. Switching to read_nonblocking() should fix existing code.
-
I changed the name of set_echo() to setecho().
-
I changed the name of send_eof() to sendeof().
-
I modified kill() so that it checks to
-make sure the pid isalive().
-
I modified spawn() (really called from __spawn())so that it does not raise an expection
-if setwinsize() fails. Some platforms such
-as Cygwin do not like setwinsize. This was a constant problem and since
-it is not a critical feature I decided to just silence the error.
-Normally I don't like to do that, but in this case I'm making an
-exception.
-
Added a method close() that does what you
-think. It closes the file descriptor of the child application. It makes
-no attempt to actually kill the child or wait for its status.
-
Add variables __version__ and __revision__ (from cvs) to the pexpect modules.
-This is mainly helpful to me so that I can make sure that I'm testing
-with the right version instead of one already installed.
-
Logging changes
-
-
log_open() and log_close()
-have been removed. Now use setlog(). The setlog() method takes a file object. This is far
-more flexible than the previous log method. Each time data is written
-to the file object it will be flushed. To turn logging off simply call setlog() with None.
-
-
isalive changes
-
-
I renamed the isAlive() method to isalive() to match the more typical naming style
-in Python. Also the technique used to detect child process status has
-been drastically modified. Previously I did some funky stuff with
-signals which caused indigestion in other Python modules on some
-platforms. It's was a big headache. It still is, but I think it works
-better now.
-
-
attribute name changes
-
-
The names of some attributes have been changed. This effects the
-names of the attributes that are set after called the expect() method.
-
-
-
-
NEW NAME
-
OLD NAME
-
-
-
before
- Everything before the match.
-
before
-
-
-
after
- Everything after and including the first character of the
-match
-
matched
-
-
-
match
- This is the re MatchObject from the match.
-You can get groups() from this.
-See 'uptime.py' in the examples tar ball.
-
New -- Did not exist
-
-
-
-
-
EOF changes
-
-
The expect_eof() method is gone. You
-can now simply use the expect() method to
-look for EOF.
-
-
Index: third_party/Python/module/pexpect-2.4/examples/README
===================================================================
--- third_party/Python/module/pexpect-2.4/examples/README
+++ third_party/Python/module/pexpect-2.4/examples/README
@@ -1,72 +0,0 @@
-This directory contains scripts that give examples of using Pexpect.
-
-hive.py
- This script creates SSH connections to a list of hosts that
- you provide. Then you are given a command line prompt. Each
- shell command that you enter is sent to all the hosts. The
- response from each host is collected and printed. For example,
- you could connect to a dozen different machines and reboot
- them all at once.
-
-script.py
- This implements a command similar to the classic BSD "script" command.
- This will start a subshell and log all input and output to a file.
- This demonstrates the interact() method of Pexpect.
-
-fix_cvs_files.py
- This is for cleaning up binary files improperly added to
- CVS. This script scans the given path to find binary files;
- checks with CVS to see if the sticky options are set to -kb;
- finally if sticky options are not -kb then uses 'cvs admin'
- to set the -kb option.
-
-ftp.py
- This demonstrates an FTP "bookmark".
- This connects to an ftp site; does a few ftp commands; and then gives the user
- interactive control over the session. In this case the "bookmark" is to a
- directory on the OpenBSD ftp server. It puts you in the i386 packages
- directory. You can easily modify this for other sites.
- This demonstrates the interact() method of Pexpect.
-
-monitor.py
- This runs a sequence of system status commands on a remote host using SSH.
- It runs a simple system checks such as uptime and free to monitor
- the state of the remote host.
-
-passmass.py
- This will login to a list of hosts and change the password of the
- given user. This demonstrates scripting logins; although, you could
- more easily do this using the pxssh subclass of Pexpect.
- See also the "hive.py" example script for a more general example
- of scripting a collection of servers.
-
-python.py
- This starts the python interpreter and prints the greeting message backwards.
- It then gives the user interactive control of Python. It's pretty useless!
-
-rippy.py
- This is a wizard for mencoder. It greatly simplifies the process of
- ripping a DVD to mpeg4 format (XviD, DivX). It can transcode from any
- video file to another. It has options for resampling the audio stream;
- removing interlace artifacts, fitting to a target file size, etc.
- There are lots of options, but the process is simple and easy to use.
-
-sshls.py
- This lists a directory on a remote machine.
-
-ssh_tunnel.py
- This starts an SSH tunnel to a remote machine. It monitors the connection
- and restarts the tunnel if it goes down.
-
-uptime.py
- This will run the uptime command and parse the output into python variables.
- This demonstrates using a single regular expression to match the output
- of a command and capturing different variable in match groups.
- The regular expression takes into account a wide variety of different
- formats for uptime output.
-
-df.py
- This collects filesystem capacity info using the 'df' command.
- Tuples of filesystem name and percentage are stored in a list.
- A simple report is printed. Filesystems over 95% capacity are highlighted.
-
Index: third_party/Python/module/pexpect-2.4/examples/astat.py
===================================================================
--- third_party/Python/module/pexpect-2.4/examples/astat.py
+++ third_party/Python/module/pexpect-2.4/examples/astat.py
@@ -1,85 +0,0 @@
-#!/usr/bin/env python
-
-"""This runs Apache Status on the remote host and returns the number of requests per second.
-
-./astat.py [-s server_hostname] [-u username] [-p password]
- -s : hostname of the remote server to login to.
- -u : username to user for login.
- -p : Password to user for login.
-
-Example:
- This will print information about the given host:
- ./astat.py -s www.example.com -u mylogin -p mypassword
-
-"""
-
-import os
-import sys
-import time
-import re
-import getopt
-import getpass
-import traceback
-import pexpect
-import pxssh
-
-
-def exit_with_usage():
-
- print globals()['__doc__']
- os._exit(1)
-
-
-def main():
-
- ######################################################################
- # Parse the options, arguments, get ready, etc.
- ######################################################################
- try:
- optlist, args = getopt.getopt(
- sys.argv[
- 1:], 'h?s:u:p:', [
- 'help', 'h', '?'])
- except Exception as e:
- print str(e)
- exit_with_usage()
- options = dict(optlist)
- if len(args) > 1:
- exit_with_usage()
-
- if [elem for elem in options if elem in [
- '-h', '--h', '-?', '--?', '--help']]:
- print "Help:"
- exit_with_usage()
-
- if '-s' in options:
- hostname = options['-s']
- else:
- hostname = raw_input('hostname: ')
- if '-u' in options:
- username = options['-u']
- else:
- username = raw_input('username: ')
- if '-p' in options:
- password = options['-p']
- else:
- password = getpass.getpass('password: ')
-
- #
- # Login via SSH
- #
- p = pxssh.pxssh()
- p.login(hostname, username, password)
- p.sendline('apachectl status')
- p.expect('([0-9]+\.[0-9]+)\s*requests/sec')
- requests_per_second = p.match.groups()[0]
- p.logout()
- print requests_per_second
-
-if __name__ == "__main__":
- try:
- main()
- except Exception as e:
- print str(e)
- traceback.print_exc()
- os._exit(1)
Index: third_party/Python/module/pexpect-2.4/examples/bd_client.py
===================================================================
--- third_party/Python/module/pexpect-2.4/examples/bd_client.py
+++ third_party/Python/module/pexpect-2.4/examples/bd_client.py
@@ -1,40 +0,0 @@
-#!/usr/bin/env python
-
-"""This is a very simple client for the backdoor daemon. This is intended more
-for testing rather than normal use. See bd_serv.py """
-
-import socket
-import sys
-import time
-import select
-
-
-def recv_wrapper(s):
- r, w, e = select.select([s.fileno()], [], [], 2)
- if not r:
- return ''
- #cols = int(s.recv(4))
- #rows = int(s.recv(4))
- cols = 80
- rows = 24
- packet_size = cols * rows * 2 # double it for good measure
- return s.recv(packet_size)
-
-# HOST = '' #'localhost' # The remote host
-# PORT = 1664 # The same port as used by the server
-s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
-s.connect(sys.argv[1]) # (HOST, PORT))
-time.sleep(1)
-# s.setblocking(0)
-#s.send('COMMAND' + '\x01' + sys.argv[1])
-s.send(':sendline ' + sys.argv[2])
-print recv_wrapper(s)
-s.close()
-sys.exit()
-# while True:
-# data = recv_wrapper(s)
-# if data == '':
-# break
-# sys.stdout.write (data)
-# sys.stdout.flush()
-# s.close()
Index: third_party/Python/module/pexpect-2.4/examples/bd_serv.py
===================================================================
--- third_party/Python/module/pexpect-2.4/examples/bd_serv.py
+++ third_party/Python/module/pexpect-2.4/examples/bd_serv.py
@@ -1,339 +0,0 @@
-#!/usr/bin/env python
-
-"""Back door shell server
-
-This exposes an shell terminal on a socket.
-
- --hostname : sets the remote host name to open an ssh connection to.
- --username : sets the user name to login with
- --password : (optional) sets the password to login with
- --port : set the local port for the server to listen on
- --watch : show the virtual screen after each client request
-"""
-
-# Having the password on the command line is not a good idea, but
-# then this entire project is probably not the most security concious thing
-# I've ever built. This should be considered an experimental tool -- at best.
-import pxssh
-import pexpect
-import ANSI
-import time
-import sys
-import os
-import getopt
-import getpass
-import traceback
-import threading
-import socket
-
-
-def exit_with_usage(exit_code=1):
-
- print globals()['__doc__']
- os._exit(exit_code)
-
-
-class roller (threading.Thread):
-
- """This runs a function in a loop in a thread."""
-
- def __init__(self, interval, function, args=[], kwargs={}):
- """The interval parameter defines time between each call to the function.
- """
-
- threading.Thread.__init__(self)
- self.interval = interval
- self.function = function
- self.args = args
- self.kwargs = kwargs
- self.finished = threading.Event()
-
- def cancel(self):
- """Stop the roller."""
-
- self.finished.set()
-
- def run(self):
-
- while not self.finished.isSet():
- # self.finished.wait(self.interval)
- self.function(*self.args, **self.kwargs)
-
-
-def endless_poll(child, prompt, screen, refresh_timeout=0.1):
- """This keeps the screen updated with the output of the child. This runs in
- a separate thread. See roller(). """
-
- #child.logfile_read = screen
- try:
- s = child.read_nonblocking(4000, 0.1)
- screen.write(s)
- except:
- pass
- # while True:
- # #child.prompt (timeout=refresh_timeout)
- # try:
- # #child.read_nonblocking(1,timeout=refresh_timeout)
- # child.read_nonblocking(4000, 0.1)
- # except:
- # pass
-
-
-def daemonize(stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
- '''This forks the current process into a daemon. Almost none of this is
- necessary (or advisable) if your daemon is being started by inetd. In that
- case, stdin, stdout and stderr are all set up for you to refer to the
- network connection, and the fork()s and session manipulation should not be
- done (to avoid confusing inetd). Only the chdir() and umask() steps remain
- as useful.
-
- References:
- UNIX Programming FAQ
- 1.7 How do I get my program to act like a daemon?
- http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16
-
- Advanced Programming in the Unix Environment
- W. Richard Stevens, 1992, Addison-Wesley, ISBN 0-201-56317-7.
-
- The stdin, stdout, and stderr arguments are file names that will be opened
- and be used to replace the standard file descriptors in sys.stdin,
- sys.stdout, and sys.stderr. These arguments are optional and default to
- /dev/null. Note that stderr is opened unbuffered, so if it shares a file
- with stdout then interleaved output may not appear in the order that you
- expect. '''
-
- # Do first fork.
- try:
- pid = os.fork()
- if pid > 0:
- sys.exit(0) # Exit first parent.
- except OSError as e:
- sys.stderr.write("fork #1 failed: (%d) %s\n" % (e.errno, e.strerror))
- sys.exit(1)
-
- # Decouple from parent environment.
- os.chdir("/")
- os.umask(0)
- os.setsid()
-
- # Do second fork.
- try:
- pid = os.fork()
- if pid > 0:
- sys.exit(0) # Exit second parent.
- except OSError as e:
- sys.stderr.write("fork #2 failed: (%d) %s\n" % (e.errno, e.strerror))
- sys.exit(1)
-
- # Now I am a daemon!
-
- # Redirect standard file descriptors.
- si = open(stdin, 'r')
- so = open(stdout, 'a+')
- se = open(stderr, 'a+', 0)
- os.dup2(si.fileno(), sys.stdin.fileno())
- os.dup2(so.fileno(), sys.stdout.fileno())
- os.dup2(se.fileno(), sys.stderr.fileno())
-
- # I now return as the daemon
- return 0
-
-
-def add_cursor_blink(response, row, col):
-
- i = (row - 1) * 80 + col
- return response[:i] + \
- '' + response[i:]
-
-
-def main():
-
- try:
- optlist, args = getopt.getopt(
- sys.argv[
- 1:], 'h?d', [
- 'help', 'h', '?', 'hostname=', 'username=', 'password=', 'port=', 'watch'])
- except Exception as e:
- print str(e)
- exit_with_usage()
-
- command_line_options = dict(optlist)
- options = dict(optlist)
- # There are a million ways to cry for help. These are but a few of them.
- if [elem for elem in command_line_options if elem in [
- '-h', '--h', '-?', '--?', '--help']]:
- exit_with_usage(0)
-
- hostname = "127.0.0.1"
- port = 1664
- username = os.getenv('USER')
- password = ""
- daemon_mode = False
- if '-d' in options:
- daemon_mode = True
- if '--watch' in options:
- watch_mode = True
- else:
- watch_mode = False
- if '--hostname' in options:
- hostname = options['--hostname']
- if '--port' in options:
- port = int(options['--port'])
- if '--username' in options:
- username = options['--username']
- print "Login for %s@%s:%s" % (username, hostname, port)
- if '--password' in options:
- password = options['--password']
- else:
- password = getpass.getpass('password: ')
-
- if daemon_mode:
- print "daemonizing server"
- daemonize()
- # daemonize('/dev/null','/tmp/daemon.log','/tmp/daemon.log')
-
- sys.stdout.write('server started with pid %d\n' % os.getpid())
-
- virtual_screen = ANSI.ANSI(24, 80)
- child = pxssh.pxssh()
- child.login(hostname, username, password)
- print 'created shell. command line prompt is', child.PROMPT
- #child.sendline ('stty -echo')
- # child.setecho(False)
- virtual_screen.write(child.before)
- virtual_screen.write(child.after)
-
- if os.path.exists("/tmp/mysock"):
- os.remove("/tmp/mysock")
- s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
- localhost = '127.0.0.1'
- s.bind('/tmp/mysock')
- os.chmod('/tmp/mysock', 0o777)
- print 'Listen'
- s.listen(1)
- print 'Accept'
- #s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- #localhost = '127.0.0.1'
- #s.bind((localhost, port))
- # print 'Listen'
- # s.listen(1)
-
- r = roller(0.01, endless_poll, (child, child.PROMPT, virtual_screen))
- r.start()
- print "screen poll updater started in background thread"
- sys.stdout.flush()
-
- try:
- while True:
- conn, addr = s.accept()
- print 'Connected by', addr
- data = conn.recv(1024)
- if data[0] != ':':
- cmd = ':sendline'
- arg = data.strip()
- else:
- request = data.split(' ', 1)
- if len(request) > 1:
- cmd = request[0].strip()
- arg = request[1].strip()
- else:
- cmd = request[0].strip()
- if cmd == ':exit':
- r.cancel()
- break
- elif cmd == ':sendline':
- child.sendline(arg)
- # child.prompt(timeout=2)
- time.sleep(0.2)
- shell_window = str(virtual_screen)
- elif cmd == ':send' or cmd == ':xsend':
- if cmd == ':xsend':
- arg = arg.decode("hex")
- child.send(arg)
- time.sleep(0.2)
- shell_window = str(virtual_screen)
- elif cmd == ':cursor':
- shell_window = '%x%x' % (
- virtual_screen.cur_r, virtual_screen.cur_c)
- elif cmd == ':refresh':
- shell_window = str(virtual_screen)
-
- response = []
- response.append(shell_window)
- #response = add_cursor_blink (response, row, col)
- sent = conn.send('\n'.join(response))
- if watch_mode:
- print '\n'.join(response)
- if sent < len(response):
- print "Sent is too short. Some data was cut off."
- conn.close()
- finally:
- r.cancel()
- print "cleaning up socket"
- s.close()
- if os.path.exists("/tmp/mysock"):
- os.remove("/tmp/mysock")
- print "done!"
-
-
-def pretty_box(rows, cols, s):
- """This puts an ASCII text box around the given string, s.
- """
-
- top_bot = '+' + '-' * cols + '+\n'
- return top_bot + \
- '\n'.join(['|' + line + '|' for line in s.split('\n')]) + '\n' + top_bot
-
-
-def error_response(msg):
-
- response = []
- response.append ("""All commands start with :
-:{REQUEST} {ARGUMENT}
-{REQUEST} may be one of the following:
- :sendline: Run the ARGUMENT followed by a line feed.
- :send : send the characters in the ARGUMENT without a line feed.
- :refresh : Use to catch up the screen with the shell if state gets out of sync.
-Example:
- :sendline ls -l
-You may also leave off :command and it will be assumed.
-Example:
- ls -l
-is equivalent to:
- :sendline ls -l
-""")
- response.append(msg)
- return '\n'.join(response)
-
-
-def parse_host_connect_string(hcs):
- """This parses a host connection string in the form
- username:password@hostname:port. All fields are options expcet hostname. A
- dictionary is returned with all four keys. Keys that were not included are
- set to empty strings ''. Note that if your password has the '@' character
- then you must backslash escape it. """
-
- if '@' in hcs:
- p = re.compile(
- r'(?P[^@:]*)(:?)(?P.*)(?!\\)@(?P[^:]*):?(?P[0-9]*)')
- else:
- p = re.compile(
- r'(?P)(?P)(?P[^:]*):?(?P[0-9]*)')
- m = p.search(hcs)
- d = m.groupdict()
- d['password'] = d['password'].replace('\\@', '@')
- return d
-
-if __name__ == "__main__":
-
- try:
- start_time = time.time()
- print time.asctime()
- main()
- print time.asctime()
- print "TOTAL TIME IN MINUTES:",
- print (time.time() - start_time) / 60.0
- except Exception as e:
- print str(e)
- tb_dump = traceback.format_exc()
- print str(tb_dump)
Index: third_party/Python/module/pexpect-2.4/examples/cgishell.cgi
===================================================================
--- third_party/Python/module/pexpect-2.4/examples/cgishell.cgi
+++ third_party/Python/module/pexpect-2.4/examples/cgishell.cgi
@@ -1,762 +0,0 @@
-#!/usr/bin/python
-##!/usr/bin/env python
-"""CGI shell server
-
-This exposes a shell terminal on a web page.
-It uses AJAX to send keys and receive screen updates.
-The client web browser needs nothing but CSS and Javascript.
-
- --hostname : sets the remote host name to open an ssh connection to.
- --username : sets the user name to login with
- --password : (optional) sets the password to login with
- --port : set the local port for the server to listen on
- --watch : show the virtual screen after each client request
-
-This project is probably not the most security concious thing I've ever built.
-This should be considered an experimental tool -- at best.
-"""
-import sys,os
-sys.path.insert (0,os.getcwd()) # let local modules precede any installed modules
-import socket, random, string, traceback, cgi, time, getopt, getpass, threading, resource, signal
-import pxssh, pexpect, ANSI
-
-def exit_with_usage(exit_code=1):
- print globals()['__doc__']
- os._exit(exit_code)
-
-def client (command, host='localhost', port=-1):
- """This sends a request to the server and returns the response.
- If port <= 0 then host is assumed to be the filename of a Unix domain socket.
- If port > 0 then host is an inet hostname.
- """
- if port <= 0:
- s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
- s.connect(host)
- else:
- s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- s.connect((host, port))
- s.send(command)
- data = s.recv (2500)
- s.close()
- return data
-
-def server (hostname, username, password, socket_filename='/tmp/server_sock', daemon_mode = True, verbose=False):
- """This starts and services requests from a client.
- If daemon_mode is True then this forks off a separate daemon process and returns the daemon's pid.
- If daemon_mode is False then this does not return until the server is done.
- """
- if daemon_mode:
- mypid_name = '/tmp/%d.pid' % os.getpid()
- daemon_pid = daemonize(daemon_pid_filename=mypid_name)
- time.sleep(1)
- if daemon_pid != 0:
- os.unlink(mypid_name)
- return daemon_pid
-
- virtual_screen = ANSI.ANSI (24,80)
- child = pxssh.pxssh()
- try:
- child.login (hostname, username, password, login_naked=True)
- except:
- return
- if verbose: print 'login OK'
- virtual_screen.write (child.before)
- virtual_screen.write (child.after)
-
- if os.path.exists(socket_filename): os.remove(socket_filename)
- s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
- s.bind(socket_filename)
- os.chmod(socket_filename, 0777)
- if verbose: print 'Listen'
- s.listen(1)
-
- r = roller (endless_poll, (child, child.PROMPT, virtual_screen))
- r.start()
- if verbose: print "started screen-poll-updater in background thread"
- sys.stdout.flush()
- try:
- while True:
- conn, addr = s.accept()
- if verbose: print 'Connected by', addr
- data = conn.recv(1024)
- request = data.split(' ', 1)
- if len(request)>1:
- cmd = request[0].strip()
- arg = request[1].strip()
- else:
- cmd = request[0].strip()
- arg = ''
-
- if cmd == 'exit':
- r.cancel()
- break
- elif cmd == 'sendline':
- child.sendline (arg)
- time.sleep(0.1)
- shell_window = str(virtual_screen)
- elif cmd == 'send' or cmd=='xsend':
- if cmd=='xsend':
- arg = arg.decode("hex")
- child.send (arg)
- time.sleep(0.1)
- shell_window = str(virtual_screen)
- elif cmd == 'cursor':
- shell_window = '%x,%x' % (virtual_screen.cur_r, virtual_screen.cur_c)
- elif cmd == 'refresh':
- shell_window = str(virtual_screen)
- elif cmd == 'hash':
- shell_window = str(hash(str(virtual_screen)))
-
- response = []
- response.append (shell_window)
- if verbose: print '\n'.join(response)
- sent = conn.send('\n'.join(response))
- if sent < len (response):
- if verbose: print "Sent is too short. Some data was cut off."
- conn.close()
- except e:
- pass
- r.cancel()
- if verbose: print "cleaning up socket"
- s.close()
- if os.path.exists(socket_filename): os.remove(socket_filename)
- if verbose: print "server done!"
-
-class roller (threading.Thread):
- """This class continuously loops a function in a thread.
- This is basically a thin layer around Thread with a
- while loop and a cancel.
- """
- def __init__(self, function, args=[], kwargs={}):
- threading.Thread.__init__(self)
- self.function = function
- self.args = args
- self.kwargs = kwargs
- self.finished = threading.Event()
- def cancel(self):
- """Stop the roller."""
- self.finished.set()
- def run(self):
- while not self.finished.isSet():
- self.function(*self.args, **self.kwargs)
-
-def endless_poll (child, prompt, screen, refresh_timeout=0.1):
- """This keeps the screen updated with the output of the child.
- This will be run in a separate thread. See roller class.
- """
- #child.logfile_read = screen
- try:
- s = child.read_nonblocking(4000, 0.1)
- screen.write(s)
- except:
- pass
-
-def daemonize (stdin=None, stdout=None, stderr=None, daemon_pid_filename=None):
- """This runs the current process in the background as a daemon.
- The arguments stdin, stdout, stderr allow you to set the filename that the daemon reads and writes to.
- If they are set to None then all stdio for the daemon will be directed to /dev/null.
- If daemon_pid_filename is set then the pid of the daemon will be written to it as plain text
- and the pid will be returned. If daemon_pid_filename is None then this will return None.
- """
- UMASK = 0
- WORKINGDIR = "/"
- MAXFD = 1024
-
- # The stdio file descriptors are redirected to /dev/null by default.
- if hasattr(os, "devnull"):
- DEVNULL = os.devnull
- else:
- DEVNULL = "/dev/null"
- if stdin is None: stdin = DEVNULL
- if stdout is None: stdout = DEVNULL
- if stderr is None: stderr = DEVNULL
-
- try:
- pid = os.fork()
- except OSError, e:
- raise Exception, "%s [%d]" % (e.strerror, e.errno)
-
- if pid != 0: # The first child.
- os.waitpid(pid,0)
- if daemon_pid_filename is not None:
- daemon_pid = int(file(daemon_pid_filename,'r').read())
- return daemon_pid
- else:
- return None
-
- # first child
- os.setsid()
- signal.signal(signal.SIGHUP, signal.SIG_IGN)
-
- try:
- pid = os.fork() # fork second child
- except OSError, e:
- raise Exception, "%s [%d]" % (e.strerror, e.errno)
-
- if pid != 0:
- if daemon_pid_filename is not None:
- file(daemon_pid_filename,'w').write(str(pid))
- os._exit(0) # exit parent (the first child) of the second child.
-
- # second child
- os.chdir(WORKINGDIR)
- os.umask(UMASK)
-
- maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1]
- if maxfd == resource.RLIM_INFINITY:
- maxfd = MAXFD
-
- # close all file descriptors
- for fd in xrange(0, maxfd):
- try:
- os.close(fd)
- except OSError: # fd wasn't open to begin with (ignored)
- pass
-
- os.open (DEVNULL, os.O_RDWR) # standard input
-
- # redirect standard file descriptors
- si = open(stdin, 'r')
- so = open(stdout, 'a+')
- se = open(stderr, 'a+', 0)
- os.dup2(si.fileno(), sys.stdin.fileno())
- os.dup2(so.fileno(), sys.stdout.fileno())
- os.dup2(se.fileno(), sys.stderr.fileno())
-
- return 0
-
-def client_cgi ():
- """This handles the request if this script was called as a cgi.
- """
- sys.stderr = sys.stdout
- ajax_mode = False
- TITLE="Shell"
- SHELL_OUTPUT=""
- SID="NOT"
- print "Content-type: text/html;charset=utf-8\r\n"
- try:
- form = cgi.FieldStorage()
- if form.has_key('ajax'):
- ajax_mode = True
- ajax_cmd = form['ajax'].value
- SID=form['sid'].value
- if ajax_cmd == 'send':
- command = 'xsend'
- arg = form['arg'].value.encode('hex')
- result = client (command + ' ' + arg, '/tmp/'+SID)
- print result
- elif ajax_cmd == 'refresh':
- command = 'refresh'
- result = client (command, '/tmp/'+SID)
- print result
- elif ajax_cmd == 'cursor':
- command = 'cursor'
- result = client (command, '/tmp/'+SID)
- print result
- elif ajax_cmd == 'exit':
- command = 'exit'
- result = client (command, '/tmp/'+SID)
- print result
- elif ajax_cmd == 'hash':
- command = 'hash'
- result = client (command, '/tmp/'+SID)
- print result
- elif not form.has_key('sid'):
- SID=random_sid()
- print LOGIN_HTML % locals();
- else:
- SID=form['sid'].value
- if form.has_key('start_server'):
- USERNAME = form['username'].value
- PASSWORD = form['password'].value
- dpid = server ('127.0.0.1', USERNAME, PASSWORD, '/tmp/'+SID)
- SHELL_OUTPUT="daemon pid: " + str(dpid)
- else:
- if form.has_key('cli'):
- command = 'sendline ' + form['cli'].value
- else:
- command = 'sendline'
- SHELL_OUTPUT = client (command, '/tmp/'+SID)
- print CGISH_HTML % locals()
- except:
- tb_dump = traceback.format_exc()
- if ajax_mode:
- print str(tb_dump)
- else:
- SHELL_OUTPUT=str(tb_dump)
- print CGISH_HTML % locals()
-
-def server_cli():
- """This is the command line interface to starting the server.
- This handles things if the script was not called as a CGI
- (if you run it from the command line).
- """
- try:
- optlist, args = getopt.getopt(sys.argv[1:], 'h?d', ['help','h','?', 'hostname=', 'username=', 'password=', 'port=', 'watch'])
- except Exception, e:
- print str(e)
- exit_with_usage()
-
- command_line_options = dict(optlist)
- options = dict(optlist)
- # There are a million ways to cry for help. These are but a few of them.
- if [elem for elem in command_line_options if elem in ['-h','--h','-?','--?','--help']]:
- exit_with_usage(0)
-
- hostname = "127.0.0.1"
- #port = 1664
- username = os.getenv('USER')
- password = ""
- daemon_mode = False
- if '-d' in options:
- daemon_mode = True
- if '--watch' in options:
- watch_mode = True
- else:
- watch_mode = False
- if '--hostname' in options:
- hostname = options['--hostname']
- if '--port' in options:
- port = int(options['--port'])
- if '--username' in options:
- username = options['--username']
- if '--password' in options:
- password = options['--password']
- else:
- password = getpass.getpass('password: ')
-
- server (hostname, username, password, '/tmp/mysock', daemon_mode)
-
-def random_sid ():
- a=random.randint(0,65535)
- b=random.randint(0,65535)
- return '%04x%04x.sid' % (a,b)
-
-def parse_host_connect_string (hcs):
- """This parses a host connection string in the form
- username:password@hostname:port. All fields are options expcet hostname. A
- dictionary is returned with all four keys. Keys that were not included are
- set to empty strings ''. Note that if your password has the '@' character
- then you must backslash escape it.
- """
- if '@' in hcs:
- p = re.compile (r'(?P[^@:]*)(:?)(?P.*)(?!\\)@(?P[^:]*):?(?P[0-9]*)')
- else:
- p = re.compile (r'(?P)(?P)(?P[^:]*):?(?P[0-9]*)')
- m = p.search (hcs)
- d = m.groupdict()
- d['password'] = d['password'].replace('\\@','@')
- return d
-
-def pretty_box (s, rows=24, cols=80):
- """This puts an ASCII text box around the given string.
- """
- top_bot = '+' + '-'*cols + '+\n'
- return top_bot + '\n'.join(['|'+line+'|' for line in s.split('\n')]) + '\n' + top_bot
-
-def main ():
- if os.getenv('REQUEST_METHOD') is None:
- server_cli()
- else:
- client_cgi()
-
-# It's mostly HTML and Javascript from here on out.
-CGISH_HTML="""
-
-
-%(TITLE)s %(SID)s
-
-
-
-
-
-
-
-
-
-
-
-"""
-
-LOGIN_HTML="""
-
-Shell Login
-
-
-
-
-
-
-
-
-
-"""
-
-if __name__ == "__main__":
- try:
- main()
- except Exception, e:
- print str(e)
- tb_dump = traceback.format_exc()
- print str(tb_dump)
-
Index: third_party/Python/module/pexpect-2.4/examples/chess.py
===================================================================
--- third_party/Python/module/pexpect-2.4/examples/chess.py
+++ third_party/Python/module/pexpect-2.4/examples/chess.py
@@ -1,132 +0,0 @@
-#!/usr/bin/env python
-
-'''This demonstrates controlling a screen oriented application (curses).
-It starts two instances of gnuchess and then pits them against each other.
-'''
-
-import pexpect
-import string
-import ANSI
-
-REGEX_MOVE = '(?:[a-z]|\x1b\[C)(?:[0-9]|\x1b\[C)(?:[a-z]|\x1b\[C)(?:[0-9]|\x1b\[C)'
-REGEX_MOVE_PART = '(?:[0-9]|\x1b\[C)(?:[a-z]|\x1b\[C)(?:[0-9]|\x1b\[C)'
-
-
-class Chess:
-
- def __init__(self, engine="/usr/local/bin/gnuchess -a -h 1"):
- self.child = pexpect.spawn(engine)
- self.term = ANSI.ANSI()
-
- self.child.expect('Chess')
- if self.child.after != 'Chess':
- raise IOError, 'incompatible chess program'
- self.term.process_list(self.before)
- self.term.process_list(self.after)
- self.last_computer_move = ''
-
- def read_until_cursor(self, r, c)
- while 1:
- self.child.read(1, 60)
- self.term.process(c)
- if self.term.cur_r == r and self.term.cur_c == c:
- return 1
-
- def do_first_move(self, move):
- self.child.expect('Your move is')
- self.child.sendline(move)
- self.term.process_list(self.before)
- self.term.process_list(self.after)
- return move
-
- def do_move(self, move):
- read_until_cursor(19, 60)
- #self.child.expect ('\[19;60H')
- self.child.sendline(move)
- print 'do_move' move
- return move
-
- def get_first_computer_move(self):
- self.child.expect('My move is')
- self.child.expect(REGEX_MOVE)
-# print '', self.child.after
- return self.child.after
-
- def get_computer_move(self):
- print 'Here'
- i = self.child.expect(['\[17;59H', '\[17;58H'])
- print i
- if i == 0:
- self.child.expect(REGEX_MOVE)
- if len(self.child.after) < 4:
- self.child.after = self.child.after + \
- self.last_computer_move[3]
- if i == 1:
- self.child.expect(REGEX_MOVE_PART)
- self.child.after = self.last_computer_move[0] + self.child.after
- print '', self.child.after
- self.last_computer_move = self.child.after
- return self.child.after
-
- def switch(self):
- self.child.sendline('switch')
-
- def set_depth(self, depth):
- self.child.sendline('depth')
- self.child.expect('depth=')
- self.child.sendline('%d' % depth)
-
- def quit(self):
- self.child.sendline('quit')
-import sys
-import os
-print 'Starting...'
-white = Chess()
-white.child.echo = 1
-white.child.expect('Your move is')
-white.set_depth(2)
-white.switch()
-
-move_white = white.get_first_computer_move()
-print 'first move white:', move_white
-
-white.do_move('e7e5')
-move_white = white.get_computer_move()
-print 'move white:', move_white
-white.do_move('f8c5')
-move_white = white.get_computer_move()
-print 'move white:', move_white
-white.do_move('b8a6')
-move_white = white.get_computer_move()
-print 'move white:', move_white
-
-sys.exit(1)
-
-
-black = Chess()
-white = Chess()
-white.child.expect('Your move is')
-white.switch()
-
-move_white = white.get_first_computer_move()
-print 'first move white:', move_white
-
-black.do_first_move(move_white)
-move_black = black.get_first_computer_move()
-print 'first move black:', move_black
-
-white.do_move(move_black)
-
-done = 0
-while not done:
- move_white = white.get_computer_move()
- print 'move white:', move_white
-
- black.do_move(move_white)
- move_black = black.get_computer_move()
- print 'move black:', move_black
-
- white.do_move(move_black)
- print 'tail of loop'
-
-g.quit()
Index: third_party/Python/module/pexpect-2.4/examples/chess2.py
===================================================================
--- third_party/Python/module/pexpect-2.4/examples/chess2.py
+++ third_party/Python/module/pexpect-2.4/examples/chess2.py
@@ -1,135 +0,0 @@
-#!/usr/bin/env python
-
-'''This demonstrates controlling a screen oriented application (curses).
-It starts two instances of gnuchess and then pits them against each other.
-'''
-
-import pexpect
-import string
-import ANSI
-import sys
-import os
-import time
-
-
-class Chess:
-
- def __init__(self, engine="/usr/local/bin/gnuchess -a -h 1"):
- self.child = pexpect.spawn(engine)
- self.term = ANSI.ANSI()
-
- #self.child.expect ('Chess')
- # if self.child.after != 'Chess':
- # raise IOError, 'incompatible chess program'
- #self.term.process_list (self.child.before)
- #self.term.process_list (self.child.after)
-
- self.last_computer_move = ''
-
- def read_until_cursor(self, r, c, e=0):
- '''Eventually something like this should move into the screen class or
- a subclass. Maybe a combination of pexpect and screen...
- '''
- fout = open('log', 'a')
- while self.term.cur_r != r or self.term.cur_c != c:
- try:
- k = self.child.read(1, 10)
- except Exception as e:
- print 'EXCEPTION, (r,c):(%d,%d)\n' % (self.term.cur_r, self.term.cur_c)
- sys.stdout.flush()
- self.term.process(k)
- fout.write('(r,c):(%d,%d)\n' % (self.term.cur_r, self.term.cur_c))
- fout.flush()
- if e:
- sys.stdout.write(k)
- sys.stdout.flush()
- if self.term.cur_r == r and self.term.cur_c == c:
- fout.close()
- return 1
- print 'DIDNT EVEN HIT.'
- fout.close()
- return 1
-
- def expect_region(self):
- '''This is another method that would be moved into the
- screen class.
- '''
- pass
-
- def do_scan(self):
- fout = open('log', 'a')
- while True:
- c = self.child.read(1, 10)
- self.term.process(c)
- fout.write('(r,c):(%d,%d)\n' % (self.term.cur_r, self.term.cur_c))
- fout.flush()
- sys.stdout.write(c)
- sys.stdout.flush()
-
- def do_move(self, move, e=0):
- time.sleep(1)
- self.read_until_cursor(19, 60, e)
- self.child.sendline(move)
-
- def wait(self, color):
- while True:
- r = self.term.get_region(14, 50, 14, 60)[0]
- r = r.strip()
- if r == color:
- return
- time.sleep(1)
-
- def parse_computer_move(self, s):
- i = s.find('is: ')
- cm = s[i + 3:i + 9]
- return cm
-
- def get_computer_move(self, e=0):
- time.sleep(1)
- self.read_until_cursor(19, 60, e)
- time.sleep(1)
- r = self.term.get_region(17, 50, 17, 62)[0]
- cm = self.parse_computer_move(r)
- return cm
-
- def switch(self):
- print 'switching'
- self.child.sendline('switch')
-
- def set_depth(self, depth):
- self.child.sendline('depth')
- self.child.expect('depth=')
- self.child.sendline('%d' % depth)
-
- def quit(self):
- self.child.sendline('quit')
-
-
-def LOG(s):
- print s
- sys.stdout.flush()
- fout = open('moves.log', 'a')
- fout.write(s + '\n')
- fout.close()
-
-print 'Starting...'
-
-black = Chess()
-white = Chess()
-white.read_until_cursor(19, 60, 1)
-white.switch()
-
-done = 0
-while not done:
- white.wait('Black')
- move_white = white.get_computer_move(1)
- LOG('move white:' + move_white)
-
- black.do_move(move_white)
- black.wait('White')
- move_black = black.get_computer_move()
- LOG('move black:' + move_black)
-
- white.do_move(move_black, 1)
-
-g.quit()
Index: third_party/Python/module/pexpect-2.4/examples/chess3.py
===================================================================
--- third_party/Python/module/pexpect-2.4/examples/chess3.py
+++ third_party/Python/module/pexpect-2.4/examples/chess3.py
@@ -1,139 +0,0 @@
-#!/usr/bin/env python
-
-'''This demonstrates controlling a screen oriented application (curses).
-It starts two instances of gnuchess and then pits them against each other.
-'''
-
-import pexpect
-import string
-import ANSI
-
-REGEX_MOVE = '(?:[a-z]|\x1b\[C)(?:[0-9]|\x1b\[C)(?:[a-z]|\x1b\[C)(?:[0-9]|\x1b\[C)'
-REGEX_MOVE_PART = '(?:[0-9]|\x1b\[C)(?:[a-z]|\x1b\[C)(?:[0-9]|\x1b\[C)'
-
-
-class Chess:
-
- def __init__(self, engine="/usr/local/bin/gnuchess -a -h 1"):
- self.child = pexpect.spawn(engine)
- self.term = ANSI.ANSI()
-
-# self.child.expect ('Chess')
- # if self.child.after != 'Chess':
- # raise IOError, 'incompatible chess program'
- # self.term.process_list (self.before)
- # self.term.process_list (self.after)
- self.last_computer_move = ''
-
- def read_until_cursor(self, r, c):
- fout = open('log', 'a')
- while True:
- k = self.child.read(1, 10)
- self.term.process(k)
- fout.write('(r,c):(%d,%d)\n' % (self.term.cur_r, self.term.cur_c))
- fout.flush()
- if self.term.cur_r == r and self.term.cur_c == c:
- fout.close()
- return 1
- sys.stdout.write(k)
- sys.stdout.flush()
-
- def do_scan(self):
- fout = open('log', 'a')
- while True:
- c = self.child.read(1, 10)
- self.term.process(c)
- fout.write('(r,c):(%d,%d)\n' % (self.term.cur_r, self.term.cur_c))
- fout.flush()
- sys.stdout.write(c)
- sys.stdout.flush()
-
- def do_move(self, move):
- self.read_until_cursor(19, 60)
- self.child.sendline(move)
- return move
-
- def get_computer_move(self):
- print 'Here'
- i = self.child.expect(['\[17;59H', '\[17;58H'])
- print i
- if i == 0:
- self.child.expect(REGEX_MOVE)
- if len(self.child.after) < 4:
- self.child.after = self.child.after + \
- self.last_computer_move[3]
- if i == 1:
- self.child.expect(REGEX_MOVE_PART)
- self.child.after = self.last_computer_move[0] + self.child.after
- print '', self.child.after
- self.last_computer_move = self.child.after
- return self.child.after
-
- def switch(self):
- self.child.sendline('switch')
-
- def set_depth(self, depth):
- self.child.sendline('depth')
- self.child.expect('depth=')
- self.child.sendline('%d' % depth)
-
- def quit(self):
- self.child.sendline('quit')
-import sys
-import os
-print 'Starting...'
-white = Chess()
-white.do_move('b2b4')
-white.read_until_cursor(19, 60)
-c1 = white.term.get_abs(17, 58)
-c2 = white.term.get_abs(17, 59)
-c3 = white.term.get_abs(17, 60)
-c4 = white.term.get_abs(17, 61)
-fout = open('log', 'a')
-fout.write('Computer:%s%s%s%s\n' % (c1, c2, c3, c4))
-fout.close()
-white.do_move('c2c4')
-white.read_until_cursor(19, 60)
-c1 = white.term.get_abs(17, 58)
-c2 = white.term.get_abs(17, 59)
-c3 = white.term.get_abs(17, 60)
-c4 = white.term.get_abs(17, 61)
-fout = open('log', 'a')
-fout.write('Computer:%s%s%s%s\n' % (c1, c2, c3, c4))
-fout.close()
-white.do_scan()
-
-#white.do_move ('b8a6')
-#move_white = white.get_computer_move()
-# print 'move white:', move_white
-
-sys.exit(1)
-
-
-black = Chess()
-white = Chess()
-white.child.expect('Your move is')
-white.switch()
-
-move_white = white.get_first_computer_move()
-print 'first move white:', move_white
-
-black.do_first_move(move_white)
-move_black = black.get_first_computer_move()
-print 'first move black:', move_black
-
-white.do_move(move_black)
-
-done = 0
-while not done:
- move_white = white.get_computer_move()
- print 'move white:', move_white
-
- black.do_move(move_white)
- move_black = black.get_computer_move()
- print 'move black:', move_black
-
- white.do_move(move_black)
- print 'tail of loop'
-
-g.quit()
Index: third_party/Python/module/pexpect-2.4/examples/df.py
===================================================================
--- third_party/Python/module/pexpect-2.4/examples/df.py
+++ third_party/Python/module/pexpect-2.4/examples/df.py
@@ -1,33 +0,0 @@
-#!/usr/bin/env python
-
-"""This collects filesystem capacity info using the 'df' command. Tuples of
-filesystem name and percentage are stored in a list. A simple report is
-printed. Filesystems over 95% capacity are highlighted. Note that this does not
-parse filesystem names after the first space, so names with spaces in them will
-be truncated. This will produce ambiguous results for automount filesystems on
-Apple OSX. """
-
-import pexpect
-
-child = pexpect.spawn('df')
-
-# parse 'df' output into a list.
-pattern = "\n(\S+).*?([0-9]+)%"
-filesystem_list = []
-for dummy in range(0, 1000):
- i = child.expect([pattern, pexpect.EOF])
- if i == 0:
- filesystem_list.append(child.match.groups())
- else:
- break
-
-# Print report
-print
-for m in filesystem_list:
- s = "Filesystem %s is at %s%%" % (m[0], m[1])
- # highlight filesystems over 95% capacity
- if int(m[1]) > 95:
- s = '! ' + s
- else:
- s = ' ' + s
- print s
Index: third_party/Python/module/pexpect-2.4/examples/fix_cvs_files.py
===================================================================
--- third_party/Python/module/pexpect-2.4/examples/fix_cvs_files.py
+++ third_party/Python/module/pexpect-2.4/examples/fix_cvs_files.py
@@ -1,98 +0,0 @@
-#!/usr/bin/env python
-
-"""This is for cleaning up binary files improperly added to CVS. This script
-scans the given path to find binary files; checks with CVS to see if the sticky
-options are set to -kb; finally if sticky options are not -kb then uses 'cvs
-admin' to set the -kb option.
-
-This script ignores CVS directories, symbolic links, and files not known under
-CVS control (cvs status is 'Unknown').
-
-Run this on a CHECKED OUT module sandbox, not on the repository itself. After
-if fixes the sticky options on any files you should manually do a 'cvs commit'
-to accept the changes. Then be sure to have all users do a 'cvs up -A' to
-update the Sticky Option status.
-
-Noah Spurrier
-20030426
-"""
-
-import os
-import sys
-import time
-import pexpect
-
-VERBOSE = 1
-
-
-def is_binary(filename):
- """Assume that any file with a character where the 8th bit is set is
- binary. """
-
- fin = open(filename, 'rb')
- wholething = fin.read()
- fin.close()
- for c in wholething:
- if ord(c) & 0x80:
- return 1
- return 0
-
-
-def is_kb_sticky(filename):
- """This checks if 'cvs status' reports '-kb' for Sticky options. If the
- Sticky Option status is '-ks' then this returns 1. If the status is
- 'Unknown' then it returns 1. Otherwise 0 is returned. """
-
- try:
- s = pexpect.spawn('cvs status %s' % filename)
- i = s.expect(['Sticky Options:\s*(.*)\r\n', 'Status: Unknown'])
- if i == 1 and VERBOSE:
- print 'File not part of CVS repository:', filename
- return 1 # Pretend it's OK.
- if s.match.group(1) == '-kb':
- return 1
- s = None
- except:
- print 'Something went wrong trying to run external cvs command.'
- print ' cvs status %s' % filename
- print 'The cvs command returned:'
- print s.before
- return 0
-
-
-def cvs_admin_kb(filename):
- """This uses 'cvs admin' to set the '-kb' sticky option. """
-
- s = pexpect.run('cvs admin -kb %s' % filename)
- # There is a timing issue. If I run 'cvs admin' too quickly
- # cvs sometimes has trouble obtaining the directory lock.
- time.sleep(1)
-
-
-def walk_and_clean_cvs_binaries(arg, dirname, names):
- """This contains the logic for processing files. This is the os.path.walk
- callback. This skips dirnames that end in CVS. """
-
- if len(dirname) > 3 and dirname[-3:] == 'CVS':
- return
- for n in names:
- fullpath = os.path.join(dirname, n)
- if os.path.isdir(fullpath) or os.path.islink(fullpath):
- continue
- if is_binary(fullpath):
- if not is_kb_sticky(fullpath):
- if VERBOSE:
- print fullpath
- cvs_admin_kb(fullpath)
-
-
-def main():
-
- if len(sys.argv) == 1:
- root = '.'
- else:
- root = sys.argv[1]
- os.path.walk(root, walk_and_clean_cvs_binaries, None)
-
-if __name__ == '__main__':
- main()
Index: third_party/Python/module/pexpect-2.4/examples/ftp.py
===================================================================
--- third_party/Python/module/pexpect-2.4/examples/ftp.py
+++ third_party/Python/module/pexpect-2.4/examples/ftp.py
@@ -1,47 +0,0 @@
-#!/usr/bin/env python
-
-"""This demonstrates an FTP "bookmark". This connects to an ftp site; does a
-few ftp stuff; and then gives the user interactive control over the session. In
-this case the "bookmark" is to a directory on the OpenBSD ftp server. It puts
-you in the i386 packages directory. You can easily modify this for other sites.
-"""
-
-import pexpect
-import sys
-
-child = pexpect.spawn('ftp ftp.openbsd.org')
-child.expect('(?i)name .*: ')
-child.sendline('anonymous')
-child.expect('(?i)password')
-child.sendline('pexpect@sourceforge.net')
-child.expect('ftp> ')
-child.sendline('cd /pub/OpenBSD/3.7/packages/i386')
-child.expect('ftp> ')
-child.sendline('bin')
-child.expect('ftp> ')
-child.sendline('prompt')
-child.expect('ftp> ')
-child.sendline('pwd')
-child.expect('ftp> ')
-print("Escape character is '^]'.\n")
-sys.stdout.write(child.after)
-sys.stdout.flush()
-child.interact() # Escape character defaults to ^]
-# At this point this script blocks until the user presses the escape character
-# or until the child exits. The human user and the child should be talking
-# to each other now.
-
-# At this point the script is running again.
-print 'Left interactve mode.'
-
-# The rest is not strictly necessary. This just demonstrates a few functions.
-# This makes sure the child is dead; although it would be killed when
-# Python exits.
-if child.isalive():
- child.sendline('bye') # Try to ask ftp child to exit.
- child.close()
-# Print the final state of the child. Normally isalive() should be FALSE.
-if child.isalive():
- print 'Child did not exit gracefully.'
-else:
- print 'Child exited gracefully.'
Index: third_party/Python/module/pexpect-2.4/examples/hive.py
===================================================================
--- third_party/Python/module/pexpect-2.4/examples/hive.py
+++ third_party/Python/module/pexpect-2.4/examples/hive.py
@@ -1,472 +0,0 @@
-#!/usr/bin/env python
-
-"""hive -- Hive Shell
-
-This lets you ssh to a group of servers and control them as if they were one.
-Each command you enter is sent to each host in parallel. The response of each
-host is collected and printed. In normal synchronous mode Hive will wait for
-each host to return the shell command line prompt. The shell prompt is used to
-sync output.
-
-Example:
-
- $ hive.py --sameuser --samepass host1.example.com host2.example.net
- username: myusername
- password:
- connecting to host1.example.com - OK
- connecting to host2.example.net - OK
- targetting hosts: 192.168.1.104 192.168.1.107
- CMD (? for help) > uptime
- =======================================================================
- host1.example.com
- -----------------------------------------------------------------------
- uptime
- 23:49:55 up 74 days, 5:14, 2 users, load average: 0.15, 0.05, 0.01
- =======================================================================
- host2.example.net
- -----------------------------------------------------------------------
- uptime
- 23:53:02 up 1 day, 13:36, 2 users, load average: 0.50, 0.40, 0.46
- =======================================================================
-
-Other Usage Examples:
-
-1. You will be asked for your username and password for each host.
-
- hive.py host1 host2 host3 ... hostN
-
-2. You will be asked once for your username and password.
- This will be used for each host.
-
- hive.py --sameuser --samepass host1 host2 host3 ... hostN
-
-3. Give a username and password on the command-line:
-
- hive.py user1:pass2@host1 user2:pass2@host2 ... userN:passN@hostN
-
-You can use an extended host notation to specify username, password, and host
-instead of entering auth information interactively. Where you would enter a
-host name use this format:
-
- username:password@host
-
-This assumes that ':' is not part of the password. If your password contains a
-':' then you can use '\\:' to indicate a ':' and '\\\\' to indicate a single
-'\\'. Remember that this information will appear in the process listing. Anyone
-on your machine can see this auth information. This is not secure.
-
-This is a crude script that begs to be multithreaded. But it serves its
-purpose.
-
-Noah Spurrier
-
-$Id: hive.py 509 2008-01-05 21:27:47Z noah $
-"""
-
-# TODO add feature to support username:password@host combination
-# TODO add feature to log each host output in separate file
-
-import sys
-import os
-import re
-import optparse
-import traceback
-import types
-import time
-import getpass
-import pexpect
-import pxssh
-import readline
-import atexit
-
-#histfile = os.path.join(os.environ["HOME"], ".hive_history")
-# try:
-# readline.read_history_file(histfile)
-# except IOError:
-# pass
-#atexit.register(readline.write_history_file, histfile)
-
-CMD_HELP = """Hive commands are preceded by a colon : (just think of vi).
-
-:target name1 name2 name3 ...
-
- set list of hosts to target commands
-
-:target all
-
- reset list of hosts to target all hosts in the hive.
-
-:to name command
-
- send a command line to the named host. This is similar to :target, but
- sends only one command and does not change the list of targets for future
- commands.
-
-:sync
-
- set mode to wait for shell prompts after commands are run. This is the
- default. When Hive first logs into a host it sets a special shell prompt
- pattern that it can later look for to synchronize output of the hosts. If
- you 'su' to another user then it can upset the synchronization. If you need
- to run something like 'su' then use the following pattern:
-
- CMD (? for help) > :async
- CMD (? for help) > sudo su - root
- CMD (? for help) > :prompt
- CMD (? for help) > :sync
-
-:async
-
- set mode to not expect command line prompts (see :sync). Afterwards
- commands are send to target hosts, but their responses are not read back
- until :sync is run. This is useful to run before commands that will not
- return with the special shell prompt pattern that Hive uses to synchronize.
-
-:refresh
-
- refresh the display. This shows the last few lines of output from all hosts.
- This is similar to resync, but does not expect the promt. This is useful
- for seeing what hosts are doing during long running commands.
-
-:resync
-
- This is similar to :sync, but it does not change the mode. It looks for the
- prompt and thus consumes all input from all targetted hosts.
-
-:prompt
-
- force each host to reset command line prompt to the special pattern used to
- synchronize all the hosts. This is useful if you 'su' to a different user
- where Hive would not know the prompt to match.
-
-:send my text
-
- This will send the 'my text' wihtout a line feed to the targetted hosts.
- This output of the hosts is not automatically synchronized.
-
-:control X
-
- This will send the given control character to the targetted hosts.
- For example, ":control c" will send ASCII 3.
-
-:exit
-
- This will exit the hive shell.
-
-"""
-
-
-def login(args, cli_username=None, cli_password=None):
-
- # I have to keep a separate list of host names because Python dicts are not ordered.
- # I want to keep the same order as in the args list.
- host_names = []
- hive_connect_info = {}
- hive = {}
- # build up the list of connection information (hostname, username,
- # password, port)
- for host_connect_string in args:
- hcd = parse_host_connect_string(host_connect_string)
- hostname = hcd['hostname']
- port = hcd['port']
- if port == '':
- port = None
- if len(hcd['username']) > 0:
- username = hcd['username']
- elif cli_username is not None:
- username = cli_username
- else:
- username = raw_input('%s username: ' % hostname)
- if len(hcd['password']) > 0:
- password = hcd['password']
- elif cli_password is not None:
- password = cli_password
- else:
- password = getpass.getpass('%s password: ' % hostname)
- host_names.append(hostname)
- hive_connect_info[hostname] = (hostname, username, password, port)
- # build up the list of hive connections using the connection information.
- for hostname in host_names:
- print 'connecting to', hostname
- try:
- fout = file("log_" + hostname, "w")
- hive[hostname] = pxssh.pxssh()
- hive[hostname].login(*hive_connect_info[hostname])
- print hive[hostname].before
- hive[hostname].logfile = fout
- print '- OK'
- except Exception as e:
- print '- ERROR',
- print str(e)
- print 'Skipping', hostname
- hive[hostname] = None
- return host_names, hive
-
-
-def main():
-
- global options, args, CMD_HELP
-
- if options.sameuser:
- cli_username = raw_input('username: ')
- else:
- cli_username = None
-
- if options.samepass:
- cli_password = getpass.getpass('password: ')
- else:
- cli_password = None
-
- host_names, hive = login(args, cli_username, cli_password)
-
- synchronous_mode = True
- target_hostnames = host_names[:]
- print 'targetting hosts:', ' '.join(target_hostnames)
- while True:
- cmd = raw_input('CMD (? for help) > ')
- cmd = cmd.strip()
- if cmd == '?' or cmd == ':help' or cmd == ':h':
- print CMD_HELP
- continue
- elif cmd == ':refresh':
- refresh(hive, target_hostnames, timeout=0.5)
- for hostname in target_hostnames:
- if hive[hostname] is None:
- print '/============================================================================='
- print '| ' + hostname + ' is DEAD'
- print '\\-----------------------------------------------------------------------------'
- else:
- print '/============================================================================='
- print '| ' + hostname
- print '\\-----------------------------------------------------------------------------'
- print hive[hostname].before
- print '=============================================================================='
- continue
- elif cmd == ':resync':
- resync(hive, target_hostnames, timeout=0.5)
- for hostname in target_hostnames:
- if hive[hostname] is None:
- print '/============================================================================='
- print '| ' + hostname + ' is DEAD'
- print '\\-----------------------------------------------------------------------------'
- else:
- print '/============================================================================='
- print '| ' + hostname
- print '\\-----------------------------------------------------------------------------'
- print hive[hostname].before
- print '=============================================================================='
- continue
- elif cmd == ':sync':
- synchronous_mode = True
- resync(hive, target_hostnames, timeout=0.5)
- continue
- elif cmd == ':async':
- synchronous_mode = False
- continue
- elif cmd == ':prompt':
- for hostname in target_hostnames:
- try:
- if hive[hostname] is not None:
- hive[hostname].set_unique_prompt()
- except Exception as e:
- print "Had trouble communicating with %s, so removing it from the target list." % hostname
- print str(e)
- hive[hostname] = None
- continue
- elif cmd[:5] == ':send':
- cmd, txt = cmd.split(None, 1)
- for hostname in target_hostnames:
- try:
- if hive[hostname] is not None:
- hive[hostname].send(txt)
- except Exception as e:
- print "Had trouble communicating with %s, so removing it from the target list." % hostname
- print str(e)
- hive[hostname] = None
- continue
- elif cmd[:3] == ':to':
- cmd, hostname, txt = cmd.split(None, 2)
- if hive[hostname] is None:
- print '/============================================================================='
- print '| ' + hostname + ' is DEAD'
- print '\\-----------------------------------------------------------------------------'
- continue
- try:
- hive[hostname].sendline(txt)
- hive[hostname].prompt(timeout=2)
- print '/============================================================================='
- print '| ' + hostname
- print '\\-----------------------------------------------------------------------------'
- print hive[hostname].before
- except Exception as e:
- print "Had trouble communicating with %s, so removing it from the target list." % hostname
- print str(e)
- hive[hostname] = None
- continue
- elif cmd[:7] == ':expect':
- cmd, pattern = cmd.split(None, 1)
- print 'looking for', pattern
- try:
- for hostname in target_hostnames:
- if hive[hostname] is not None:
- hive[hostname].expect(pattern)
- print hive[hostname].before
- except Exception as e:
- print "Had trouble communicating with %s, so removing it from the target list." % hostname
- print str(e)
- hive[hostname] = None
- continue
- elif cmd[:7] == ':target':
- target_hostnames = cmd.split()[1:]
- if len(target_hostnames) == 0 or target_hostnames[0] == all:
- target_hostnames = host_names[:]
- print 'targetting hosts:', ' '.join(target_hostnames)
- continue
- elif cmd == ':exit' or cmd == ':q' or cmd == ':quit':
- break
- elif cmd[:8] == ':control' or cmd[:5] == ':ctrl':
- cmd, c = cmd.split(None, 1)
- if ord(c) - 96 < 0 or ord(c) - 96 > 255:
- print '/============================================================================='
- print '| Invalid character. Must be [a-zA-Z], @, [, ], \\, ^, _, or ?'
- print '\\-----------------------------------------------------------------------------'
- continue
- for hostname in target_hostnames:
- try:
- if hive[hostname] is not None:
- hive[hostname].sendcontrol(c)
- except Exception as e:
- print "Had trouble communicating with %s, so removing it from the target list." % hostname
- print str(e)
- hive[hostname] = None
- continue
- elif cmd == ':esc':
- for hostname in target_hostnames:
- if hive[hostname] is not None:
- hive[hostname].send(chr(27))
- continue
- #
- # Run the command on all targets in parallel
- #
- for hostname in target_hostnames:
- try:
- if hive[hostname] is not None:
- hive[hostname].sendline(cmd)
- except Exception as e:
- print "Had trouble communicating with %s, so removing it from the target list." % hostname
- print str(e)
- hive[hostname] = None
-
- #
- # print the response for each targeted host.
- #
- if synchronous_mode:
- for hostname in target_hostnames:
- try:
- if hive[hostname] is None:
- print '/============================================================================='
- print '| ' + hostname + ' is DEAD'
- print '\\-----------------------------------------------------------------------------'
- else:
- hive[hostname].prompt(timeout=2)
- print '/============================================================================='
- print '| ' + hostname
- print '\\-----------------------------------------------------------------------------'
- print hive[hostname].before
- except Exception as e:
- print "Had trouble communicating with %s, so removing it from the target list." % hostname
- print str(e)
- hive[hostname] = None
- print '=============================================================================='
-
-
-def refresh(hive, hive_names, timeout=0.5):
- """This waits for the TIMEOUT on each host.
- """
-
- # TODO This is ideal for threading.
- for hostname in hive_names:
- hive[hostname].expect([pexpect.TIMEOUT, pexpect.EOF], timeout=timeout)
-
-
-def resync(hive, hive_names, timeout=2, max_attempts=5):
- """This waits for the shell prompt for each host in an effort to try to get
- them all to the same state. The timeout is set low so that hosts that are
- already at the prompt will not slow things down too much. If a prompt match
- is made for a hosts then keep asking until it stops matching. This is a
- best effort to consume all input if it printed more than one prompt. It's
- kind of kludgy. Note that this will always introduce a delay equal to the
- timeout for each machine. So for 10 machines with a 2 second delay you will
- get AT LEAST a 20 second delay if not more. """
-
- # TODO This is ideal for threading.
- for hostname in hive_names:
- for attempts in xrange(0, max_attempts):
- if not hive[hostname].prompt(timeout=timeout):
- break
-
-
-def parse_host_connect_string(hcs):
- """This parses a host connection string in the form
- username:password@hostname:port. All fields are options expcet hostname. A
- dictionary is returned with all four keys. Keys that were not included are
- set to empty strings ''. Note that if your password has the '@' character
- then you must backslash escape it. """
-
- if '@' in hcs:
- p = re.compile(
- r'(?P[^@:]*)(:?)(?P.*)(?!\\)@(?P[^:]*):?(?P[0-9]*)')
- else:
- p = re.compile(
- r'(?P)(?P)(?P[^:]*):?(?P[0-9]*)')
- m = p.search(hcs)
- d = m.groupdict()
- d['password'] = d['password'].replace('\\@', '@')
- return d
-
-if __name__ == '__main__':
- try:
- start_time = time.time()
- parser = optparse.OptionParser(
- formatter=optparse.TitledHelpFormatter(),
- usage=globals()['__doc__'],
- version='$Id: hive.py 509 2008-01-05 21:27:47Z noah $',
- conflict_handler="resolve")
- parser.add_option(
- '-v',
- '--verbose',
- action='store_true',
- default=False,
- help='verbose output')
- parser.add_option(
- '--samepass',
- action='store_true',
- default=False,
- help='Use same password for each login.')
- parser.add_option(
- '--sameuser',
- action='store_true',
- default=False,
- help='Use same username for each login.')
- (options, args) = parser.parse_args()
- if len(args) < 1:
- parser.error('missing argument')
- if options.verbose:
- print time.asctime()
- main()
- if options.verbose:
- print time.asctime()
- if options.verbose:
- print 'TOTAL TIME IN MINUTES:',
- if options.verbose:
- print (time.time() - start_time) / 60.0
- sys.exit(0)
- except KeyboardInterrupt as e: # Ctrl-C
- raise e
- except SystemExit as e: # sys.exit()
- raise e
- except Exception as e:
- print 'ERROR, UNEXPECTED EXCEPTION'
- print str(e)
- traceback.print_exc()
- os._exit(1)
Index: third_party/Python/module/pexpect-2.4/examples/monitor.py
===================================================================
--- third_party/Python/module/pexpect-2.4/examples/monitor.py
+++ third_party/Python/module/pexpect-2.4/examples/monitor.py
@@ -1,222 +0,0 @@
-#!/usr/bin/env python
-
-""" This runs a sequence of commands on a remote host using SSH. It runs a
-simple system checks such as uptime and free to monitor the state of the remote
-host.
-
-./monitor.py [-s server_hostname] [-u username] [-p password]
- -s : hostname of the remote server to login to.
- -u : username to user for login.
- -p : Password to user for login.
-
-Example:
- This will print information about the given host:
- ./monitor.py -s www.example.com -u mylogin -p mypassword
-
-It works like this:
- Login via SSH (This is the hardest part).
- Run and parse 'uptime'.
- Run 'iostat'.
- Run 'vmstat'.
- Run 'netstat'
- Run 'free'.
- Exit the remote host.
-"""
-
-import os
-import sys
-import time
-import re
-import getopt
-import getpass
-import traceback
-import pexpect
-
-#
-# Some constants.
-#
-# This is way too simple for industrial use -- we will change is ASAP.
-COMMAND_PROMPT = '[#$] '
-TERMINAL_PROMPT = '(?i)terminal type\?'
-TERMINAL_TYPE = 'vt100'
-# This is the prompt we get if SSH does not have the remote host's public
-# key stored in the cache.
-SSH_NEWKEY = '(?i)are you sure you want to continue connecting'
-
-
-def exit_with_usage():
-
- print globals()['__doc__']
- os._exit(1)
-
-
-def main():
-
- global COMMAND_PROMPT, TERMINAL_PROMPT, TERMINAL_TYPE, SSH_NEWKEY
- ######################################################################
- # Parse the options, arguments, get ready, etc.
- ######################################################################
- try:
- optlist, args = getopt.getopt(
- sys.argv[
- 1:], 'h?s:u:p:', [
- 'help', 'h', '?'])
- except Exception as e:
- print str(e)
- exit_with_usage()
- options = dict(optlist)
- if len(args) > 1:
- exit_with_usage()
-
- if [elem for elem in options if elem in [
- '-h', '--h', '-?', '--?', '--help']]:
- print "Help:"
- exit_with_usage()
-
- if '-s' in options:
- host = options['-s']
- else:
- host = raw_input('hostname: ')
- if '-u' in options:
- user = options['-u']
- else:
- user = raw_input('username: ')
- if '-p' in options:
- password = options['-p']
- else:
- password = getpass.getpass('password: ')
-
- #
- # Login via SSH
- #
- child = pexpect.spawn('ssh -l %s %s' % (user, host))
- i = child.expect([pexpect.TIMEOUT, SSH_NEWKEY,
- COMMAND_PROMPT, '(?i)password'])
- if i == 0: # Timeout
- print 'ERROR! could not login with SSH. Here is what SSH said:'
- print child.before, child.after
- print str(child)
- sys.exit(1)
- if i == 1: # In this case SSH does not have the public key cached.
- child.sendline('yes')
- child.expect('(?i)password')
- if i == 2:
- # This may happen if a public key was setup to automatically login.
- # But beware, the COMMAND_PROMPT at this point is very trivial and
- # could be fooled by some output in the MOTD or login message.
- pass
- if i == 3:
- child.sendline(password)
- # Now we are either at the command prompt or
- # the login process is asking for our terminal type.
- i = child.expect([COMMAND_PROMPT, TERMINAL_PROMPT])
- if i == 1:
- child.sendline(TERMINAL_TYPE)
- child.expect(COMMAND_PROMPT)
- #
- # Set command prompt to something more unique.
- #
- COMMAND_PROMPT = "\[PEXPECT\]\$ "
- child.sendline("PS1='[PEXPECT]\$ '") # In case of sh-style
- i = child.expect([pexpect.TIMEOUT, COMMAND_PROMPT], timeout=10)
- if i == 0:
- print "# Couldn't set sh-style prompt -- trying csh-style."
- child.sendline("set prompt='[PEXPECT]\$ '")
- i = child.expect([pexpect.TIMEOUT, COMMAND_PROMPT], timeout=10)
- if i == 0:
- print "Failed to set command prompt using sh or csh style."
- print "Response was:"
- print child.before
- sys.exit(1)
-
- # Now we should be at the command prompt and ready to run some commands.
- print '---------------------------------------'
- print 'Report of commands run on remote host.'
- print '---------------------------------------'
-
- # Run uname.
- child.sendline('uname -a')
- child.expect(COMMAND_PROMPT)
- print child.before
- if 'linux' in child.before.lower():
- LINUX_MODE = 1
- else:
- LINUX_MODE = 0
-
- # Run and parse 'uptime'.
- child.sendline('uptime')
- child.expect(
- 'up\s+(.*?),\s+([0-9]+) users?,\s+load averages?: ([0-9]+\.[0-9][0-9]),?\s+([0-9]+\.[0-9][0-9]),?\s+([0-9]+\.[0-9][0-9])')
- duration, users, av1, av5, av15 = child.match.groups()
- days = '0'
- hours = '0'
- mins = '0'
- if 'day' in duration:
- child.match = re.search('([0-9]+)\s+day', duration)
- days = str(int(child.match.group(1)))
- if ':' in duration:
- child.match = re.search('([0-9]+):([0-9]+)', duration)
- hours = str(int(child.match.group(1)))
- mins = str(int(child.match.group(2)))
- if 'min' in duration:
- child.match = re.search('([0-9]+)\s+min', duration)
- mins = str(int(child.match.group(1)))
- print
- print 'Uptime: %s days, %s users, %s (1 min), %s (5 min), %s (15 min)' % (
- duration, users, av1, av5, av15)
- child.expect(COMMAND_PROMPT)
-
- # Run iostat.
- child.sendline('iostat')
- child.expect(COMMAND_PROMPT)
- print child.before
-
- # Run vmstat.
- child.sendline('vmstat')
- child.expect(COMMAND_PROMPT)
- print child.before
-
- # Run free.
- if LINUX_MODE:
- child.sendline('free') # Linux systems only.
- child.expect(COMMAND_PROMPT)
- print child.before
-
- # Run df.
- child.sendline('df')
- child.expect(COMMAND_PROMPT)
- print child.before
-
- # Run lsof.
- child.sendline('lsof')
- child.expect(COMMAND_PROMPT)
- print child.before
-
-# # Run netstat
-# child.sendline ('netstat')
-# child.expect (COMMAND_PROMPT)
-# print child.before
-
-# # Run MySQL show status.
-# child.sendline ('mysql -p -e "SHOW STATUS;"')
-# child.expect (PASSWORD_PROMPT_MYSQL)
-# child.sendline (password_mysql)
-# child.expect (COMMAND_PROMPT)
-# print
-# print child.before
-
- # Now exit the remote host.
- child.sendline('exit')
- index = child.expect([pexpect.EOF, "(?i)there are stopped jobs"])
- if index == 1:
- child.sendline("exit")
- child.expect(EOF)
-
-if __name__ == "__main__":
-
- try:
- main()
- except Exception as e:
- print str(e)
- traceback.print_exc()
- os._exit(1)
Index: third_party/Python/module/pexpect-2.4/examples/passmass.py
===================================================================
--- third_party/Python/module/pexpect-2.4/examples/passmass.py
+++ third_party/Python/module/pexpect-2.4/examples/passmass.py
@@ -1,95 +0,0 @@
-#!/usr/bin/env python
-
-"""Change passwords on the named machines. passmass host1 host2 host3 . . .
-Note that login shell prompt on remote machine must end in # or $. """
-
-import pexpect
-import sys
-import getpass
-
-USAGE = '''passmass host1 host2 host3 . . .'''
-COMMAND_PROMPT = '[$#] '
-TERMINAL_PROMPT = r'Terminal type\?'
-TERMINAL_TYPE = 'vt100'
-SSH_NEWKEY = r'Are you sure you want to continue connecting \(yes/no\)\?'
-
-
-def login(host, user, password):
-
- child = pexpect.spawn('ssh -l %s %s' % (user, host))
- fout = file("LOG.TXT", "wb")
- child.setlog(fout)
-
- i = child.expect([pexpect.TIMEOUT, SSH_NEWKEY, '[Pp]assword: '])
- if i == 0: # Timeout
- print 'ERROR!'
- print 'SSH could not login. Here is what SSH said:'
- print child.before, child.after
- sys.exit(1)
- if i == 1: # SSH does not have the public key. Just accept it.
- child.sendline('yes')
- child.expect('[Pp]assword: ')
- child.sendline(password)
- # Now we are either at the command prompt or
- # the login process is asking for our terminal type.
- i = child.expect(['Permission denied', TERMINAL_PROMPT, COMMAND_PROMPT])
- if i == 0:
- print 'Permission denied on host:', host
- sys.exit(1)
- if i == 1:
- child.sendline(TERMINAL_TYPE)
- child.expect(COMMAND_PROMPT)
- return child
-
-# (current) UNIX password:
-
-
-def change_password(child, user, oldpassword, newpassword):
-
- child.sendline('passwd')
- i = child.expect(
- ['[Oo]ld [Pp]assword', '.current.*password', '[Nn]ew [Pp]assword'])
- # Root does not require old password, so it gets to bypass the next step.
- if i == 0 or i == 1:
- child.sendline(oldpassword)
- child.expect('[Nn]ew [Pp]assword')
- child.sendline(newpassword)
- i = child.expect(['[Nn]ew [Pp]assword', '[Rr]etype', '[Rr]e-enter'])
- if i == 0:
- print 'Host did not like new password. Here is what it said...'
- print child.before
- child.send(chr(3)) # Ctrl-C
- child.sendline('') # This should tell remote passwd command to quit.
- return
- child.sendline(newpassword)
-
-
-def main():
-
- if len(sys.argv) <= 1:
- print USAGE
- return 1
-
- user = raw_input('Username: ')
- password = getpass.getpass('Current Password: ')
- newpassword = getpass.getpass('New Password: ')
- newpasswordconfirm = getpass.getpass('Confirm New Password: ')
- if newpassword != newpasswordconfirm:
- print 'New Passwords do not match.'
- return 1
-
- for host in sys.argv[1:]:
- child = login(host, user, password)
- if child is None:
- print 'Could not login to host:', host
- continue
- print 'Changing password on host:', host
- change_password(child, user, password, newpassword)
- child.expect(COMMAND_PROMPT)
- child.sendline('exit')
-
-if __name__ == '__main__':
- try:
- main()
- except pexpect.ExceptionPexpect as e:
- print str(e)
Index: third_party/Python/module/pexpect-2.4/examples/python.py
===================================================================
--- third_party/Python/module/pexpect-2.4/examples/python.py
+++ third_party/Python/module/pexpect-2.4/examples/python.py
@@ -1,21 +0,0 @@
-#!/usr/bin/env python
-
-"""This starts the python interpreter; captures the startup message; then gives
-the user interactive control over the session. Why? For fun... """
-
-# Don't do this unless you like being John Malkovich
-# c = pexpect.spawn ('/usr/bin/env python ./python.py')
-
-import pexpect
-c = pexpect.spawn('/usr/bin/env python')
-c.expect('>>>')
-print 'And now for something completely different...'
-f = lambda s: s and f(s[1:]) + s[0] # Makes a function to reverse a string.
-print f(c.before)
-print 'Yes, it\'s python, but it\'s backwards.'
-print
-print 'Escape character is \'^]\'.'
-print c.after,
-c.interact()
-c.kill(1)
-print 'is alive:', c.isalive()
Index: third_party/Python/module/pexpect-2.4/examples/rippy.py
===================================================================
--- third_party/Python/module/pexpect-2.4/examples/rippy.py
+++ third_party/Python/module/pexpect-2.4/examples/rippy.py
@@ -1,1322 +0,0 @@
-#!/usr/bin/env python
-
-"""Rippy!
-
-This script helps to convert video from one format to another.
-This is useful for ripping DVD to mpeg4 video (XviD, DivX).
-
-Features:
- * automatic crop detection
- * mp3 audio compression with resampling options
- * automatic bitrate calculation based on desired target size
- * optional interlace removal, b/w video optimization, video scaling
-
-Run the script with no arguments to start with interactive prompts:
- rippy.py
-Run the script with the filename of a config to start automatic mode:
- rippy.py rippy.conf
-
-After Rippy is finished it saves the current configuation in a file called
-'rippy.conf' in the local directoy. This can be used to rerun process using the
-exact same settings by passing the filename of the conf file as an argument to
-Rippy. Rippy will read the options from the file instead of asking you for
-options interactively. So if you run rippy with 'dry_run=1' then you can run
-the process again later using the 'rippy.conf' file. Don't forget to edit
-'rippy.conf' to set 'dry_run=0'!
-
-If you run rippy with 'dry_run' and 'verbose' true then the output generated is
-valid command line commands. you could (in theory) cut-and-paste the commands
-to a shell prompt. You will need to tweak some values such as crop area and bit
-rate because these cannot be calculated in a dry run. This is useful if you
-want to get an idea of what Rippy plans to do.
-
-For all the trouble that Rippy goes through to calculate the best bitrate for a
-desired target video size it sometimes fails to get it right. Sometimes the
-final video size will differ more than you wanted from the desired size, but if
-you are really motivated and have a lot of time on your hands then you can run
-Rippy again with a manually calculated bitrate. After all compression is done
-the first time Rippy will recalculate the bitrate to give you the nearly exact
-bitrate that would have worked. You can then edit the 'rippy.conf' file; set
-the video_bitrate with this revised bitrate; and then run Rippy all over again.
-There is nothing like 4-pass video compression to get it right! Actually, this
-could be done in three passes since I don't need to do the second pass
-compression before I calculate the revised bitrate. I'm also considering an
-enhancement where Rippy would compress ten spread out chunks, 1-minute in
-length to estimate the bitrate.
-
-Free, open source, and all that good stuff.
-Rippy Copyright (c) 2006 Noah Spurrier
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Noah Spurrier
-$Id: rippy.py 517 2008-08-18 22:23:56Z noah $
-"""
-
-import sys
-import os
-import re
-import math
-import stat
-import getopt
-import traceback
-import types
-import time
-import pexpect
-
-__version__ = '1.2'
-__revision__ = '$Revision: 11 $'
-__all__ = ['main', __version__, __revision__]
-
-GLOBAL_LOGFILE_NAME = "rippy_%d.log" % os.getpid()
-GLOBAL_LOGFILE = open(GLOBAL_LOGFILE_NAME, "wb")
-
-###############################################################################
-# This giant section defines the prompts and defaults used in interactive mode.
-###############################################################################
-# Python dictionaries are unordered, so
-# I have this list that maintains the order of the keys.
-prompts_key_order = (
- 'verbose_flag',
- 'dry_run_flag',
- 'video_source_filename',
- 'video_chapter',
- 'video_final_filename',
- 'video_length',
- 'video_aspect_ratio',
- 'video_scale',
- 'video_encode_passes',
- 'video_codec',
- 'video_fourcc_override',
- 'video_bitrate',
- 'video_bitrate_overhead',
- 'video_target_size',
- 'video_deinterlace_flag',
- 'video_crop_area',
- 'video_gray_flag',
- 'subtitle_id',
- 'audio_id',
- 'audio_codec',
- 'audio_raw_filename',
- 'audio_volume_boost',
- 'audio_sample_rate',
- 'audio_bitrate',
- #'audio_lowpass_filter',
- 'delete_tmp_files_flag'
-)
-#
-# The 'prompts' dictionary holds all the messages shown to the user in
-# interactive mode. The 'prompts' dictionary schema is defined as follows:
-# prompt_key : ( default value, prompt string, help string, level of difficulty (0,1,2) )
-#
-prompts = {
- 'video_source_filename': ("dvd://1", 'video source filename?', """This is the filename of the video that you want to convert from.
-It can be any file that mencoder supports.
-You can also choose a DVD device using the dvd://1 syntax.
-Title 1 is usually the main title on a DVD.""", 0),
- 'video_chapter': ("none", 'video chapter?', """This is the chapter number. Usually disks such as TV series seasons will be divided into chapters. Maybe be set to none.""", 0),
- 'video_final_filename': ("video_final.avi", "video final filename?", """This is the name of the final video.""", 0),
- 'audio_raw_filename': ("audiodump.wav", "audio raw filename?", """This is the audio raw PCM filename. This is prior to compression.
-Note that mplayer automatically names this audiodump.wav, so don't change this.""", 1000),
- #'audio_compressed_filename':("audiodump.mp3","Audio compressed filename?", """This is the name of the compressed audio that will be mixed
- # into the final video. Normally you don't need to change this.""",2),
- 'video_length': ("none", "video length in seconds?", """This sets the length of the video in seconds. This is used to estimate the
-bitrate for a target video file size. Set to 'calc' to have Rippy calculate
-the length. Set to 'none' if you don't want rippy to estimate the bitrate --
-you will have to manually specify bitrate.""", 1),
- 'video_aspect_ratio': ("calc", "aspect ratio?", """This sets the aspect ratio of the video. Most DVDs are 16/9 or 4/3.""", 1),
- 'video_scale': ("none", "video scale?", """This scales the video to the given output size. The default is to do no scaling.
-You may type in a resolution such as 320x240 or you may use presets.
- qntsc: 352x240 (NTSC quarter screen)
- qpal: 352x288 (PAL quarter screen)
- ntsc: 720x480 (standard NTSC)
- pal: 720x576 (standard PAL)
- sntsc: 640x480 (square pixel NTSC)
- spal: 768x576 (square pixel PAL)""", 1),
- 'video_codec': ("mpeg4", "video codec?", """This is the video compression to use. This is passed directly to mencoder, so
-any format that it recognizes should work. For XviD or DivX use mpeg4.
-Almost all MS Windows systems support wmv2 out of the box.
-Some common codecs include:
-mjpeg, h263, h263p, h264, mpeg4, msmpeg4, wmv1, wmv2, mpeg1video, mpeg2video, huffyuv, ffv1.
-""", 2),
- 'audio_codec': ("mp3", "audio codec?", """This is the audio compression to use. This is passed directly to mencoder, so
-any format that it recognizes will work.
-Some common codecs include:
-mp3, mp2, aac, pcm
-See mencoder manual for details.""", 2),
- 'video_fourcc_override': ("XVID", "force fourcc code?", """This forces the fourcc codec to the given value. XVID is safest for Windows.
-The following are common fourcc values:
- FMP4 - This is the mencoder default. This is the "real" value.
- XVID - used by Xvid (safest)
- DX50 -
- MP4S - Microsoft""", 2),
- 'video_encode_passes': ("1", "number of encode passes?", """This sets how many passes to use to encode the video. You can choose 1 or 2.
-Using two pases takes twice as long as one pass, but produces a better
-quality video. I found that the improvement is not that impressive.""", 1),
- 'verbose_flag': ("Y", "verbose output?", """This sets verbose output. If true then all commands and arguments are printed
-before they are run. This is useful to see exactly how commands are run.""", 1),
- 'dry_run_flag': ("N", "dry run?", """This sets 'dry run' mode. If true then commands are not run. This is useful
-if you want to see what would the script would do.""", 1),
- 'video_bitrate': ("calc", "video bitrate?", """This sets the video bitrate. This overrides video_target_size.
-Set to 'calc' to automatically estimate the bitrate based on the
-video final target size. If you set video_length to 'none' then
-you will have to specify this video_bitrate.""", 1),
- 'video_target_size': ("737280000", "video final target size?", """This sets the target video size that you want to end up with.
-This is over-ridden by video_bitrate. In other words, if you specify
-video_bitrate then video_target_size is ignored.
-Due to the unpredictable nature of VBR compression the final video size
-may not exactly match. The following are common CDR sizes:
- 180MB CDR (21 minutes) holds 193536000 bytes
- 550MB CDR (63 minutes) holds 580608000 bytes
- 650MB CDR (74 minutes) holds 681984000 bytes
- 700MB CDR (80 minutes) holds 737280000 bytes""", 0),
- 'video_bitrate_overhead': ("1.0", "bitrate overhead factor?", """Adjust this value if you want to leave more room for
-other files such as subtitle files.
-If you specify video_bitrate then this value is ignored.""", 2),
- 'video_crop_area': ("detect", "crop area?", """This sets the crop area to remove black bars from the top or sides of the video.
-This helps save space. Set to 'detect' to automatically detect the crop area.
-Set to 'none' to not crop the video. Normally you don't need to change this.""", 1),
- 'video_deinterlace_flag': ("N", "is the video interlaced?", """This sets the deinterlace flag. If set then mencoder will be instructed
-to filter out interlace artifacts (using '-vf pp=md').""", 1),
- 'video_gray_flag': ("N", "is the video black and white (gray)?", """This improves output for black and white video.""", 1),
- 'subtitle_id': ("None", "Subtitle ID stream?", """This selects the subtitle stream to extract from the source video.
-Normally, 0 is the English subtitle stream for a DVD.
-Subtitles IDs with higher numbers may be other languages.""", 1),
- 'audio_id': ("128", "audio ID stream?", """This selects the audio stream to extract from the source video.
-If your source is a VOB file (DVD) then stream IDs start at 128.
-Normally, 128 is the main audio track for a DVD.
-Tracks with higher numbers may be other language dubs or audio commentary.""", 1),
- 'audio_sample_rate': ("32000", "audio sample rate (Hz) 48000, 44100, 32000, 24000, 12000", """This sets the rate at which the compressed audio will be resampled.
-DVD audio is 48 kHz whereas music CDs use 44.1 kHz. The higher the sample rate
-the more space the audio track will take. That will leave less space for video.
-32 kHz is a good trade-off if you are trying to fit a video onto a CD.""", 1),
- 'audio_bitrate': ("96", "audio bitrate (kbit/s) 192, 128, 96, 64?", """This sets the bitrate for MP3 audio compression.
-The higher the bitrate the more space the audio track will take.
-That will leave less space for video. Most people find music to be acceptable
-at 128 kBitS. 96 kBitS is a good trade-off if you are trying to fit a video onto a CD.""", 1),
- 'audio_volume_boost': ("none", "volume dB boost?", """Many DVDs have very low audio volume. This sets an audio volume boost in Decibels.
-Values of 6 to 10 usually adjust quiet DVDs to a comfortable level.""", 1),
- #'audio_lowpass_filter':("16","audio lowpass filter (kHz)?","""This sets the low-pass filter for the audio.
- # Normally this should be half of the audio sample rate.
- # This improves audio compression and quality.
- # Normally you don't need to change this.""",1),
- 'delete_tmp_files_flag': ("N", "delete temporary files when finished?", """If Y then %s, audio_raw_filename, and 'divx2pass.log' will be deleted at the end.""" % GLOBAL_LOGFILE_NAME, 1)
-}
-
-##############################################################################
-# This is the important convert control function
-##############################################################################
-
-
-def convert(options):
- """This is the heart of it all -- this performs an end-to-end conversion of
- a video from one format to another. It requires a dictionary of options.
- The conversion process will also add some keys to the dictionary
- such as length of the video and crop area. The dictionary is returned.
- This options dictionary could be used again to repeat the convert process
- (it is also saved to rippy.conf as text).
- """
- if options['subtitle_id'] is not None:
- print "# extract subtitles"
- apply_smart(extract_subtitles, options)
- else:
- print "# do not extract subtitles."
-
- # Optimization
- # I really only need to calculate the exact video length if the user
- # selected 'calc' for video_bitrate
- # or
- # selected 'detect' for video_crop_area.
- if options['video_bitrate'] == 'calc' or options[
- 'video_crop_area'] == 'detect':
- # As strange as it seems, the only reliable way to calculate the length
- # of a video (in seconds) is to extract the raw, uncompressed PCM audio stream
- # and then calculate the length of that. This is because MP4 video is VBR, so
- # you cannot get exact time based on compressed size.
- if options['video_length'] == 'calc':
- print "# extract PCM raw audio to %s" % (options['audio_raw_filename'])
- apply_smart(extract_audio, options)
- options['video_length'] = apply_smart(get_length, options)
- print "# Length of raw audio file : %d seconds (%0.2f minutes)" % (options['video_length'], float(options['video_length']) / 60.0)
- if options['video_bitrate'] == 'calc':
- options['video_bitrate'] = options[
- 'video_bitrate_overhead'] * apply_smart(calc_video_bitrate, options)
- print "# video bitrate : " + str(options['video_bitrate'])
- if options['video_crop_area'] == 'detect':
- options['video_crop_area'] = apply_smart(crop_detect, options)
- print "# crop area : " + str(options['video_crop_area'])
- print "# compression estimate"
- print apply_smart(compression_estimate, options)
-
- print "# compress video"
- apply_smart(compress_video, options)
- 'audio_volume_boost',
-
- print "# delete temporary files:",
- if options['delete_tmp_files_flag']:
- print "yes"
- apply_smart(delete_tmp_files, options)
- else:
- print "no"
-
- # Finish by saving options to rippy.conf and
- # calclating if final_size is less than target_size.
- o = ["# options used to create video\n"]
- video_actual_size = get_filesize(options['video_final_filename'])
- if options['video_target_size'] != 'none':
- revised_bitrate = calculate_revised_bitrate(
- options['video_bitrate'],
- options['video_target_size'],
- video_actual_size)
- o.append("# revised video_bitrate : %d\n" % revised_bitrate)
- for k, v in options.iteritems():
- o.append(" %30s : %s\n" % (k, v))
- print '# '.join(o)
- fout = open("rippy.conf", "wb").write(''.join(o))
- print "# final actual video size = %d" % video_actual_size
- if options['video_target_size'] != 'none':
- if video_actual_size > options['video_target_size']:
- print "# FINAL VIDEO SIZE IS GREATER THAN DESIRED TARGET"
- print "# final video size is %d bytes over target size" % (video_actual_size - options['video_target_size'])
- else:
- print "# final video size is %d bytes under target size" % (options['video_target_size'] - video_actual_size)
- print "# If you want to run the entire compression process all over again"
- print "# to get closer to the target video size then trying using a revised"
- print "# video_bitrate of %d" % revised_bitrate
-
- return options
-
-##############################################################################
-
-
-def exit_with_usage(exit_code=1):
- print globals()['__doc__']
- print 'version:', globals()['__version__']
- sys.stdout.flush()
- os._exit(exit_code)
-
-
-def check_missing_requirements():
- """This list of missing requirements (mencoder, mplayer, lame, and mkvmerge).
- Returns None if all requirements are in the execution path.
- """
- missing = []
- if pexpect.which("mencoder") is None:
- missing.append("mencoder")
- if pexpect.which("mplayer") is None:
- missing.append("mplayer")
- cmd = "mencoder -oac help"
- (command_output, exitstatus) = run(cmd)
- ar = re.findall("(mp3lame)", command_output)
- if len(ar) == 0:
- missing.append("Mencoder was not compiled with mp3lame support.")
-
- # if pexpect.which("lame") is None:
- # missing.append("lame")
- # if pexpect.which("mkvmerge") is None:
- # missing.append("mkvmerge")
- if len(missing) == 0:
- return None
- return missing
-
-
-def input_option(message, default_value="", help=None, level=0, max_level=0):
- """This is a fancy raw_input function.
- If the user enters '?' then the contents of help is printed.
-
- The 'level' and 'max_level' are used to adjust which advanced options
- are printed. 'max_level' is the level of options that the user wants
- to see. 'level' is the level of difficulty for this particular option.
- If this level is <= the max_level the user wants then the
- message is printed and user input is allowed; otherwise, the
- default value is returned automatically without user input.
- """
- if default_value != '':
- message = "%s [%s] " % (message, default_value)
- if level > max_level:
- return default_value
- while True:
- user_input = raw_input(message)
- if user_input == '?':
- print help
- elif user_input == '':
- return default_value
- else:
- break
- return user_input
-
-
-def progress_callback(d=None):
- """This callback simply prints a dot to show activity.
- This is used when running external commands with pexpect.run.
- """
- sys.stdout.write(".")
- sys.stdout.flush()
-
-
-def run(cmd):
- global GLOBAL_LOGFILE
- print >>GLOBAL_LOGFILE, cmd
- (command_output,
- exitstatus) = pexpect.run(cmd,
- events={pexpect.TIMEOUT: progress_callback},
- timeout=5,
- withexitstatus=True,
- logfile=GLOBAL_LOGFILE)
- if exitstatus != 0:
- print "RUN FAILED. RETURNED EXIT STATUS:", exitstatus
- print >>GLOBAL_LOGFILE, "RUN FAILED. RETURNED EXIT STATUS:", exitstatus
- return (command_output, exitstatus)
-
-
-def apply_smart(func, args):
- """This is similar to func(**args), but this won't complain about
- extra keys in 'args'. This ignores keys in 'args' that are
- not required by 'func'. This passes None to arguments that are
- not defined in 'args'. That's fine for arguments with a default valeue, but
- that's a bug for required arguments. I should probably raise a TypeError.
- The func parameter can be a function reference or a string.
- If it is a string then it is converted to a function reference.
- """
- if isinstance(func, type('')):
- if func in globals():
- func = globals()[func]
- else:
- raise NameError("name '%s' is not defined" % func)
- if hasattr(func, 'im_func'): # Handle case when func is a class method.
- func = func.im_func
- argcount = func.func_code.co_argcount
- required_args = dict([(k, args.get(k))
- for k in func.func_code.co_varnames[:argcount]])
- return func(**required_args)
-
-
-def count_unique(items):
- """This takes a list and returns a sorted list of tuples with a count of each unique item in the list.
- Example 1:
- count_unique(['a','b','c','a','c','c','a','c','c'])
- returns:
- [(5,'c'), (3,'a'), (1,'b')]
- Example 2 -- get the most frequent item in a list:
- count_unique(['a','b','c','a','c','c','a','c','c'])[0][1]
- returns:
- 'c'
- """
- stats = {}
- for i in items:
- if i in stats:
- stats[i] = stats[i] + 1
- else:
- stats[i] = 1
- stats = sorted([(v, k) for k, v in stats.items()])
- stats.reverse()
- return stats
-
-
-def calculate_revised_bitrate(
- video_bitrate,
- video_target_size,
- video_actual_size):
- """This calculates a revised video bitrate given the video_bitrate used,
- the actual size that resulted, and the video_target_size.
- This can be used if you want to compress the video all over again in an
- attempt to get closer to the video_target_size.
- """
- return int(math.floor(video_bitrate * \
- (float(video_target_size) / float(video_actual_size))))
-
-
-def get_aspect_ratio(video_source_filename):
- """This returns the aspect ratio of the original video.
- This is usualy 1.78:1(16/9) or 1.33:1(4/3).
- This function is very lenient. It basically guesses 16/9 whenever
- it cannot figure out the aspect ratio.
- """
- cmd = "mplayer '%s' -vo png -ao null -frames 1" % video_source_filename
- (command_output, exitstatus) = run(cmd)
- ar = re.findall(
- "Movie-Aspect is ([0-9]+\.?[0-9]*:[0-9]+\.?[0-9]*)",
- command_output)
- if len(ar) == 0:
- return '16/9'
- if ar[0] == '1.78:1':
- return '16/9'
- if ar[0] == '1.33:1':
- return '4/3'
- return '16/9'
- #idh = re.findall("ID_VIDEO_HEIGHT=([0-9]+)", command_output)
- # if len(idw)==0 or len(idh)==0:
- # print 'WARNING!'
- # print 'Could not get aspect ration. Assuming 1.78:1 (16/9).'
- # return 1.78
- # return float(idw[0])/float(idh[0])
-# ID_VIDEO_WIDTH=720
-# ID_VIDEO_HEIGHT=480
-# Movie-Aspect is 1.78:1 - prescaling to correct movie aspect.
-
-
-def get_aid_list(video_source_filename):
- """This returns a list of audio ids in the source video file.
- TODO: Also extract ID_AID_nnn_LANG to associate language. Not all DVDs include this.
- """
- cmd = "mplayer '%s' -vo null -ao null -frames 0 -identify" % video_source_filename
- (command_output, exitstatus) = run(cmd)
- idl = sorted(re.findall("ID_AUDIO_ID=([0-9]+)", command_output))
- return idl
-
-
-def get_sid_list(video_source_filename):
- """This returns a list of subtitle ids in the source video file.
- TODO: Also extract ID_SID_nnn_LANG to associate language. Not all DVDs include this.
- """
- cmd = "mplayer '%s' -vo null -ao null -frames 0 -identify" % video_source_filename
- (command_output, exitstatus) = run(cmd)
- idl = sorted(re.findall("ID_SUBTITLE_ID=([0-9]+)", command_output))
- return idl
-
-
-def extract_audio(
- video_source_filename,
- audio_id=128,
- verbose_flag=0,
- dry_run_flag=0):
- """This extracts the given audio_id track as raw uncompressed PCM from the given source video.
- Note that mplayer always saves this to audiodump.wav.
- At this time there is no way to set the output audio name.
- """
- #cmd = "mplayer %(video_source_filename)s -vc null -vo null -aid %(audio_id)s -ao pcm:fast -noframedrop" % locals()
- cmd = "mplayer -quiet '%(video_source_filename)s' -vc dummy -vo null -aid %(audio_id)s -ao pcm:fast -noframedrop" % locals()
- if verbose_flag:
- print cmd
- if not dry_run_flag:
- run(cmd)
- print
-
-
-def extract_subtitles(
- video_source_filename,
- subtitle_id=0,
- verbose_flag=0,
- dry_run_flag=0):
- """This extracts the given subtitle_id track as VOBSUB format from the given source video.
- """
- cmd = "mencoder -quiet '%(video_source_filename)s' -o /dev/null -nosound -ovc copy -vobsubout subtitles -vobsuboutindex 0 -sid %(subtitle_id)s" % locals()
- if verbose_flag:
- print cmd
- if not dry_run_flag:
- run(cmd)
- print
-
-
-def get_length(audio_raw_filename):
- """This attempts to get the length of the media file (length is time in seconds).
- This should not be confused with size (in bytes) of the file data.
- This is best used on a raw PCM AUDIO file because mplayer cannot get an accurate
- time for many compressed video and audio formats -- notably MPEG4 and MP3.
- Weird...
- This returns -1 if it cannot get the length of the given file.
- """
- cmd = "mplayer %s -vo null -ao null -frames 0 -identify" % audio_raw_filename
- (command_output, exitstatus) = run(cmd)
- idl = sorted(re.findall("ID_LENGTH=([0-9.]*)", command_output))
- if len(idl) != 1:
- print "ERROR: cannot get length of raw audio file."
- print "command_output of mplayer identify:"
- print command_output
- print "parsed command_output:"
- print str(idl)
- return -1
- return float(idl[0])
-
-
-def get_filesize(filename):
- """This returns the number of bytes a file takes on storage."""
- return os.stat(filename)[stat.ST_SIZE]
-
-
-def calc_video_bitrate(
- video_target_size,
- audio_bitrate,
- video_length,
- extra_space=0,
- dry_run_flag=0):
- """This gives an estimate of the video bitrate necessary to
- fit the final target size. This will take into account room to
- fit the audio and extra space if given (for container overhead or whatnot).
- video_target_size is in bytes,
- audio_bitrate is bits per second (96, 128, 256, etc.) ASSUMING CBR,
- video_length is in seconds,
- extra_space is in bytes.
- a 180MB CDR (21 minutes) holds 193536000 bytes.
- a 550MB CDR (63 minutes) holds 580608000 bytes.
- a 650MB CDR (74 minutes) holds 681984000 bytes.
- a 700MB CDR (80 minutes) holds 737280000 bytes.
- """
- if dry_run_flag:
- return -1
- if extra_space is None:
- extra_space = 0
- #audio_size = os.stat(audio_compressed_filename)[stat.ST_SIZE]
- audio_size = (audio_bitrate * video_length * 1000) / 8.0
- video_target_size = video_target_size - audio_size - extra_space
- return (int)(calc_video_kbitrate(video_target_size, video_length))
-
-
-def calc_video_kbitrate(target_size, length_secs):
- """Given a target byte size free for video data, this returns the bitrate in kBit/S.
- For mencoder vbitrate 1 kBit = 1000 Bits -- not 1024 bits.
- target_size = bitrate * 1000 * length_secs / 8
- target_size = bitrate * 125 * length_secs
- bitrate = target_size/(125*length_secs)
- """
- return int(target_size / (125.0 * length_secs))
-
-
-def crop_detect(video_source_filename, video_length, dry_run_flag=0):
- """This attempts to figure out the best crop for the given video file.
- Basically it runs crop detect for 10 seconds on five different places in the video.
- It picks the crop area that was most often detected.
- """
- skip = int(video_length / 9) # offset to skip (-ss option in mencoder)
- sample_length = 10
- cmd1 = "mencoder '%s' -quiet -ss %d -endpos %d -o /dev/null -nosound -ovc lavc -vf cropdetect" % (
- video_source_filename, skip, sample_length)
- cmd2 = "mencoder '%s' -quiet -ss %d -endpos %d -o /dev/null -nosound -ovc lavc -vf cropdetect" % (
- video_source_filename, 2 * skip, sample_length)
- cmd3 = "mencoder '%s' -quiet -ss %d -endpos %d -o /dev/null -nosound -ovc lavc -vf cropdetect" % (
- video_source_filename, 4 * skip, sample_length)
- cmd4 = "mencoder '%s' -quiet -ss %d -endpos %d -o /dev/null -nosound -ovc lavc -vf cropdetect" % (
- video_source_filename, 6 * skip, sample_length)
- cmd5 = "mencoder '%s' -quiet -ss %d -endpos %d -o /dev/null -nosound -ovc lavc -vf cropdetect" % (
- video_source_filename, 8 * skip, sample_length)
- if dry_run_flag:
- return "0:0:0:0"
- (command_output1, exitstatus1) = run(cmd1)
- (command_output2, exitstatus2) = run(cmd2)
- (command_output3, exitstatus3) = run(cmd3)
- (command_output4, exitstatus4) = run(cmd4)
- (command_output5, exitstatus5) = run(cmd5)
- idl = re.findall("-vf crop=([0-9]+:[0-9]+:[0-9]+:[0-9]+)", command_output1)
- idl = idl + \
- re.findall("-vf crop=([0-9]+:[0-9]+:[0-9]+:[0-9]+)", command_output2)
- idl = idl + \
- re.findall("-vf crop=([0-9]+:[0-9]+:[0-9]+:[0-9]+)", command_output3)
- idl = idl + \
- re.findall("-vf crop=([0-9]+:[0-9]+:[0-9]+:[0-9]+)", command_output4)
- idl = idl + \
- re.findall("-vf crop=([0-9]+:[0-9]+:[0-9]+:[0-9]+)", command_output5)
- items_count = count_unique(idl)
- return items_count[0][1]
-
-
-def build_compression_command(
- video_source_filename,
- video_final_filename,
- video_target_size,
- audio_id=128,
- video_bitrate=1000,
- video_codec='mpeg4',
- audio_codec='mp3',
- video_fourcc_override='FMP4',
- video_gray_flag=0,
- video_crop_area=None,
- video_aspect_ratio='16/9',
- video_scale=None,
- video_encode_passes=2,
- video_deinterlace_flag=0,
- audio_volume_boost=None,
- audio_sample_rate=None,
- audio_bitrate=None,
- seek_skip=None,
- seek_length=None,
- video_chapter=None):
- # Notes:For DVD, VCD, and SVCD use acodec=mp2 and vcodec=mpeg2video:
- # mencoder movie.avi -o movie.VOB -ovc lavc -oac lavc -lavcopts
- # acodec=mp2:abitrate=224:vcodec=mpeg2video:vbitrate=2000
-
- #
- # build video filter (-vf) argument
- #
- video_filter = ''
- if video_crop_area and video_crop_area.lower() != 'none':
- video_filter = video_filter + 'crop=%s' % video_crop_area
- if video_deinterlace_flag:
- if video_filter != '':
- video_filter = video_filter + ','
- video_filter = video_filter + 'pp=md'
- if video_scale and video_scale.lower() != 'none':
- if video_filter != '':
- video_filter = video_filter + ','
- video_filter = video_filter + 'scale=%s' % video_scale
- # optional video rotation -- were you holding your camera sideways?
- # if video_filter != '':
- # video_filter = video_filter + ','
- #video_filter = video_filter + 'rotate=2'
- if video_filter != '':
- video_filter = '-vf ' + video_filter
-
- #
- # build chapter argument
- #
- if video_chapter is not None:
- chapter = '-chapter %d-%d' % (video_chapter, video_chapter)
- else:
- chapter = ''
-# chapter = '-chapter 2-2'
-
- #
- # build audio_filter argument
- #
- audio_filter = ''
- if audio_sample_rate:
- if audio_filter != '':
- audio_filter = audio_filter + ','
- audio_filter = audio_filter + 'lavcresample=%s' % audio_sample_rate
- if audio_volume_boost is not None:
- if audio_filter != '':
- audio_filter = audio_filter + ','
- audio_filter = audio_filter + 'volume=%0.1f:1' % audio_volume_boost
- if audio_filter != '':
- audio_filter = '-af ' + audio_filter
- #
- # if audio_sample_rate:
- # audio_filter = ('-srate %d ' % audio_sample_rate) + audio_filter
-
- #
- # build lavcopts argument
- #
- #lavcopts = '-lavcopts vcodec=%s:vbitrate=%d:mbd=2:aspect=%s:acodec=%s:abitrate=%d:vpass=1' % (video_codec,video_bitrate,audio_codec,audio_bitrate)
- lavcopts = '-lavcopts vcodec=%(video_codec)s:vbitrate=%(video_bitrate)d:mbd=2:aspect=%(video_aspect_ratio)s:acodec=%(audio_codec)s:abitrate=%(audio_bitrate)d:vpass=1' % (locals())
- if video_gray_flag:
- lavcopts = lavcopts + ':gray'
-
- seek_filter = ''
- if seek_skip is not None:
- seek_filter = '-ss %s' % (str(seek_skip))
- if seek_length is not None:
- seek_filter = seek_filter + ' -endpos %s' % (str(seek_length))
-
-# cmd = "mencoder -quiet -info comment='Arkivist' '%(video_source_filename)s' %(seek_filter)s %(chapter)s -aid %(audio_id)s -o '%(video_final_filename)s' -ffourcc %(video_fourcc_override)s -ovc lavc -oac lavc %(lavcopts)s %(video_filter)s %(audio_filter)s" % locals()
- cmd = "mencoder -quiet -info comment='Arkivist' '%(video_source_filename)s' %(seek_filter)s %(chapter)s -aid %(audio_id)s -o '%(video_final_filename)s' -ffourcc %(video_fourcc_override)s -ovc lavc -oac mp3lame %(lavcopts)s %(video_filter)s %(audio_filter)s" % locals()
- return cmd
-
-
-def compression_estimate(
- video_length,
- video_source_filename,
- video_final_filename,
- video_target_size,
- audio_id=128,
- video_bitrate=1000,
- video_codec='mpeg4',
- audio_codec='mp3',
- video_fourcc_override='FMP4',
- video_gray_flag=0,
- video_crop_area=None,
- video_aspect_ratio='16/9',
- video_scale=None,
- video_encode_passes=2,
- video_deinterlace_flag=0,
- audio_volume_boost=None,
- audio_sample_rate=None,
- audio_bitrate=None):
- """This attempts to figure out the best compression ratio for a given set of compression options.
- """
- # TODO Need to account for AVI overhead.
- skip = int(video_length / 9) # offset to skip (-ss option in mencoder)
- sample_length = 10
- cmd1 = build_compression_command(
- video_source_filename,
- "compression_test_1.avi",
- video_target_size,
- audio_id,
- video_bitrate,
- video_codec,
- audio_codec,
- video_fourcc_override,
- video_gray_flag,
- video_crop_area,
- video_aspect_ratio,
- video_scale,
- video_encode_passes,
- video_deinterlace_flag,
- audio_volume_boost,
- audio_sample_rate,
- audio_bitrate,
- skip,
- sample_length)
- cmd2 = build_compression_command(
- video_source_filename,
- "compression_test_2.avi",
- video_target_size,
- audio_id,
- video_bitrate,
- video_codec,
- audio_codec,
- video_fourcc_override,
- video_gray_flag,
- video_crop_area,
- video_aspect_ratio,
- video_scale,
- video_encode_passes,
- video_deinterlace_flag,
- audio_volume_boost,
- audio_sample_rate,
- audio_bitrate,
- skip * 2,
- sample_length)
- cmd3 = build_compression_command(
- video_source_filename,
- "compression_test_3.avi",
- video_target_size,
- audio_id,
- video_bitrate,
- video_codec,
- audio_codec,
- video_fourcc_override,
- video_gray_flag,
- video_crop_area,
- video_aspect_ratio,
- video_scale,
- video_encode_passes,
- video_deinterlace_flag,
- audio_volume_boost,
- audio_sample_rate,
- audio_bitrate,
- skip * 4,
- sample_length)
- cmd4 = build_compression_command(
- video_source_filename,
- "compression_test_4.avi",
- video_target_size,
- audio_id,
- video_bitrate,
- video_codec,
- audio_codec,
- video_fourcc_override,
- video_gray_flag,
- video_crop_area,
- video_aspect_ratio,
- video_scale,
- video_encode_passes,
- video_deinterlace_flag,
- audio_volume_boost,
- audio_sample_rate,
- audio_bitrate,
- skip * 6,
- sample_length)
- cmd5 = build_compression_command(
- video_source_filename,
- "compression_test_5.avi",
- video_target_size,
- audio_id,
- video_bitrate,
- video_codec,
- audio_codec,
- video_fourcc_override,
- video_gray_flag,
- video_crop_area,
- video_aspect_ratio,
- video_scale,
- video_encode_passes,
- video_deinterlace_flag,
- audio_volume_boost,
- audio_sample_rate,
- audio_bitrate,
- skip * 8,
- sample_length)
- run(cmd1)
- run(cmd2)
- run(cmd3)
- run(cmd4)
- run(cmd5)
- size = get_filesize("compression_test_1.avi") + get_filesize("compression_test_2.avi") + get_filesize(
- "compression_test_3.avi") + get_filesize("compression_test_4.avi") + get_filesize("compression_test_5.avi")
- return (size / 5.0)
-
-
-def compress_video(
- video_source_filename,
- video_final_filename,
- video_target_size,
- audio_id=128,
- video_bitrate=1000,
- video_codec='mpeg4',
- audio_codec='mp3',
- video_fourcc_override='FMP4',
- video_gray_flag=0,
- video_crop_area=None,
- video_aspect_ratio='16/9',
- video_scale=None,
- video_encode_passes=2,
- video_deinterlace_flag=0,
- audio_volume_boost=None,
- audio_sample_rate=None,
- audio_bitrate=None,
- seek_skip=None,
- seek_length=None,
- video_chapter=None,
- verbose_flag=0,
- dry_run_flag=0):
- """This compresses the video and audio of the given source video filename to the transcoded filename.
- This does a two-pass compression (I'm assuming mpeg4, I should probably make this smarter for other formats).
- """
- #
- # do the first pass video compression
- #
- #cmd = "mencoder -quiet '%(video_source_filename)s' -ss 65 -endpos 20 -aid %(audio_id)s -o '%(video_final_filename)s' -ffourcc %(video_fourcc_override)s -ovc lavc -oac lavc %(lavcopts)s %(video_filter)s %(audio_filter)s" % locals()
-
- cmd = build_compression_command(
- video_source_filename,
- video_final_filename,
- video_target_size,
- audio_id,
- video_bitrate,
- video_codec,
- audio_codec,
- video_fourcc_override,
- video_gray_flag,
- video_crop_area,
- video_aspect_ratio,
- video_scale,
- video_encode_passes,
- video_deinterlace_flag,
- audio_volume_boost,
- audio_sample_rate,
- audio_bitrate,
- seek_skip,
- seek_length,
- video_chapter)
- if verbose_flag:
- print cmd
- if not dry_run_flag:
- run(cmd)
- print
-
- # If not doing two passes then return early.
- if video_encode_passes != '2':
- return
-
- if verbose_flag:
- video_actual_size = get_filesize(video_final_filename)
- if video_actual_size > video_target_size:
- print "======================================================="
- print "WARNING!"
- print "First pass compression resulted in"
- print "actual file size greater than target size."
- print "Second pass will be too big."
- print "======================================================="
-
- #
- # do the second pass video compression
- #
- cmd = cmd.replace('vpass=1', 'vpass=2')
- if verbose_flag:
- print cmd
- if not dry_run_flag:
- run(cmd)
- print
- return
-
-
-def compress_audio(
- audio_raw_filename,
- audio_compressed_filename,
- audio_lowpass_filter=None,
- audio_sample_rate=None,
- audio_bitrate=None,
- verbose_flag=0,
- dry_run_flag=0):
- """This is depricated.
- This compresses the raw audio file to the compressed audio filename.
- """
- cmd = 'lame -h --athaa-sensitivity 1' # --cwlimit 11"
- if audio_lowpass_filter:
- cmd = cmd + ' --lowpass ' + audio_lowpass_filter
- if audio_bitrate:
- #cmd = cmd + ' --abr ' + audio_bitrate
- cmd = cmd + ' --cbr -b ' + audio_bitrate
- if audio_sample_rate:
- cmd = cmd + ' --resample ' + audio_sample_rate
- cmd = cmd + ' ' + audio_raw_filename + ' ' + audio_compressed_filename
- if verbose_flag:
- print cmd
- if not dry_run_flag:
- (command_output, exitstatus) = run(cmd)
- print
- if exitstatus != 0:
- raise Exception('ERROR: lame failed to compress raw audio file.')
-
-
-def mux(
- video_final_filename,
- video_transcoded_filename,
- audio_compressed_filename,
- video_container_format,
- verbose_flag=0,
- dry_run_flag=0):
- """This is depricated. I used to use a three-pass encoding where I would mix the audio track separately, but
- this never worked very well (loss of audio sync)."""
- if video_container_format.lower() == 'mkv': # Matroska
- mux_mkv(
- video_final_filename,
- video_transcoded_filename,
- audio_compressed_filename,
- verbose_flag,
- dry_run_flag)
- if video_container_format.lower() == 'avi':
- mux_avi(
- video_final_filename,
- video_transcoded_filename,
- audio_compressed_filename,
- verbose_flag,
- dry_run_flag)
-
-
-def mux_mkv(
- video_final_filename,
- video_transcoded_filename,
- audio_compressed_filename,
- verbose_flag=0,
- dry_run_flag=0):
- """This is depricated."""
- cmd = 'mkvmerge -o %s --noaudio %s %s' % (
- video_final_filename, video_transcoded_filename, audio_compressed_filename)
- if verbose_flag:
- print cmd
- if not dry_run_flag:
- run(cmd)
- print
-
-
-def mux_avi(
- video_final_filename,
- video_transcoded_filename,
- audio_compressed_filename,
- verbose_flag=0,
- dry_run_flag=0):
- """This is depricated."""
- pass
-# cmd = "mencoder -quiet -oac copy -ovc copy -o '%s' -audiofile %s '%s'" % (video_final_filename, audio_compressed_filename, video_transcoded_filename)
-# if verbose_flag: print cmd
-# if not dry_run_flag:
-# run(cmd)
-# print
-
-
-def delete_tmp_files(audio_raw_filename, verbose_flag=0, dry_run_flag=0):
- global GLOBAL_LOGFILE_NAME
- file_list = ' '.join(
- [GLOBAL_LOGFILE_NAME, 'divx2pass.log', audio_raw_filename])
- cmd = 'rm -f ' + file_list
- if verbose_flag:
- print cmd
- if not dry_run_flag:
- run(cmd)
- print
-
-##############################################################################
-# This is the interactive Q&A that is used if a conf file was not given.
-##############################################################################
-
-
-def interactive_convert():
-
- global prompts, prompts_key_order
-
- print globals()['__doc__']
- print
- print "=============================================="
- print " Enter '?' at any question to get extra help."
- print "=============================================="
- print
-
- # Ask for the level of options the user wants.
- # A lot of code just to print a string!
- level_sort = {0: '', 1: '', 2: ''}
- for k in prompts:
- level = prompts[k][3]
- if level < 0 or level > 2:
- continue
- level_sort[level] += " " + prompts[k][1] + "\n"
- level_sort_string = "This sets the level for advanced options prompts. Set 0 for simple, 1 for advanced, or 2 for expert.\n"
- level_sort_string += "[0] Basic options:\n" + str(level_sort[0]) + "\n"
- level_sort_string += "[1] Advanced options:\n" + str(level_sort[1]) + "\n"
- level_sort_string += "[2] Expert options:\n" + str(level_sort[2])
- c = input_option("Prompt level (0, 1, or 2)?", "1", level_sort_string)
- max_prompt_level = int(c)
-
- options = {}
- for k in prompts_key_order:
- if k == 'video_aspect_ratio':
- guess_aspect = get_aspect_ratio(options['video_source_filename'])
- options[k] = input_option(
- prompts[k][1],
- guess_aspect,
- prompts[k][2],
- prompts[k][3],
- max_prompt_level)
- elif k == 'audio_id':
- aid_list = get_aid_list(options['video_source_filename'])
- default_id = '128'
- if max_prompt_level >= prompts[k][3]:
- if len(aid_list) > 1:
- print "This video has more than one audio stream. The following stream audio IDs were found:"
- for aid in aid_list:
- print " " + aid
- default_id = aid_list[0]
- else:
- print "WARNING!"
- print "Rippy was unable to get the list of audio streams from this video."
- print "If reading directly from a DVD then the DVD device might be busy."
- print "Using a default setting of stream id 128 (main audio on most DVDs)."
- default_id = '128'
- options[k] = input_option(
- prompts[k][1],
- default_id,
- prompts[k][2],
- prompts[k][3],
- max_prompt_level)
- elif k == 'subtitle_id':
- sid_list = get_sid_list(options['video_source_filename'])
- default_id = 'None'
- if max_prompt_level >= prompts[k][3]:
- if len(sid_list) > 0:
- print "This video has one or more subtitle streams. The following stream subtitle IDs were found:"
- for sid in sid_list:
- print " " + sid
- #default_id = sid_list[0]
- default_id = prompts[k][0]
- else:
- print "WARNING!"
- print "Unable to get the list of subtitle streams from this video. It may have none."
- print "Setting default to None."
- default_id = 'None'
- options[k] = input_option(
- prompts[k][1],
- default_id,
- prompts[k][2],
- prompts[k][3],
- max_prompt_level)
- elif k == 'audio_lowpass_filter':
- lowpass_default = "%.1f" % (math.floor(
- float(options['audio_sample_rate']) / 2.0))
- options[k] = input_option(
- prompts[k][1],
- lowpass_default,
- prompts[k][2],
- prompts[k][3],
- max_prompt_level)
- elif k == 'video_bitrate':
- if options['video_length'].lower() == 'none':
- options[k] = input_option(prompts[k][1], '1000', prompts[k][
- 2], prompts[k][3], max_prompt_level)
- else:
- options[k] = input_option(prompts[k][1], prompts[k][0], prompts[
- k][2], prompts[k][3], max_prompt_level)
- else:
- # don't bother asking for video_target_size or
- # video_bitrate_overhead if video_bitrate was set
- if (k == 'video_target_size' or k == 'video_bitrate_overhead') and options[
- 'video_bitrate'] != 'calc':
- continue
- # don't bother with crop area if video length is none
- if k == 'video_crop_area' and options[
- 'video_length'].lower() == 'none':
- options['video_crop_area'] = 'none'
- continue
- options[k] = input_option(
- prompts[k][1],
- prompts[k][0],
- prompts[k][2],
- prompts[k][3],
- max_prompt_level)
-
- #options['video_final_filename'] = options['video_final_filename'] + "." + options['video_container_format']
-
- print "=========================================================================="
- print "Ready to Rippy!"
- print
- print "The following options will be used:"
- for k, v in options.iteritems():
- print "%27s : %s" % (k, v)
-
- print
- c = input_option("Continue?", "Y")
- c = c.strip().lower()
- if c[0] != 'y':
- print "Exiting..."
- os._exit(1)
- return options
-
-
-def clean_options(d):
- """This validates and cleans up the options dictionary.
- After reading options interactively or from a conf file
- we need to make sure that the values make sense and are
- converted to the correct type.
- 1. Any key with "_flag" in it becomes a boolean True or False.
- 2. Values are normalized ("No", "None", "none" all become "none";
- "Calcluate", "c", "CALC" all become "calc").
- 3. Certain values are converted from string to int.
- 4. Certain combinations of options are invalid or override each other.
- This is a rather annoying function, but then so it most cleanup work.
- """
- for k in d:
- d[k] = d[k].strip()
- # convert all flag options to 0 or 1
- if '_flag' in k:
- if isinstance(d[k], types.StringType):
- if d[k].strip().lower()[0] in 'yt1': # Yes, True, 1
- d[k] = 1
- else:
- d[k] = 0
- d['video_bitrate'] = d['video_bitrate'].lower()
- if d['video_bitrate'][0] == 'c':
- d['video_bitrate'] = 'calc'
- else:
- d['video_bitrate'] = int(float(d['video_bitrate']))
- try:
- d['video_target_size'] = int(d['video_target_size'])
- # shorthand magic numbers get automatically expanded
- if d['video_target_size'] == 180:
- d['video_target_size'] = 193536000
- elif d['video_target_size'] == 550:
- d['video_target_size'] = 580608000
- elif d['video_target_size'] == 650:
- d['video_target_size'] = 681984000
- elif d['video_target_size'] == 700:
- d['video_target_size'] = 737280000
- except:
- d['video_target_size'] = 'none'
-
- try:
- d['video_chapter'] = int(d['video_chapter'])
- except:
- d['video_chapter'] = None
-
- try:
- d['subtitle_id'] = int(d['subtitle_id'])
- except:
- d['subtitle_id'] = None
-
- try:
- d['video_bitrate_overhead'] = float(d['video_bitrate_overhead'])
- except:
- d['video_bitrate_overhead'] = -1.0
-
- d['audio_bitrate'] = int(d['audio_bitrate'])
- d['audio_sample_rate'] = int(d['audio_sample_rate'])
- d['audio_volume_boost'] = d['audio_volume_boost'].lower()
- if d['audio_volume_boost'][0] == 'n':
- d['audio_volume_boost'] = None
- else:
- d['audio_volume_boost'] = d['audio_volume_boost'].replace('db', '')
- d['audio_volume_boost'] = float(d['audio_volume_boost'])
-
-# assert (d['video_bitrate']=='calc' and d['video_target_size']!='none')
-# or (d['video_bitrate']!='calc' and d['video_target_size']=='none')
-
- d['video_scale'] = d['video_scale'].lower()
- if d['video_scale'][0] == 'n':
- d['video_scale'] = 'none'
- else:
- al = re.findall("([0-9]+).*?([0-9]+)", d['video_scale'])
- d['video_scale'] = al[0][0] + ':' + al[0][1]
- d['video_crop_area'] = d['video_crop_area'].lower()
- if d['video_crop_area'][0] == 'n':
- d['video_crop_area'] = 'none'
- d['video_length'] = d['video_length'].lower()
- if d['video_length'][0] == 'c':
- d['video_length'] = 'calc'
- elif d['video_length'][0] == 'n':
- d['video_length'] = 'none'
- else:
- d['video_length'] = int(float(d['video_length']))
- if d['video_length'] == 0:
- d['video_length'] = 'none'
- assert (not (d['video_length'] == 'none' and d['video_bitrate'] == 'calc'))
- return d
-
-
-def main():
- try:
- optlist, args = getopt.getopt(sys.argv[1:], 'h?', ['help', 'h', '?'])
- except Exception as e:
- print str(e)
- exit_with_usage()
- command_line_options = dict(optlist)
- # There are a million ways to cry for help. These are but a few of them.
- if [elem for elem in command_line_options if elem in [
- '-h', '--h', '-?', '--?', '--help']]:
- exit_with_usage(0)
-
- missing = check_missing_requirements()
- if missing is not None:
- print
- print "=========================================================================="
- print "ERROR!"
- print "Some required external commands are missing."
- print "please install the following packages:"
- print str(missing)
- print "=========================================================================="
- print
- c = input_option("Continue?", "Y")
- c = c.strip().lower()
- if c[0] != 'y':
- print "Exiting..."
- os._exit(1)
-
- if len(args) > 0:
- # cute one-line string-to-dictionary parser (two-lines if you count
- # this comment):
- options = dict(
- re.findall(
- '([^: \t\n]*)\s*:\s*(".*"|[^ \t\n]*)',
- file(
- args[0]).read()))
- options = clean_options(options)
- convert(options)
- else:
- options = interactive_convert()
- options = clean_options(options)
- convert(options)
- print "# Done!"
-
-if __name__ == "__main__":
- try:
- start_time = time.time()
- print time.asctime()
- main()
- print time.asctime()
- print "TOTAL TIME IN MINUTES:",
- print (time.time() - start_time) / 60.0
- except Exception as e:
- tb_dump = traceback.format_exc()
- print "=========================================================================="
- print "ERROR -- Unexpected exception in script."
- print str(e)
- print str(tb_dump)
- print "=========================================================================="
- print >>GLOBAL_LOGFILE, "=========================================================================="
- print >>GLOBAL_LOGFILE, "ERROR -- Unexpected exception in script."
- print >>GLOBAL_LOGFILE, str(e)
- print >>GLOBAL_LOGFILE, str(tb_dump)
- print >>GLOBAL_LOGFILE, "=========================================================================="
- exit_with_usage(3)
Index: third_party/Python/module/pexpect-2.4/examples/script.py
===================================================================
--- third_party/Python/module/pexpect-2.4/examples/script.py
+++ third_party/Python/module/pexpect-2.4/examples/script.py
@@ -1,115 +0,0 @@
-#!/usr/bin/env python
-
-"""This spawns a sub-shell (bash) and gives the user interactive control. The
-entire shell session is logged to a file called script.log. This behaves much
-like the classic BSD command 'script'.
-
-./script.py [-a] [-c command] {logfilename}
-
- logfilename : This is the name of the log file. Default is script.log.
- -a : Append to log file. Default is to overwrite log file.
- -c : spawn command. Default is to spawn the sh shell.
-
-Example:
-
- This will start a bash shell and append to the log named my_session.log:
-
- ./script.py -a -c bash my_session.log
-
-"""
-
-import os
-import sys
-import time
-import getopt
-import signal
-import fcntl
-import termios
-import struct
-import traceback
-import pexpect
-
-global_pexpect_instance = None # Used by signal handler
-
-
-def exit_with_usage():
-
- print globals()['__doc__']
- os._exit(1)
-
-
-def main():
-
- ######################################################################
- # Parse the options, arguments, get ready, etc.
- ######################################################################
- try:
- optlist, args = getopt.getopt(
- sys.argv[
- 1:], 'h?ac:', [
- 'help', 'h', '?'])
- except Exception as e:
- print str(e)
- exit_with_usage()
- options = dict(optlist)
- if len(args) > 1:
- exit_with_usage()
-
- if [elem for elem in options if elem in [
- '-h', '--h', '-?', '--?', '--help']]:
- print "Help:"
- exit_with_usage()
-
- if len(args) == 1:
- script_filename = args[0]
- else:
- script_filename = "script.log"
- if '-a' in options:
- fout = file(script_filename, "ab")
- else:
- fout = file(script_filename, "wb")
- if '-c' in options:
- command = options['-c']
- else:
- command = "sh"
-
- # Begin log with date/time in the form CCCCyymm.hhmmss
- fout.write('# %4d%02d%02d.%02d%02d%02d \n' % time.localtime()[:-3])
-
- ######################################################################
- # Start the interactive session
- ######################################################################
- p = pexpect.spawn(command)
- p.logfile = fout
- global global_pexpect_instance
- global_pexpect_instance = p
- signal.signal(signal.SIGWINCH, sigwinch_passthrough)
-
- print "Script recording started. Type ^] (ASCII 29) to escape from the script shell."
- p.interact(chr(29))
- fout.close()
- return 0
-
-
-def sigwinch_passthrough(sig, data):
-
- # Check for buggy platforms (see pexpect.setwinsize()).
- if 'TIOCGWINSZ' in dir(termios):
- TIOCGWINSZ = termios.TIOCGWINSZ
- else:
- TIOCGWINSZ = 1074295912 # assume
- s = struct.pack("HHHH", 0, 0, 0, 0)
- a = struct.unpack('HHHH', fcntl.ioctl(sys.stdout.fileno(), TIOCGWINSZ, s))
- global global_pexpect_instance
- global_pexpect_instance.setwinsize(a[0], a[1])
-
-if __name__ == "__main__":
- try:
- main()
- except SystemExit as e:
- raise e
- except Exception as e:
- print "ERROR"
- print str(e)
- traceback.print_exc()
- os._exit(1)
Index: third_party/Python/module/pexpect-2.4/examples/ssh_session.py
===================================================================
--- third_party/Python/module/pexpect-2.4/examples/ssh_session.py
+++ third_party/Python/module/pexpect-2.4/examples/ssh_session.py
@@ -1,93 +0,0 @@
-#
-# Eric S. Raymond
-#
-# Greatly modified by Nigel W. Moriarty
-# April 2003
-#
-from pexpect import *
-import os
-import sys
-import getpass
-import time
-
-
-class ssh_session:
-
- "Session with extra state including the password to be used."
-
- def __init__(self, user, host, password=None, verbose=0):
-
- self.user = user
- self.host = host
- self.verbose = verbose
- self.password = password
- self.keys = [
- 'authenticity',
- 'assword:',
- '@@@@@@@@@@@@',
- 'Command not found.',
- EOF,
- ]
-
- self.f = open('ssh.out', 'w')
-
- def __repr__(self):
-
- outl = 'class :' + self.__class__.__name__
- for attr in self.__dict__:
- if attr == 'password':
- outl += '\n\t' + attr + ' : ' + '*' * len(self.password)
- else:
- outl += '\n\t' + attr + ' : ' + str(getattr(self, attr))
- return outl
-
- def __exec(self, command):
- "Execute a command on the remote host. Return the output."
- child = spawn(command,
- # timeout=10,
- )
- if self.verbose:
- sys.stderr.write("-> " + command + "\n")
- seen = child.expect(self.keys)
- self.f.write(str(child.before) + str(child.after) + '\n')
- if seen == 0:
- child.sendline('yes')
- seen = child.expect(self.keys)
- if seen == 1:
- if not self.password:
- self.password = getpass.getpass('Remote password: ')
- child.sendline(self.password)
- child.readline()
- time.sleep(5)
- # Added to allow the background running of remote process
- if not child.isalive():
- seen = child.expect(self.keys)
- if seen == 2:
- lines = child.readlines()
- self.f.write(lines)
- if self.verbose:
- sys.stderr.write("<- " + child.before + "|\n")
- try:
- self.f.write(str(child.before) + str(child.after) + '\n')
- except:
- pass
- self.f.close()
- return child.before
-
- def ssh(self, command):
-
- return self.__exec("ssh -l %s %s \"%s\""
- % (self.user, self.host, command))
-
- def scp(self, src, dst):
-
- return self.__exec("scp %s %s@%s:%s"
- % (src, session.user, session.host, dst))
-
- def exists(self, file):
- "Retrieve file permissions of specified remote file."
- seen = self.ssh("/bin/ls -ld %s" % file)
- if string.find(seen, "No such file") > -1:
- return None # File doesn't exist
- else:
- return seen.split()[0] # Return permission field of listing.
Index: third_party/Python/module/pexpect-2.4/examples/ssh_tunnel.py
===================================================================
--- third_party/Python/module/pexpect-2.4/examples/ssh_tunnel.py
+++ third_party/Python/module/pexpect-2.4/examples/ssh_tunnel.py
@@ -1,76 +0,0 @@
-#!/usr/bin/env python
-
-"""This starts an SSH tunnel to a given host. If the SSH process ever dies then
-this script will detect that and restart it. I use this under Cygwin to keep
-open encrypted tunnels to port 25 (SMTP), port 143 (IMAP4), and port 110
-(POP3). I set my mail client to talk to localhost and I keep this script
-running in the background.
-
-Note that this is a rather stupid script at the moment because it just looks to
-see if any ssh process is running. It should really make sure that our specific
-ssh process is running. The problem is that ssh is missing a very useful
-feature. It has no way to report the process id of the background daemon that
-it creates with the -f command. This would be a really useful script if I could
-figure a way around this problem. """
-
-import pexpect
-import getpass
-import time
-
-# SMTP:25 IMAP4:143 POP3:110
-tunnel_command = 'ssh -C -N -f -L 25:127.0.0.1:25 -L 143:127.0.0.1:143 -L 110:127.0.0.1:110 %(user)@%(host)'
-host = raw_input('Hostname: ')
-user = raw_input('Username: ')
-X = getpass.getpass('Password: ')
-
-
-def get_process_info():
-
- # This seems to work on both Linux and BSD, but should otherwise be
- # considered highly UNportable.
-
- ps = pexpect.run('ps ax -O ppid')
- pass
-
-
-def start_tunnel():
- try:
- ssh_tunnel = pexpect.spawn(tunnel_command % globals())
- ssh_tunnel.expect('password:')
- time.sleep(0.1)
- ssh_tunnel.sendline(X)
- time.sleep(60) # Cygwin is slow to update process status.
- ssh_tunnel.expect(pexpect.EOF)
-
- except Exception, e:
- print str(e)
-
-
-def main():
-
- while True:
- ps = pexpect.spawn('ps')
- time.sleep(1)
- index = ps.expect(['/usr/bin/ssh', pexpect.EOF, pexpect.TIMEOUT])
- if index == 2:
- print 'TIMEOUT in ps command...'
- print str(ps)
- time.sleep(13)
- if index == 1:
- print time.asctime(),
- print 'restarting tunnel'
- start_tunnel()
- time.sleep(11)
- print 'tunnel OK'
- else:
- # print 'tunnel OK'
- time.sleep(7)
-
-if __name__ == '__main__':
- main()
-
-# This was for older SSH versions that didn't have -f option
-#tunnel_command = 'ssh -C -n -L 25:%(host)s:25 -L 110:%(host)s:110 %(user)s@%(host)s -f nothing.sh'
-# nothing_script = """#!/bin/sh
-# while true; do sleep 53; done
-#"""
Index: third_party/Python/module/pexpect-2.4/examples/sshls.py
===================================================================
--- third_party/Python/module/pexpect-2.4/examples/sshls.py
+++ third_party/Python/module/pexpect-2.4/examples/sshls.py
@@ -1,57 +0,0 @@
-#!/usr/bin/env python
-
-"""This runs 'ls -l' on a remote host using SSH. At the prompts enter hostname,
-user, and password.
-
-$Id: sshls.py 489 2007-11-28 23:40:34Z noah $
-"""
-
-import pexpect
-import getpass
-import os
-
-
-def ssh_command(user, host, password, command):
- """This runs a command on the remote host. This could also be done with the
-pxssh class, but this demonstrates what that class does at a simpler level.
-This returns a pexpect.spawn object. This handles the case when you try to
-connect to a new host and ssh asks you if you want to accept the public key
-fingerprint and continue connecting. """
-
- ssh_newkey = 'Are you sure you want to continue connecting'
- child = pexpect.spawn('ssh -l %s %s %s' % (user, host, command))
- i = child.expect([pexpect.TIMEOUT, ssh_newkey, 'password: '])
- if i == 0: # Timeout
- print 'ERROR!'
- print 'SSH could not login. Here is what SSH said:'
- print child.before, child.after
- return None
- if i == 1: # SSH does not have the public key. Just accept it.
- child.sendline('yes')
- child.expect('password: ')
- i = child.expect([pexpect.TIMEOUT, 'password: '])
- if i == 0: # Timeout
- print 'ERROR!'
- print 'SSH could not login. Here is what SSH said:'
- print child.before, child.after
- return None
- child.sendline(password)
- return child
-
-
-def main():
-
- host = raw_input('Hostname: ')
- user = raw_input('User: ')
- password = getpass.getpass('Password: ')
- child = ssh_command(user, host, password, '/bin/ls -l')
- child.expect(pexpect.EOF)
- print child.before
-
-if __name__ == '__main__':
- try:
- main()
- except Exception as e:
- print str(e)
- traceback.print_exc()
- os._exit(1)
Index: third_party/Python/module/pexpect-2.4/examples/table_test.html
===================================================================
--- third_party/Python/module/pexpect-2.4/examples/table_test.html
+++ third_party/Python/module/pexpect-2.4/examples/table_test.html
@@ -1,106 +0,0 @@
-
-
-
-TEST
-
-
-
-
-
-
-
-
-
/
-
h
-
o
-
m
-
e
-
/
-
n
-
o
-
a
-
h
-
/
-
-
-
-
-
-
-
\ No newline at end of file
Index: third_party/Python/module/pexpect-2.4/examples/topip.py
===================================================================
--- third_party/Python/module/pexpect-2.4/examples/topip.py
+++ third_party/Python/module/pexpect-2.4/examples/topip.py
@@ -1,297 +0,0 @@
-#!/usr/bin/env python
-
-""" This runs netstat on a local or remote server. It calculates some simple
-statistical information on the number of external inet connections. It groups
-by IP address. This can be used to detect if one IP address is taking up an
-excessive number of connections. It can also send an email alert if a given IP
-address exceeds a threshold between runs of the script. This script can be used
-as a drop-in Munin plugin or it can be used stand-alone from cron. I used this
-on a busy web server that would sometimes get hit with denial of service
-attacks. This made it easy to see if a script was opening many multiple
-connections. A typical browser would open fewer than 10 connections at once. A
-script might open over 100 simultaneous connections.
-
-./topip.py [-s server_hostname] [-u username] [-p password] {-a from_addr,to_addr} {-n N} {-v} {--ipv6}
-
- -s : hostname of the remote server to login to.
- -u : username to user for login.
- -p : password to user for login.
- -n : print stddev for the the number of the top 'N' ipaddresses.
- -v : verbose - print stats and list of top ipaddresses.
- -a : send alert if stddev goes over 20.
- -l : to log message to /var/log/topip.log
- --ipv6 : this parses netstat output that includes ipv6 format.
- Note that this actually only works with ipv4 addresses, but for versions of
- netstat that print in ipv6 format.
- --stdev=N : Where N is an integer. This sets the trigger point for alerts and logs.
- Default is to trigger if max value is above 5 standard deviations.
-
-Example:
-
- This will print stats for the top IP addresses connected to the given host:
-
- ./topip.py -s www.example.com -u mylogin -p mypassword -n 10 -v
-
- This will send an alert email if the maxip goes over the stddev trigger value and
- the the current top ip is the same as the last top ip (/tmp/topip.last):
-
- ./topip.py -s www.example.com -u mylogin -p mypassword -n 10 -v -a alert@example.com,user@example.com
-
- This will print the connection stats for the localhost in Munin format:
-
- ./topip.py
-
-Noah Spurrier
-
-$Id: topip.py 489 2007-11-28 23:40:34Z noah $
-"""
-
-import pexpect
-import pxssh # See http://pexpect.sourceforge.net/
-import os
-import sys
-import time
-import re
-import getopt
-import pickle
-import getpass
-import smtplib
-import traceback
-from pprint import pprint
-
-TOPIP_LOG_FILE = '/var/log/topip.log'
-TOPIP_LAST_RUN_STATS = '/var/run/topip.last'
-
-
-def exit_with_usage():
-
- print globals()['__doc__']
- os._exit(1)
-
-
-def stats(r):
- """This returns a dict of the median, average, standard deviation, min and max of the given sequence.
-
- >>> from topip import stats
- >>> print stats([5,6,8,9])
- {'med': 8, 'max': 9, 'avg': 7.0, 'stddev': 1.5811388300841898, 'min': 5}
- >>> print stats([1000,1006,1008,1014])
- {'med': 1008, 'max': 1014, 'avg': 1007.0, 'stddev': 5.0, 'min': 1000}
- >>> print stats([1,3,4,5,18,16,4,3,3,5,13])
- {'med': 4, 'max': 18, 'avg': 6.8181818181818183, 'stddev': 5.6216817577237475, 'min': 1}
- >>> print stats([1,3,4,5,18,16,4,3,3,5,13,14,5,6,7,8,7,6,6,7,5,6,4,14,7])
- {'med': 6, 'max': 18, 'avg': 7.0800000000000001, 'stddev': 4.3259218670706474, 'min': 1}
- """
-
- total = sum(r)
- avg = float(total) / float(len(r))
- sdsq = sum([(i - avg)**2 for i in r])
- s = sorted(r)
- return dict(zip(['med', 'avg', 'stddev', 'min', 'max'],
- (s[len(s) // 2], avg, (sdsq / len(r))**.5, min(r), max(r))))
-
-
-def send_alert(message, subject, addr_from, addr_to, smtp_server='localhost'):
- """This sends an email alert.
- """
-
- message = 'From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n' % (
- addr_from, addr_to, subject) + message
- server = smtplib.SMTP(smtp_server)
- server.sendmail(addr_from, addr_to, message)
- server.quit()
-
-
-def main():
-
- ######################################################################
- # Parse the options, arguments, etc.
- ######################################################################
- try:
- optlist, args = getopt.getopt(
- sys.argv[
- 1:], 'h?valqs:u:p:n:', [
- 'help', 'h', '?', 'ipv6', 'stddev='])
- except Exception as e:
- print str(e)
- exit_with_usage()
- options = dict(optlist)
-
- munin_flag = False
- if len(args) > 0:
- if args[0] == 'config':
- print 'graph_title Netstat Connections per IP'
- print 'graph_vlabel Socket connections per IP'
- print 'connections_max.label max'
- print 'connections_max.info Maximum number of connections per IP'
- print 'connections_avg.label avg'
- print 'connections_avg.info Average number of connections per IP'
- print 'connections_stddev.label stddev'
- print 'connections_stddev.info Standard deviation'
- return 0
- elif args[0] != '':
- print args, len(args)
- return 0
- exit_with_usage()
- if [elem for elem in options if elem in [
- '-h', '--h', '-?', '--?', '--help']]:
- print 'Help:'
- exit_with_usage()
- if '-s' in options:
- hostname = options['-s']
- else:
- # if host was not specified then assume localhost munin plugin.
- munin_flag = True
- hostname = 'localhost'
- # If localhost then don't ask for username/password.
- if hostname != 'localhost' and hostname != '127.0.0.1':
- if '-u' in options:
- username = options['-u']
- else:
- username = raw_input('username: ')
- if '-p' in options:
- password = options['-p']
- else:
- password = getpass.getpass('password: ')
- else:
- use_localhost = True
-
- if '-l' in options:
- log_flag = True
- else:
- log_flag = False
- if '-n' in options:
- average_n = int(options['-n'])
- else:
- average_n = None
- if '-v' in options:
- verbose = True
- else:
- verbose = False
- if '-a' in options:
- alert_flag = True
- (alert_addr_from, alert_addr_to) = tuple(options['-a'].split(','))
- else:
- alert_flag = False
- if '--ipv6' in options:
- ipv6_flag = True
- else:
- ipv6_flag = False
- if '--stddev' in options:
- stddev_trigger = float(options['--stddev'])
- else:
- stddev_trigger = 5
-
- if ipv6_flag:
- netstat_pattern = '(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+::ffff:(\S+):(\S+)\s+.*?\r'
- else:
- netstat_pattern = '(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(?:::ffff:)*(\S+):(\S+)\s+.*?\r'
- #netstat_pattern = '(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+):(\S+)\s+.*?\r'
-
- # run netstat (either locally or via SSH).
- if use_localhost:
- p = pexpect.spawn('netstat -n -t')
- PROMPT = pexpect.TIMEOUT
- else:
- p = pxssh.pxssh()
- p.login(hostname, username, password)
- p.sendline('netstat -n -t')
- PROMPT = p.PROMPT
-
- # loop through each matching netstat_pattern and put the ip address in the
- # list.
- ip_list = {}
- try:
- while True:
- i = p.expect([PROMPT, netstat_pattern])
- if i == 0:
- break
- k = p.match.groups()[4]
- if k in ip_list:
- ip_list[k] = ip_list[k] + 1
- else:
- ip_list[k] = 1
- except:
- pass
-
- # remove a few common, uninteresting addresses from the dictionary.
- ip_list = dict([(key, value)
- for key, value in ip_list.items() if '192.168.' not in key])
- ip_list = dict([(key, value)
- for key, value in ip_list.items() if '127.0.0.1' not in key])
-
- # sort dict by value (count)
- #ip_list = sorted(ip_list.iteritems(),lambda x,y:cmp(x[1], y[1]),reverse=True)
- ip_list = ip_list.items()
- if len(ip_list) < 1:
- if verbose:
- print 'Warning: no networks connections worth looking at.'
- return 0
- ip_list.sort(lambda x, y: cmp(y[1], x[1]))
-
- # generate some stats for the ip addresses found.
- if average_n <= 1:
- average_n = None
- # The * unary operator treats the list elements as arguments
- s = stats(zip(*ip_list[0:average_n])[1])
- s['maxip'] = ip_list[0]
-
- # print munin-style or verbose results for the stats.
- if munin_flag:
- print 'connections_max.value', s['max']
- print 'connections_avg.value', s['avg']
- print 'connections_stddev.value', s['stddev']
- return 0
- if verbose:
- pprint(s)
- print
- pprint(ip_list[0:average_n])
-
- # load the stats from the last run.
- try:
- last_stats = pickle.load(file(TOPIP_LAST_RUN_STATS))
- except:
- last_stats = {'maxip': None}
-
- if s['maxip'][1] > (
- s['stddev'] *
- stddev_trigger) and s['maxip'] == last_stats['maxip']:
- if verbose:
- print 'The maxip has been above trigger for two consecutive samples.'
- if alert_flag:
- if verbose:
- print 'SENDING ALERT EMAIL'
- send_alert(
- str(s),
- 'ALERT on %s' %
- hostname,
- alert_addr_from,
- alert_addr_to)
- if log_flag:
- if verbose:
- print 'LOGGING THIS EVENT'
- fout = file(TOPIP_LOG_FILE, 'a')
- #dts = time.strftime('%Y:%m:%d:%H:%M:%S', time.localtime())
- dts = time.asctime()
- fout.write('%s - %d connections from %s\n' %
- (dts, s['maxip'][1], str(s['maxip'][0])))
- fout.close()
-
- # save state to TOPIP_LAST_RUN_STATS
- try:
- pickle.dump(s, file(TOPIP_LAST_RUN_STATS, 'w'))
- os.chmod(TOPIP_LAST_RUN_STATS, 0o664)
- except:
- pass
- # p.logout()
-
-if __name__ == '__main__':
- try:
- main()
- sys.exit(0)
- except SystemExit as e:
- raise e
- except Exception as e:
- print str(e)
- traceback.print_exc()
- os._exit(1)
Index: third_party/Python/module/pexpect-2.4/examples/uptime.py
===================================================================
--- third_party/Python/module/pexpect-2.4/examples/uptime.py
+++ third_party/Python/module/pexpect-2.4/examples/uptime.py
@@ -1,58 +0,0 @@
-#!/usr/bin/env python
-
-"""This displays uptime information using uptime. This is redundant,
-but it demonstrates expecting for a regular expression that uses subgroups.
-
-$Id: uptime.py 489 2007-11-28 23:40:34Z noah $
-"""
-
-import pexpect
-import re
-
-# There are many different styles of uptime results. I try to parse them all. Yeee!
-# Examples from different machines:
-# [x86] Linux 2.4 (Redhat 7.3)
-# 2:06pm up 63 days, 18 min, 3 users, load average: 0.32, 0.08, 0.02
-# [x86] Linux 2.4.18-14 (Redhat 8.0)
-# 3:07pm up 29 min, 1 user, load average: 2.44, 2.51, 1.57
-# [PPC - G4] MacOS X 10.1 SERVER Edition
-# 2:11PM up 3 days, 13:50, 3 users, load averages: 0.01, 0.00, 0.00
-# [powerpc] Darwin v1-58.corefa.com 8.2.0 Darwin Kernel Version 8.2.0
-# 10:35 up 18:06, 4 users, load averages: 0.52 0.47 0.36
-# [Sparc - R220] Sun Solaris (8)
-# 2:13pm up 22 min(s), 1 user, load average: 0.02, 0.01, 0.01
-# [x86] Linux 2.4.18-14 (Redhat 8)
-# 11:36pm up 4 days, 17:58, 1 user, load average: 0.03, 0.01, 0.00
-# AIX jwdir 2 5 0001DBFA4C00
-# 09:43AM up 23:27, 1 user, load average: 0.49, 0.32, 0.23
-# OpenBSD box3 2.9 GENERIC#653 i386
-# 6:08PM up 4 days, 22:26, 1 user, load averages: 0.13, 0.09, 0.08
-
-# This parses uptime output into the major groups using regex group matching.
-p = pexpect.spawn('uptime')
-p.expect(
- 'up\s+(.*?),\s+([0-9]+) users?,\s+load averages?: ([0-9]+\.[0-9][0-9]),?\s+([0-9]+\.[0-9][0-9]),?\s+([0-9]+\.[0-9][0-9])')
-duration, users, av1, av5, av15 = p.match.groups()
-
-# The duration is a little harder to parse because of all the different
-# styles of uptime. I'm sure there is a way to do this all at once with
-# one single regex, but I bet it would be hard to read and maintain.
-# If anyone wants to send me a version using a single regex I'd be happy
-# to see it.
-days = '0'
-hours = '0'
-mins = '0'
-if 'day' in duration:
- p.match = re.search('([0-9]+)\s+day', duration)
- days = str(int(p.match.group(1)))
-if ':' in duration:
- p.match = re.search('([0-9]+):([0-9]+)', duration)
- hours = str(int(p.match.group(1)))
- mins = str(int(p.match.group(2)))
-if 'min' in duration:
- p.match = re.search('([0-9]+)\s+min', duration)
- mins = str(int(p.match.group(1)))
-
-# Print the parsed fields in CSV format.
-print 'days, hours, minutes, users, cpu avg 1 min, cpu avg 5 min, cpu avg 15 min'
-print '%s, %s, %s, %s, %s, %s, %s' % (days, hours, mins, users, av1, av5, av15)
Index: third_party/Python/module/pexpect-2.4/fdpexpect.py
===================================================================
--- third_party/Python/module/pexpect-2.4/fdpexpect.py
+++ third_party/Python/module/pexpect-2.4/fdpexpect.py
@@ -1,98 +0,0 @@
-"""This is like pexpect, but will work on any file descriptor that you pass it.
-So you are reponsible for opening and close the file descriptor.
-
-$Id: fdpexpect.py 505 2007-12-26 21:33:50Z noah $
-"""
-
-from pexpect import *
-import os
-
-__all__ = ['fdspawn']
-
-
-class fdspawn (spawn):
-
- """This is like pexpect.spawn but allows you to supply your own open file
- descriptor. For example, you could use it to read through a file looking
- for patterns, or to control a modem or serial device. """
-
- def __init__(
- self,
- fd,
- args=[],
- timeout=30,
- maxread=2000,
- searchwindowsize=None,
- logfile=None):
- """This takes a file descriptor (an int) or an object that support the
- fileno() method (returning an int). All Python file-like objects
- support fileno(). """
-
- # TODO: Add better handling of trying to use fdspawn in place of spawn
- # TODO: (overload to allow fdspawn to also handle commands as spawn
- # does.
-
- if not isinstance(fd, type(0)) and hasattr(fd, 'fileno'):
- fd = fd.fileno()
-
- if not isinstance(fd, type(0)):
- raise ExceptionPexpect(
- 'The fd argument is not an int. If this is a command string then maybe you want to use pexpect.spawn.')
-
- try: # make sure fd is a valid file descriptor
- os.fstat(fd)
- except OSError:
- raise ExceptionPexpect(
- 'The fd argument is not a valid file descriptor.')
-
- self.args = None
- self.command = None
- spawn.__init__(
- self,
- None,
- args,
- timeout,
- maxread,
- searchwindowsize,
- logfile)
- self.child_fd = fd
- self.own_fd = False
- self.closed = False
- self.name = '' % fd
-
- def __del__(self):
-
- return
-
- def close(self):
-
- if self.child_fd == -1:
- return
- if self.own_fd:
- self.close(self)
- else:
- self.flush()
- os.close(self.child_fd)
- self.child_fd = -1
- self.closed = True
-
- def isalive(self):
- """This checks if the file descriptor is still valid. If os.fstat()
- does not raise an exception then we assume it is alive. """
-
- if self.child_fd == -1:
- return False
- try:
- os.fstat(self.child_fd)
- return True
- except:
- return False
-
- def terminate(self, force=False):
-
- raise ExceptionPexpect(
- 'This method is not valid for file descriptors.')
-
- def kill(self, sig):
-
- return
Index: third_party/Python/module/pexpect-2.4/pexpect.py
===================================================================
--- third_party/Python/module/pexpect-2.4/pexpect.py
+++ third_party/Python/module/pexpect-2.4/pexpect.py
@@ -1,1894 +0,0 @@
-"""Pexpect is a Python module for spawning child applications and controlling
-them automatically. Pexpect can be used for automating interactive applications
-such as ssh, ftp, passwd, telnet, etc. It can be used to a automate setup
-scripts for duplicating software package installations on different servers. It
-can be used for automated software testing. Pexpect is in the spirit of Don
-Libes' Expect, but Pexpect is pure Python. Other Expect-like modules for Python
-require TCL and Expect or require C extensions to be compiled. Pexpect does not
-use C, Expect, or TCL extensions. It should work on any platform that supports
-the standard Python pty module. The Pexpect interface focuses on ease of use so
-that simple tasks are easy.
-
-There are two main interfaces to Pexpect -- the function, run() and the class,
-spawn. You can call the run() function to execute a command and return the
-output. This is a handy replacement for os.system().
-
-For example::
-
- pexpect.run('ls -la')
-
-The more powerful interface is the spawn class. You can use this to spawn an
-external child command and then interact with the child by sending lines and
-expecting responses.
-
-For example::
-
- child = pexpect.spawn('scp foo myname@host.example.com:.')
- child.expect ('Password:')
- child.sendline (mypassword)
-
-This works even for commands that ask for passwords or other input outside of
-the normal stdio streams.
-
-Credits: Noah Spurrier, Richard Holden, Marco Molteni, Kimberley Burchett,
-Robert Stone, Hartmut Goebel, Chad Schroeder, Erick Tryzelaar, Dave Kirby, Ids
-vander Molen, George Todd, Noel Taylor, Nicolas D. Cesar, Alexander Gattin,
-Jacques-Etienne Baudoux, Geoffrey Marshall, Francisco Lourenco, Glen Mabey,
-Karthik Gurusamy, Fernando Perez, Corey Minyard, Jon Cohen, Guillaume
-Chazarain, Andrew Ryan, Nick Craig-Wood, Andrew Stone, Jorgen Grahn, John
-Spiegel, Jan Grant (Let me know if I forgot anyone.)
-
-Free, open source, and all that good stuff.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-of the Software, and to permit persons to whom the Software is furnished to do
-so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-Pexpect Copyright (c) 2008 Noah Spurrier
-http://pexpect.sourceforge.net/
-
-$Id: pexpect.py 516 2008-05-23 20:46:01Z noah $
-"""
-
-try:
- import os
- import sys
- import time
- import select
- import string
- import re
- import struct
- import resource
- import types
- import pty
- import tty
- import termios
- import fcntl
- import errno
- import traceback
- import signal
-except ImportError as e:
- raise ImportError (str(e) + """
-
-A critical module was not found. Probably this operating system does not
-support it. Pexpect is intended for UNIX-like operating systems.""")
-
-__version__ = '2.4'
-__revision__ = '$Revision: 516 $'
-__all__ = ['ExceptionPexpect', 'EOF', 'TIMEOUT', 'spawn', 'run', 'which',
- 'split_command_line', '__version__', '__revision__']
-
-# Exception classes used by this module.
-
-
-class ExceptionPexpect(Exception):
-
- """Base class for all exceptions raised by this module.
- """
-
- def __init__(self, value):
-
- self.value = value
-
- def __str__(self):
-
- return str(self.value)
-
- def get_trace(self):
- """This returns an abbreviated stack trace with lines that only concern
- the caller. In other words, the stack trace inside the Pexpect module
- is not included. """
-
- tblist = traceback.extract_tb(sys.exc_info()[2])
- #tblist = filter(self.__filter_not_pexpect, tblist)
- tblist = [item for item in tblist if self.__filter_not_pexpect(item)]
- tblist = traceback.format_list(tblist)
- return ''.join(tblist)
-
- def __filter_not_pexpect(self, trace_list_item):
- """This returns True if list item 0 the string 'pexpect.py' in it. """
-
- if trace_list_item[0].find('pexpect.py') == -1:
- return True
- else:
- return False
-
-
-class EOF(ExceptionPexpect):
-
- """Raised when EOF is read from a child. This usually means the child has exited."""
-
-
-class TIMEOUT(ExceptionPexpect):
-
- """Raised when a read time exceeds the timeout. """
-
-# class TIMEOUT_PATTERN(TIMEOUT):
-# """Raised when the pattern match time exceeds the timeout.
-# This is different than a read TIMEOUT because the child process may
-# give output, thus never give a TIMEOUT, but the output
-# may never match a pattern.
-# """
-# class MAXBUFFER(ExceptionPexpect):
-## """Raised when a scan buffer fills before matching an expected pattern."""
-
-
-def run(
- command,
- timeout=-1,
- withexitstatus=False,
- events=None,
- extra_args=None,
- logfile=None,
- cwd=None,
- env=None):
- """
- This function runs the given command; waits for it to finish; then
- returns all output as a string. STDERR is included in output. If the full
- path to the command is not given then the path is searched.
-
- Note that lines are terminated by CR/LF (\\r\\n) combination even on
- UNIX-like systems because this is the standard for pseudo ttys. If you set
- 'withexitstatus' to true, then run will return a tuple of (command_output,
- exitstatus). If 'withexitstatus' is false then this returns just
- command_output.
-
- The run() function can often be used instead of creating a spawn instance.
- For example, the following code uses spawn::
-
- from pexpect import *
- child = spawn('scp foo myname@host.example.com:.')
- child.expect ('(?i)password')
- child.sendline (mypassword)
-
- The previous code can be replace with the following::
-
- from pexpect import *
- run ('scp foo myname@host.example.com:.', events={'(?i)password': mypassword})
-
- Examples
- ========
-
- Start the apache daemon on the local machine::
-
- from pexpect import *
- run ("/usr/local/apache/bin/apachectl start")
-
- Check in a file using SVN::
-
- from pexpect import *
- run ("svn ci -m 'automatic commit' my_file.py")
-
- Run a command and capture exit status::
-
- from pexpect import *
- (command_output, exitstatus) = run ('ls -l /bin', withexitstatus=1)
-
- Tricky Examples
- ===============
-
- The following will run SSH and execute 'ls -l' on the remote machine. The
- password 'secret' will be sent if the '(?i)password' pattern is ever seen::
-
- run ("ssh username@machine.example.com 'ls -l'", events={'(?i)password':'secret\\n'})
-
- This will start mencoder to rip a video from DVD. This will also display
- progress ticks every 5 seconds as it runs. For example::
-
- from pexpect import *
- def print_ticks(d):
- print d['event_count'],
- run ("mencoder dvd://1 -o video.avi -oac copy -ovc copy", events={TIMEOUT:print_ticks}, timeout=5)
-
- The 'events' argument should be a dictionary of patterns and responses.
- Whenever one of the patterns is seen in the command out run() will send the
- associated response string. Note that you should put newlines in your
- string if Enter is necessary. The responses may also contain callback
- functions. Any callback is function that takes a dictionary as an argument.
- The dictionary contains all the locals from the run() function, so you can
- access the child spawn object or any other variable defined in run()
- (event_count, child, and extra_args are the most useful). A callback may
- return True to stop the current run process otherwise run() continues until
- the next event. A callback may also return a string which will be sent to
- the child. 'extra_args' is not used by directly run(). It provides a way to
- pass data to a callback function through run() through the locals
- dictionary passed to a callback. """
-
- if timeout == -1:
- child = spawn(command, maxread=2000, logfile=logfile, cwd=cwd, env=env)
- else:
- child = spawn(
- command,
- timeout=timeout,
- maxread=2000,
- logfile=logfile,
- cwd=cwd,
- env=env)
- if events is not None:
- patterns = events.keys()
- responses = events.values()
- else:
- patterns = None # We assume that EOF or TIMEOUT will save us.
- responses = None
- child_result_list = []
- event_count = 0
- while True:
- try:
- index = child.expect(patterns)
- if type(child.after) in types.StringTypes:
- child_result_list.append(child.before + child.after)
- else: # child.after may have been a TIMEOUT or EOF, so don't cat those.
- child_result_list.append(child.before)
- if type(responses[index]) in types.StringTypes:
- child.send(responses[index])
- elif isinstance(responses[index], types.FunctionType):
- callback_result = responses[index](locals())
- sys.stdout.flush()
- if type(callback_result) in types.StringTypes:
- child.send(callback_result)
- elif callback_result:
- break
- else:
- raise TypeError(
- 'The callback must be a string or function type.')
- event_count = event_count + 1
- except TIMEOUT as e:
- child_result_list.append(child.before)
- break
- except EOF as e:
- child_result_list.append(child.before)
- break
- child_result = ''.join(child_result_list)
- if withexitstatus:
- child.close()
- return (child_result, child.exitstatus)
- else:
- return child_result
-
-
-class spawn (object):
-
- """This is the main class interface for Pexpect. Use this class to start
- and control child applications. """
-
- def __init__(
- self,
- command,
- args=[],
- timeout=30,
- maxread=2000,
- searchwindowsize=None,
- logfile=None,
- cwd=None,
- env=None):
- """This is the constructor. The command parameter may be a string that
- includes a command and any arguments to the command. For example::
-
- child = pexpect.spawn ('/usr/bin/ftp')
- child = pexpect.spawn ('/usr/bin/ssh user@example.com')
- child = pexpect.spawn ('ls -latr /tmp')
-
- You may also construct it with a list of arguments like so::
-
- child = pexpect.spawn ('/usr/bin/ftp', [])
- child = pexpect.spawn ('/usr/bin/ssh', ['user@example.com'])
- child = pexpect.spawn ('ls', ['-latr', '/tmp'])
-
- After this the child application will be created and will be ready to
- talk to. For normal use, see expect() and send() and sendline().
-
- Remember that Pexpect does NOT interpret shell meta characters such as
- redirect, pipe, or wild cards (>, |, or *). This is a common mistake.
- If you want to run a command and pipe it through another command then
- you must also start a shell. For example::
-
- child = pexpect.spawn('/bin/bash -c "ls -l | grep LOG > log_list.txt"')
- child.expect(pexpect.EOF)
-
- The second form of spawn (where you pass a list of arguments) is useful
- in situations where you wish to spawn a command and pass it its own
- argument list. This can make syntax more clear. For example, the
- following is equivalent to the previous example::
-
- shell_cmd = 'ls -l | grep LOG > log_list.txt'
- child = pexpect.spawn('/bin/bash', ['-c', shell_cmd])
- child.expect(pexpect.EOF)
-
- The maxread attribute sets the read buffer size. This is maximum number
- of bytes that Pexpect will try to read from a TTY at one time. Setting
- the maxread size to 1 will turn off buffering. Setting the maxread
- value higher may help performance in cases where large amounts of
- output are read back from the child. This feature is useful in
- conjunction with searchwindowsize.
-
- The searchwindowsize attribute sets the how far back in the incomming
- seach buffer Pexpect will search for pattern matches. Every time
- Pexpect reads some data from the child it will append the data to the
- incomming buffer. The default is to search from the beginning of the
- imcomming buffer each time new data is read from the child. But this is
- very inefficient if you are running a command that generates a large
- amount of data where you want to match The searchwindowsize does not
- effect the size of the incomming data buffer. You will still have
- access to the full buffer after expect() returns.
-
- The logfile member turns on or off logging. All input and output will
- be copied to the given file object. Set logfile to None to stop
- logging. This is the default. Set logfile to sys.stdout to echo
- everything to standard output. The logfile is flushed after each write.
-
- Example log input and output to a file::
-
- child = pexpect.spawn('some_command')
- fout = file('mylog.txt','w')
- child.logfile = fout
-
- Example log to stdout::
-
- child = pexpect.spawn('some_command')
- child.logfile = sys.stdout
-
- The logfile_read and logfile_send members can be used to separately log
- the input from the child and output sent to the child. Sometimes you
- don't want to see everything you write to the child. You only want to
- log what the child sends back. For example::
-
- child = pexpect.spawn('some_command')
- child.logfile_read = sys.stdout
-
- To separately log output sent to the child use logfile_send::
-
- self.logfile_send = fout
-
- The delaybeforesend helps overcome a weird behavior that many users
- were experiencing. The typical problem was that a user would expect() a
- "Password:" prompt and then immediately call sendline() to send the
- password. The user would then see that their password was echoed back
- to them. Passwords don't normally echo. The problem is caused by the
- fact that most applications print out the "Password" prompt and then
- turn off stdin echo, but if you send your password before the
- application turned off echo, then you get your password echoed.
- Normally this wouldn't be a problem when interacting with a human at a
- real keyboard. If you introduce a slight delay just before writing then
- this seems to clear up the problem. This was such a common problem for
- many users that I decided that the default pexpect behavior should be
- to sleep just before writing to the child application. 1/20th of a
- second (50 ms) seems to be enough to clear up the problem. You can set
- delaybeforesend to 0 to return to the old behavior. Most Linux machines
- don't like this to be below 0.03. I don't know why.
-
- Note that spawn is clever about finding commands on your path.
- It uses the same logic that "which" uses to find executables.
-
- If you wish to get the exit status of the child you must call the
- close() method. The exit or signal status of the child will be stored
- in self.exitstatus or self.signalstatus. If the child exited normally
- then exitstatus will store the exit return code and signalstatus will
- be None. If the child was terminated abnormally with a signal then
- signalstatus will store the signal value and exitstatus will be None.
- If you need more detail you can also read the self.status member which
- stores the status returned by os.waitpid. You can interpret this using
- os.WIFEXITED/os.WEXITSTATUS or os.WIFSIGNALED/os.TERMSIG. """
-
- self.STDIN_FILENO = pty.STDIN_FILENO
- self.STDOUT_FILENO = pty.STDOUT_FILENO
- self.STDERR_FILENO = pty.STDERR_FILENO
- self.stdin = sys.stdin
- self.stdout = sys.stdout
- self.stderr = sys.stderr
-
- self.searcher = None
- self.ignorecase = False
- self.before = None
- self.after = None
- self.match = None
- self.match_index = None
- self.terminated = True
- self.exitstatus = None
- self.signalstatus = None
- self.status = None # status returned by os.waitpid
- self.flag_eof = False
- self.pid = None
- self.child_fd = -1 # initially closed
- self.timeout = timeout
- self.delimiter = EOF
- self.logfile = logfile
- self.logfile_read = None # input from child (read_nonblocking)
- self.logfile_send = None # output to send (send, sendline)
- self.maxread = maxread # max bytes to read at one time into buffer
- self.buffer = '' # This is the read buffer. See maxread.
- # Anything before searchwindowsize point is preserved, but not
- # searched.
- self.searchwindowsize = searchwindowsize
- # Most Linux machines don't like delaybeforesend to be below 0.03 (30
- # ms).
- # Sets sleep time used just before sending data to child. Time in
- # seconds.
- self.delaybeforesend = 0.05
- # Sets delay in close() method to allow kernel time to update process
- # status. Time in seconds.
- self.delayafterclose = 0.1
- # Sets delay in terminate() method to allow kernel time to update
- # process status. Time in seconds.
- self.delayafterterminate = 0.1
- self.softspace = False # File-like object.
- self.name = '<' + repr(self) + '>' # File-like object.
- self.encoding = None # File-like object.
- self.closed = True # File-like object.
- self.cwd = cwd
- self.env = env
- # This flags if we are running on irix
- self.__irix_hack = (sys.platform.lower().find('irix') >= 0)
- # Solaris uses internal __fork_pty(). All others use pty.fork().
- if (sys.platform.lower().find('solaris') >= 0) or (
- sys.platform.lower().find('sunos5') >= 0):
- self.use_native_pty_fork = False
- else:
- self.use_native_pty_fork = True
-
- # allow dummy instances for subclasses that may not use command or
- # args.
- if command is None:
- self.command = None
- self.args = None
- self.name = ''
- else:
- self._spawn(command, args)
-
- def __del__(self):
- """This makes sure that no system resources are left open. Python only
- garbage collects Python objects. OS file descriptors are not Python
- objects, so they must be handled explicitly. If the child file
- descriptor was opened outside of this class (passed to the constructor)
- then this does not close it. """
-
- if not self.closed:
- # It is possible for __del__ methods to execute during the
- # teardown of the Python VM itself. Thus self.close() may
- # trigger an exception because os.close may be None.
- # -- Fernando Perez
- try:
- self.close()
- except:
- pass
-
- def __str__(self):
- """This returns a human-readable string that represents the state of
- the object. """
-
- s = []
- s.append(repr(self))
- s.append('version: ' + __version__ + ' (' + __revision__ + ')')
- s.append('command: ' + str(self.command))
- s.append('args: ' + str(self.args))
- s.append('searcher: ' + str(self.searcher))
- s.append('buffer (last 100 chars): ' + str(self.buffer)[-100:])
- s.append('before (last 100 chars): ' + str(self.before)[-100:])
- s.append('after: ' + str(self.after))
- s.append('match: ' + str(self.match))
- s.append('match_index: ' + str(self.match_index))
- s.append('exitstatus: ' + str(self.exitstatus))
- s.append('flag_eof: ' + str(self.flag_eof))
- s.append('pid: ' + str(self.pid))
- s.append('child_fd: ' + str(self.child_fd))
- s.append('closed: ' + str(self.closed))
- s.append('timeout: ' + str(self.timeout))
- s.append('delimiter: ' + str(self.delimiter))
- s.append('logfile: ' + str(self.logfile))
- s.append('logfile_read: ' + str(self.logfile_read))
- s.append('logfile_send: ' + str(self.logfile_send))
- s.append('maxread: ' + str(self.maxread))
- s.append('ignorecase: ' + str(self.ignorecase))
- s.append('searchwindowsize: ' + str(self.searchwindowsize))
- s.append('delaybeforesend: ' + str(self.delaybeforesend))
- s.append('delayafterclose: ' + str(self.delayafterclose))
- s.append('delayafterterminate: ' + str(self.delayafterterminate))
- return '\n'.join(s)
-
- def _spawn(self, command, args=[]):
- """This starts the given command in a child process. This does all the
- fork/exec type of stuff for a pty. This is called by __init__. If args
- is empty then command will be parsed (split on spaces) and args will be
- set to parsed arguments. """
-
- # The pid and child_fd of this object get set by this method.
- # Note that it is difficult for this method to fail.
- # You cannot detect if the child process cannot start.
- # So the only way you can tell if the child process started
- # or not is to try to read from the file descriptor. If you get
- # EOF immediately then it means that the child is already dead.
- # That may not necessarily be bad because you may haved spawned a child
- # that performs some task; creates no stdout output; and then dies.
-
- # If command is an int type then it may represent a file descriptor.
- if isinstance(command, type(0)):
- raise ExceptionPexpect(
- 'Command is an int type. If this is a file descriptor then maybe you want to use fdpexpect.fdspawn which takes an existing file descriptor instead of a command string.')
-
- if not isinstance(args, type([])):
- raise TypeError('The argument, args, must be a list.')
-
- if args == []:
- self.args = split_command_line(command)
- self.command = self.args[0]
- else:
- self.args = args[:] # work with a copy
- self.args.insert(0, command)
- self.command = command
-
- command_with_path = which(self.command)
- if command_with_path is None:
- raise ExceptionPexpect(
- 'The command was not found or was not executable: %s.' %
- self.command)
- self.command = command_with_path
- self.args[0] = self.command
-
- self.name = '<' + ' '.join(self.args) + '>'
-
- assert self.pid is None, 'The pid member should be None.'
- assert self.command is not None, 'The command member should not be None.'
-
- if self.use_native_pty_fork:
- try:
- self.pid, self.child_fd = pty.fork()
- except OSError as e:
- raise ExceptionPexpect('Error! pty.fork() failed: ' + str(e))
- else: # Use internal __fork_pty
- self.pid, self.child_fd = self.__fork_pty()
-
- if self.pid == 0: # Child
- try:
- self.child_fd = sys.stdout.fileno() # used by setwinsize()
- self.setwinsize(24, 80)
- except:
- # Some platforms do not like setwinsize (Cygwin).
- # This will cause problem when running applications that
- # are very picky about window size.
- # This is a serious limitation, but not a show stopper.
- pass
- # Do not allow child to inherit open file descriptors from parent.
- max_fd = resource.getrlimit(resource.RLIMIT_NOFILE)[0]
- for i in range(3, max_fd):
- try:
- os.close(i)
- except OSError:
- pass
-
- # I don't know why this works, but ignoring SIGHUP fixes a
- # problem when trying to start a Java daemon with sudo
- # (specifically, Tomcat).
- signal.signal(signal.SIGHUP, signal.SIG_IGN)
-
- if self.cwd is not None:
- os.chdir(self.cwd)
- if self.env is None:
- os.execv(self.command, self.args)
- else:
- os.execvpe(self.command, self.args, self.env)
-
- # Parent
- self.terminated = False
- self.closed = False
-
- def __fork_pty(self):
- """This implements a substitute for the forkpty system call. This
- should be more portable than the pty.fork() function. Specifically,
- this should work on Solaris.
-
- Modified 10.06.05 by Geoff Marshall: Implemented __fork_pty() method to
- resolve the issue with Python's pty.fork() not supporting Solaris,
- particularly ssh. Based on patch to posixmodule.c authored by Noah
- Spurrier::
-
- http://mail.python.org/pipermail/python-dev/2003-May/035281.html
-
- """
-
- parent_fd, child_fd = os.openpty()
- if parent_fd < 0 or child_fd < 0:
- raise ExceptionPexpect(
- "Error! Could not open pty with os.openpty().")
-
- pid = os.fork()
- if pid < 0:
- raise ExceptionPexpect("Error! Failed os.fork().")
- elif pid == 0:
- # Child.
- os.close(parent_fd)
- self.__pty_make_controlling_tty(child_fd)
-
- os.dup2(child_fd, 0)
- os.dup2(child_fd, 1)
- os.dup2(child_fd, 2)
-
- if child_fd > 2:
- os.close(child_fd)
- else:
- # Parent.
- os.close(child_fd)
-
- return pid, parent_fd
-
- def __pty_make_controlling_tty(self, tty_fd):
- """This makes the pseudo-terminal the controlling tty. This should be
- more portable than the pty.fork() function. Specifically, this should
- work on Solaris. """
-
- child_name = os.ttyname(tty_fd)
-
- # Disconnect from controlling tty if still connected.
- try:
- fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY)
- if fd >= 0:
- os.close(fd)
- except:
- # We are already disconnected. Perhaps we are running inside cron.
- pass
-
- os.setsid()
-
- # Verify we are disconnected from controlling tty
- try:
- fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY)
- if fd >= 0:
- os.close(fd)
- raise ExceptionPexpect(
- "Error! We are not disconnected from a controlling tty.")
- except:
- # Good! We are disconnected from a controlling tty.
- pass
-
- # Verify we can open child pty.
- fd = os.open(child_name, os.O_RDWR)
- if fd < 0:
- raise ExceptionPexpect(
- "Error! Could not open child pty, " + child_name)
- else:
- os.close(fd)
-
- # Verify we now have a controlling tty.
- fd = os.open("/dev/tty", os.O_WRONLY)
- if fd < 0:
- raise ExceptionPexpect(
- "Error! Could not open controlling tty, /dev/tty")
- else:
- os.close(fd)
-
- def fileno(self): # File-like object.
- """This returns the file descriptor of the pty for the child.
- """
-
- return self.child_fd
-
- def close(self, force=True): # File-like object.
- """This closes the connection with the child application. Note that
- calling close() more than once is valid. This emulates standard Python
- behavior with files. Set force to True if you want to make sure that
- the child is terminated (SIGKILL is sent if the child ignores SIGHUP
- and SIGINT). """
-
- if not self.closed:
- self.flush()
- os.close(self.child_fd)
- # Give kernel time to update process status.
- time.sleep(self.delayafterclose)
- if self.isalive():
- if not self.terminate(force):
- raise ExceptionPexpect(
- 'close() could not terminate the child using terminate()')
- self.child_fd = -1
- self.closed = True
- #self.pid = None
-
- def flush(self): # File-like object.
- """This does nothing. It is here to support the interface for a
- File-like object. """
-
- pass
-
- def isatty(self): # File-like object.
- """This returns True if the file descriptor is open and connected to a
- tty(-like) device, else False. """
-
- return os.isatty(self.child_fd)
-
- def waitnoecho(self, timeout=-1):
- """This waits until the terminal ECHO flag is set False. This returns
- True if the echo mode is off. This returns False if the ECHO flag was
- not set False before the timeout. This can be used to detect when the
- child is waiting for a password. Usually a child application will turn
- off echo mode when it is waiting for the user to enter a password. For
- example, instead of expecting the "password:" prompt you can wait for
- the child to set ECHO off::
-
- p = pexpect.spawn ('ssh user@example.com')
- p.waitnoecho()
- p.sendline(mypassword)
-
- If timeout is None then this method to block forever until ECHO flag is
- False.
-
- """
-
- if timeout == -1:
- timeout = self.timeout
- if timeout is not None:
- end_time = time.time() + timeout
- while True:
- if not self.getecho():
- return True
- if timeout < 0 and timeout is not None:
- return False
- if timeout is not None:
- timeout = end_time - time.time()
- time.sleep(0.1)
-
- def getecho(self):
- """This returns the terminal echo mode. This returns True if echo is
- on or False if echo is off. Child applications that are expecting you
- to enter a password often set ECHO False. See waitnoecho(). """
-
- attr = termios.tcgetattr(self.child_fd)
- if attr[3] & termios.ECHO:
- return True
- return False
-
- def setecho(self, state):
- """This sets the terminal echo mode on or off. Note that anything the
- child sent before the echo will be lost, so you should be sure that
- your input buffer is empty before you call setecho(). For example, the
- following will work as expected::
-
- p = pexpect.spawn('cat')
- p.sendline ('1234') # We will see this twice (once from tty echo and again from cat).
- p.expect (['1234'])
- p.expect (['1234'])
- p.setecho(False) # Turn off tty echo
- p.sendline ('abcd') # We will set this only once (echoed by cat).
- p.sendline ('wxyz') # We will set this only once (echoed by cat)
- p.expect (['abcd'])
- p.expect (['wxyz'])
-
- The following WILL NOT WORK because the lines sent before the setecho
- will be lost::
-
- p = pexpect.spawn('cat')
- p.sendline ('1234') # We will see this twice (once from tty echo and again from cat).
- p.setecho(False) # Turn off tty echo
- p.sendline ('abcd') # We will set this only once (echoed by cat).
- p.sendline ('wxyz') # We will set this only once (echoed by cat)
- p.expect (['1234'])
- p.expect (['1234'])
- p.expect (['abcd'])
- p.expect (['wxyz'])
- """
-
- self.child_fd
- attr = termios.tcgetattr(self.child_fd)
- if state:
- attr[3] = attr[3] | termios.ECHO
- else:
- attr[3] = attr[3] & ~termios.ECHO
- # I tried TCSADRAIN and TCSAFLUSH, but these were inconsistent
- # and blocked on some platforms. TCSADRAIN is probably ideal if it
- # worked.
- termios.tcsetattr(self.child_fd, termios.TCSANOW, attr)
-
- def read_nonblocking(self, size=1, timeout=-1):
- """This reads at most size characters from the child application. It
- includes a timeout. If the read does not complete within the timeout
- period then a TIMEOUT exception is raised. If the end of file is read
- then an EOF exception will be raised. If a log file was set using
- setlog() then all data will also be written to the log file.
-
- If timeout is None then the read may block indefinitely. If timeout is -1
- then the self.timeout value is used. If timeout is 0 then the child is
- polled and if there was no data immediately ready then this will raise
- a TIMEOUT exception.
-
- The timeout refers only to the amount of time to read at least one
- character. This is not effected by the 'size' parameter, so if you call
- read_nonblocking(size=100, timeout=30) and only one character is
- available right away then one character will be returned immediately.
- It will not wait for 30 seconds for another 99 characters to come in.
-
- This is a wrapper around os.read(). It uses select.select() to
- implement the timeout. """
-
- if self.closed:
- raise ValueError(
- 'I/O operation on closed file in read_nonblocking().')
-
- if timeout == -1:
- timeout = self.timeout
-
- # Note that some systems such as Solaris do not give an EOF when
- # the child dies. In fact, you can still try to read
- # from the child_fd -- it will block forever or until TIMEOUT.
- # For this case, I test isalive() before doing any reading.
- # If isalive() is false, then I pretend that this is the same as EOF.
- if not self.isalive():
- # timeout of 0 means "poll"
- r, w, e = self.__select([self.child_fd], [], [], 0)
- if not r:
- self.flag_eof = True
- raise EOF(
- 'End Of File (EOF) in read_nonblocking(). Braindead platform.')
- elif self.__irix_hack:
- # This is a hack for Irix. It seems that Irix requires a long delay before checking isalive.
- # This adds a 2 second delay, but only when the child is
- # terminated.
- r, w, e = self.__select([self.child_fd], [], [], 2)
- if not r and not self.isalive():
- self.flag_eof = True
- raise EOF(
- 'End Of File (EOF) in read_nonblocking(). Pokey platform.')
-
- r, w, e = self.__select([self.child_fd], [], [], timeout)
-
- if not r:
- if not self.isalive():
- # Some platforms, such as Irix, will claim that their processes are alive;
- # then timeout on the select; and then finally admit that they
- # are not alive.
- self.flag_eof = True
- raise EOF(
- 'End of File (EOF) in read_nonblocking(). Very pokey platform.')
- else:
- raise TIMEOUT('Timeout exceeded in read_nonblocking().')
-
- if self.child_fd in r:
- try:
- s = os.read(self.child_fd, size)
- except OSError as e: # Linux does this
- self.flag_eof = True
- raise EOF(
- 'End Of File (EOF) in read_nonblocking(). Exception style platform.')
- if s == '': # BSD style
- self.flag_eof = True
- raise EOF(
- 'End Of File (EOF) in read_nonblocking(). Empty string style platform.')
-
- if self.logfile is not None:
- self.logfile.write(s)
- self.logfile.flush()
- if self.logfile_read is not None:
- self.logfile_read.write(s)
- self.logfile_read.flush()
-
- return s
-
- raise ExceptionPexpect(
- 'Reached an unexpected state in read_nonblocking().')
-
- def read(self, size=-1): # File-like object.
- """This reads at most "size" bytes from the file (less if the read hits
- EOF before obtaining size bytes). If the size argument is negative or
- omitted, read all data until EOF is reached. The bytes are returned as
- a string object. An empty string is returned when EOF is encountered
- immediately. """
-
- if size == 0:
- return ''
- if size < 0:
- self.expect(self.delimiter) # delimiter default is EOF
- return self.before
-
- # I could have done this more directly by not using expect(), but
- # I deliberately decided to couple read() to expect() so that
- # I would catch any bugs early and ensure consistant behavior.
- # It's a little less efficient, but there is less for me to
- # worry about if I have to later modify read() or expect().
- # Note, it's OK if size==-1 in the regex. That just means it
- # will never match anything in which case we stop only on EOF.
- cre = re.compile('.{%d}' % size, re.DOTALL)
- index = self.expect([cre, self.delimiter]) # delimiter default is EOF
- if index == 0:
- return self.after # self.before should be ''. Should I assert this?
- return self.before
-
- def readline(self, size=-1): # File-like object.
- """This reads and returns one entire line. A trailing newline is kept
- in the string, but may be absent when a file ends with an incomplete
- line. Note: This readline() looks for a \\r\\n pair even on UNIX
- because this is what the pseudo tty device returns. So contrary to what
- you may expect you will receive the newline as \\r\\n. An empty string
- is returned when EOF is hit immediately. Currently, the size argument is
- mostly ignored, so this behavior is not standard for a file-like
- object. If size is 0 then an empty string is returned. """
-
- if size == 0:
- return ''
- # delimiter default is EOF
- index = self.expect(['\r\n', self.delimiter])
- if index == 0:
- return self.before + '\r\n'
- else:
- return self.before
-
- def __iter__(self): # File-like object.
- """This is to support iterators over a file-like object.
- """
-
- return self
-
- def next(self): # File-like object.
- """This is to support iterators over a file-like object.
- """
-
- result = self.readline()
- if result == "":
- raise StopIteration
- return result
-
- def readlines(self, sizehint=-1): # File-like object.
- """This reads until EOF using readline() and returns a list containing
- the lines thus read. The optional "sizehint" argument is ignored. """
-
- lines = []
- while True:
- line = self.readline()
- if not line:
- break
- lines.append(line)
- return lines
-
- def write(self, s): # File-like object.
- """This is similar to send() except that there is no return value.
- """
-
- self.send(s)
-
- def writelines(self, sequence): # File-like object.
- """This calls write() for each element in the sequence. The sequence
- can be any iterable object producing strings, typically a list of
- strings. This does not add line separators There is no return value.
- """
-
- for s in sequence:
- self.write(s)
-
- def send(self, s):
- """This sends a string to the child process. This returns the number of
- bytes written. If a log file was set then the data is also written to
- the log. """
-
- time.sleep(self.delaybeforesend)
- if self.logfile is not None:
- self.logfile.write(s)
- self.logfile.flush()
- if self.logfile_send is not None:
- self.logfile_send.write(s)
- self.logfile_send.flush()
- c = os.write(self.child_fd, s)
- return c
-
- def sendline(self, s=''):
- """This is like send(), but it adds a line feed (os.linesep). This
- returns the number of bytes written. """
-
- n = self.send(s)
- n = n + self.send(os.linesep)
- return n
-
- def sendcontrol(self, char):
- """This sends a control character to the child such as Ctrl-C or
- Ctrl-D. For example, to send a Ctrl-G (ASCII 7)::
-
- child.sendcontrol('g')
-
- See also, sendintr() and sendeof().
- """
-
- char = char.lower()
- a = ord(char)
- if a >= 97 and a <= 122:
- a = a - ord('a') + 1
- return self.send(chr(a))
- d = {'@': 0, '`': 0,
- '[': 27, '{': 27,
- '\\': 28, '|': 28,
- ']': 29, '}': 29,
- '^': 30, '~': 30,
- '_': 31,
- '?': 127}
- if char not in d:
- return 0
- return self.send(chr(d[char]))
-
- def sendeof(self):
- """This sends an EOF to the child. This sends a character which causes
- the pending parent output buffer to be sent to the waiting child
- program without waiting for end-of-line. If it is the first character
- of the line, the read() in the user program returns 0, which signifies
- end-of-file. This means to work as expected a sendeof() has to be
- called at the beginning of a line. This method does not send a newline.
- It is the responsibility of the caller to ensure the eof is sent at the
- beginning of a line. """
-
- # Hmmm... how do I send an EOF?
- # C if ((m = write(pty, *buf, p - *buf)) < 0)
- # C return (errno == EWOULDBLOCK) ? n : -1;
- #fd = sys.stdin.fileno()
- # old = termios.tcgetattr(fd) # remember current state
- #attr = termios.tcgetattr(fd)
- # attr[3] = attr[3] | termios.ICANON # ICANON must be set to recognize EOF
- # try: # use try/finally to ensure state gets restored
- # termios.tcsetattr(fd, termios.TCSADRAIN, attr)
- # if hasattr(termios, 'CEOF'):
- # os.write (self.child_fd, '%c' % termios.CEOF)
- # else:
- # # Silly platform does not define CEOF so assume CTRL-D
- # os.write (self.child_fd, '%c' % 4)
- # finally: # restore state
- # termios.tcsetattr(fd, termios.TCSADRAIN, old)
- if hasattr(termios, 'VEOF'):
- char = termios.tcgetattr(self.child_fd)[6][termios.VEOF]
- else:
- # platform does not define VEOF so assume CTRL-D
- char = chr(4)
- self.send(char)
-
- def sendintr(self):
- """This sends a SIGINT to the child. It does not require
- the SIGINT to be the first character on a line. """
-
- if hasattr(termios, 'VINTR'):
- char = termios.tcgetattr(self.child_fd)[6][termios.VINTR]
- else:
- # platform does not define VINTR so assume CTRL-C
- char = chr(3)
- self.send(char)
-
- def eof(self):
- """This returns True if the EOF exception was ever raised.
- """
-
- return self.flag_eof
-
- def terminate(self, force=False):
- """This forces a child process to terminate. It starts nicely with
- SIGHUP and SIGINT. If "force" is True then moves onto SIGKILL. This
- returns True if the child was terminated. This returns False if the
- child could not be terminated. """
-
- if not self.isalive():
- return True
- try:
- self.kill(signal.SIGHUP)
- time.sleep(self.delayafterterminate)
- if not self.isalive():
- return True
- self.kill(signal.SIGCONT)
- time.sleep(self.delayafterterminate)
- if not self.isalive():
- return True
- self.kill(signal.SIGINT)
- time.sleep(self.delayafterterminate)
- if not self.isalive():
- return True
- if force:
- self.kill(signal.SIGKILL)
- time.sleep(self.delayafterterminate)
- if not self.isalive():
- return True
- else:
- return False
- return False
- except OSError as e:
- # I think there are kernel timing issues that sometimes cause
- # this to happen. I think isalive() reports True, but the
- # process is dead to the kernel.
- # Make one last attempt to see if the kernel is up to date.
- time.sleep(self.delayafterterminate)
- if not self.isalive():
- return True
- else:
- return False
-
- def wait(self):
- """This waits until the child exits. This is a blocking call. This will
- not read any data from the child, so this will block forever if the
- child has unread output and has terminated. In other words, the child
- may have printed output then called exit(); but, technically, the child
- is still alive until its output is read. """
-
- if self.isalive():
- pid, status = os.waitpid(self.pid, 0)
- else:
- raise ExceptionPexpect('Cannot wait for dead child process.')
- self.exitstatus = os.WEXITSTATUS(status)
- if os.WIFEXITED(status):
- self.status = status
- self.exitstatus = os.WEXITSTATUS(status)
- self.signalstatus = None
- self.terminated = True
- elif os.WIFSIGNALED(status):
- self.status = status
- self.exitstatus = None
- self.signalstatus = os.WTERMSIG(status)
- self.terminated = True
- elif os.WIFSTOPPED(status):
- raise ExceptionPexpect(
- 'Wait was called for a child process that is stopped. This is not supported. Is some other process attempting job control with our child pid?')
- return self.exitstatus
-
- def isalive(self):
- """This tests if the child process is running or not. This is
- non-blocking. If the child was terminated then this will read the
- exitstatus or signalstatus of the child. This returns True if the child
- process appears to be running or False if not. It can take literally
- SECONDS for Solaris to return the right status. """
-
- if self.terminated:
- return False
-
- if self.flag_eof:
- # This is for Linux, which requires the blocking form of waitpid to get
- # status of a defunct process. This is super-lame. The flag_eof would have
- # been set in read_nonblocking(), so this should be safe.
- waitpid_options = 0
- else:
- waitpid_options = os.WNOHANG
-
- try:
- pid, status = os.waitpid(self.pid, waitpid_options)
- except OSError as e: # No child processes
- if e[0] == errno.ECHILD:
- raise ExceptionPexpect(
- 'isalive() encountered condition where "terminated" is 0, but there was no child process. Did someone else call waitpid() on our process?')
- else:
- raise e
-
- # I have to do this twice for Solaris. I can't even believe that I figured this out...
- # If waitpid() returns 0 it means that no child process wishes to
- # report, and the value of status is undefined.
- if pid == 0:
- try:
- pid, status = os.waitpid(
- self.pid, waitpid_options) # os.WNOHANG) # Solaris!
- except OSError as e: # This should never happen...
- if e[0] == errno.ECHILD:
- raise ExceptionPexpect(
- 'isalive() encountered condition that should never happen. There was no child process. Did someone else call waitpid() on our process?')
- else:
- raise e
-
- # If pid is still 0 after two calls to waitpid() then
- # the process really is alive. This seems to work on all platforms, except
- # for Irix which seems to require a blocking call on waitpid or select, so I let read_nonblocking
- # take care of this situation (unfortunately, this requires waiting
- # through the timeout).
- if pid == 0:
- return True
-
- if pid == 0:
- return True
-
- if os.WIFEXITED(status):
- self.status = status
- self.exitstatus = os.WEXITSTATUS(status)
- self.signalstatus = None
- self.terminated = True
- elif os.WIFSIGNALED(status):
- self.status = status
- self.exitstatus = None
- self.signalstatus = os.WTERMSIG(status)
- self.terminated = True
- elif os.WIFSTOPPED(status):
- raise ExceptionPexpect(
- 'isalive() encountered condition where child process is stopped. This is not supported. Is some other process attempting job control with our child pid?')
- return False
-
- def kill(self, sig):
- """This sends the given signal to the child application. In keeping
- with UNIX tradition it has a misleading name. It does not necessarily
- kill the child unless you send the right signal. """
-
- # Same as os.kill, but the pid is given for you.
- if self.isalive():
- os.kill(self.pid, sig)
-
- def compile_pattern_list(self, patterns):
- """This compiles a pattern-string or a list of pattern-strings.
- Patterns must be a StringType, EOF, TIMEOUT, SRE_Pattern, or a list of
- those. Patterns may also be None which results in an empty list (you
- might do this if waiting for an EOF or TIMEOUT condition without
- expecting any pattern).
-
- This is used by expect() when calling expect_list(). Thus expect() is
- nothing more than::
-
- cpl = self.compile_pattern_list(pl)
- return self.expect_list(cpl, timeout)
-
- If you are using expect() within a loop it may be more
- efficient to compile the patterns first and then call expect_list().
- This avoid calls in a loop to compile_pattern_list()::
-
- cpl = self.compile_pattern_list(my_pattern)
- while some_condition:
- ...
- i = self.expect_list(clp, timeout)
- ...
- """
-
- if patterns is None:
- return []
- if not isinstance(patterns, types.ListType):
- patterns = [patterns]
-
- compile_flags = re.DOTALL # Allow dot to match \n
- if self.ignorecase:
- compile_flags = compile_flags | re.IGNORECASE
- compiled_pattern_list = []
- for p in patterns:
- if type(p) in types.StringTypes:
- compiled_pattern_list.append(re.compile(p, compile_flags))
- elif p is EOF:
- compiled_pattern_list.append(EOF)
- elif p is TIMEOUT:
- compiled_pattern_list.append(TIMEOUT)
- elif isinstance(p, type(re.compile(''))):
- compiled_pattern_list.append(p)
- else:
- raise TypeError(
- 'Argument must be one of StringTypes, EOF, TIMEOUT, SRE_Pattern, or a list of those type. %s' % str(
- type(p)))
-
- return compiled_pattern_list
-
- def expect(self, pattern, timeout=-1, searchwindowsize=-1):
- """This seeks through the stream until a pattern is matched. The
- pattern is overloaded and may take several types. The pattern can be a
- StringType, EOF, a compiled re, or a list of any of those types.
- Strings will be compiled to re types. This returns the index into the
- pattern list. If the pattern was not a list this returns index 0 on a
- successful match. This may raise exceptions for EOF or TIMEOUT. To
- avoid the EOF or TIMEOUT exceptions add EOF or TIMEOUT to the pattern
- list. That will cause expect to match an EOF or TIMEOUT condition
- instead of raising an exception.
-
- If you pass a list of patterns and more than one matches, the first match
- in the stream is chosen. If more than one pattern matches at that point,
- the leftmost in the pattern list is chosen. For example::
-
- # the input is 'foobar'
- index = p.expect (['bar', 'foo', 'foobar'])
- # returns 1 ('foo') even though 'foobar' is a "better" match
-
- Please note, however, that buffering can affect this behavior, since
- input arrives in unpredictable chunks. For example::
-
- # the input is 'foobar'
- index = p.expect (['foobar', 'foo'])
- # returns 0 ('foobar') if all input is available at once,
- # but returs 1 ('foo') if parts of the final 'bar' arrive late
-
- After a match is found the instance attributes 'before', 'after' and
- 'match' will be set. You can see all the data read before the match in
- 'before'. You can see the data that was matched in 'after'. The
- re.MatchObject used in the re match will be in 'match'. If an error
- occurred then 'before' will be set to all the data read so far and
- 'after' and 'match' will be None.
-
- If timeout is -1 then timeout will be set to the self.timeout value.
-
- A list entry may be EOF or TIMEOUT instead of a string. This will
- catch these exceptions and return the index of the list entry instead
- of raising the exception. The attribute 'after' will be set to the
- exception type. The attribute 'match' will be None. This allows you to
- write code like this::
-
- index = p.expect (['good', 'bad', pexpect.EOF, pexpect.TIMEOUT])
- if index == 0:
- do_something()
- elif index == 1:
- do_something_else()
- elif index == 2:
- do_some_other_thing()
- elif index == 3:
- do_something_completely_different()
-
- instead of code like this::
-
- try:
- index = p.expect (['good', 'bad'])
- if index == 0:
- do_something()
- elif index == 1:
- do_something_else()
- except EOF:
- do_some_other_thing()
- except TIMEOUT:
- do_something_completely_different()
-
- These two forms are equivalent. It all depends on what you want. You
- can also just expect the EOF if you are waiting for all output of a
- child to finish. For example::
-
- p = pexpect.spawn('/bin/ls')
- p.expect (pexpect.EOF)
- print p.before
-
- If you are trying to optimize for speed then see expect_list().
- """
-
- compiled_pattern_list = self.compile_pattern_list(pattern)
- return self.expect_list(
- compiled_pattern_list,
- timeout,
- searchwindowsize)
-
- def expect_list(self, pattern_list, timeout=-1, searchwindowsize=-1):
- """This takes a list of compiled regular expressions and returns the
- index into the pattern_list that matched the child output. The list may
- also contain EOF or TIMEOUT (which are not compiled regular
- expressions). This method is similar to the expect() method except that
- expect_list() does not recompile the pattern list on every call. This
- may help if you are trying to optimize for speed, otherwise just use
- the expect() method. This is called by expect(). If timeout==-1 then
- the self.timeout value is used. If searchwindowsize==-1 then the
- self.searchwindowsize value is used. """
-
- return self.expect_loop(
- searcher_re(pattern_list),
- timeout,
- searchwindowsize)
-
- def expect_exact(self, pattern_list, timeout=-1, searchwindowsize=-1):
- """This is similar to expect(), but uses plain string matching instead
- of compiled regular expressions in 'pattern_list'. The 'pattern_list'
- may be a string; a list or other sequence of strings; or TIMEOUT and
- EOF.
-
- This call might be faster than expect() for two reasons: string
- searching is faster than RE matching and it is possible to limit the
- search to just the end of the input buffer.
-
- This method is also useful when you don't want to have to worry about
- escaping regular expression characters that you want to match."""
-
- if type(pattern_list) in types.StringTypes or pattern_list in (
- TIMEOUT, EOF):
- pattern_list = [pattern_list]
- return self.expect_loop(
- searcher_string(pattern_list),
- timeout,
- searchwindowsize)
-
- def expect_loop(self, searcher, timeout=-1, searchwindowsize=-1):
- """This is the common loop used inside expect. The 'searcher' should be
- an instance of searcher_re or searcher_string, which describes how and what
- to search for in the input.
-
- See expect() for other arguments, return value and exceptions. """
-
- self.searcher = searcher
-
- if timeout == -1:
- timeout = self.timeout
- if timeout is not None:
- end_time = time.time() + timeout
- if searchwindowsize == -1:
- searchwindowsize = self.searchwindowsize
-
- try:
- incoming = self.buffer
- freshlen = len(incoming)
- while True: # Keep reading until exception or return.
- index = searcher.search(incoming, freshlen, searchwindowsize)
- if index >= 0:
- self.buffer = incoming[searcher.end:]
- self.before = incoming[: searcher.start]
- self.after = incoming[searcher.start: searcher.end]
- self.match = searcher.match
- self.match_index = index
- return self.match_index
- # No match at this point
- if timeout < 0 and timeout is not None:
- raise TIMEOUT('Timeout exceeded in expect_any().')
- # Still have time left, so read more data
- c = self.read_nonblocking(self.maxread, timeout)
- freshlen = len(c)
- time.sleep(0.0001)
- incoming = incoming + c
- if timeout is not None:
- timeout = end_time - time.time()
- except EOF as e:
- self.buffer = ''
- self.before = incoming
- self.after = EOF
- index = searcher.eof_index
- if index >= 0:
- self.match = EOF
- self.match_index = index
- return self.match_index
- else:
- self.match = None
- self.match_index = None
- raise EOF(str(e) + '\n' + str(self))
- except TIMEOUT as e:
- self.buffer = incoming
- self.before = incoming
- self.after = TIMEOUT
- index = searcher.timeout_index
- if index >= 0:
- self.match = TIMEOUT
- self.match_index = index
- return self.match_index
- else:
- self.match = None
- self.match_index = None
- raise TIMEOUT(str(e) + '\n' + str(self))
- except:
- self.before = incoming
- self.after = None
- self.match = None
- self.match_index = None
- raise
-
- def getwinsize(self):
- """This returns the terminal window size of the child tty. The return
- value is a tuple of (rows, cols). """
-
- TIOCGWINSZ = getattr(termios, 'TIOCGWINSZ', 1074295912)
- s = struct.pack('HHHH', 0, 0, 0, 0)
- x = fcntl.ioctl(self.fileno(), TIOCGWINSZ, s)
- return struct.unpack('HHHH', x)[0:2]
-
- def setwinsize(self, r, c):
- """This sets the terminal window size of the child tty. This will cause
- a SIGWINCH signal to be sent to the child. This does not change the
- physical window size. It changes the size reported to TTY-aware
- applications like vi or curses -- applications that respond to the
- SIGWINCH signal. """
-
- # Some very old platforms have a bug that causes the value for
- # termios.TIOCSWINSZ to be truncated. There was a hack here to work
- # around this, but it caused problems with newer platforms so has been
- # removed. For details see https://github.com/pexpect/pexpect/issues/39
- TIOCSWINSZ = getattr(termios, 'TIOCSWINSZ', -2146929561)
- # Note, assume ws_xpixel and ws_ypixel are zero.
- s = struct.pack('HHHH', r, c, 0, 0)
- fcntl.ioctl(self.fileno(), TIOCSWINSZ, s)
-
- def interact(
- self,
- escape_character=chr(29),
- input_filter=None,
- output_filter=None):
- """This gives control of the child process to the interactive user (the
- human at the keyboard). Keystrokes are sent to the child process, and
- the stdout and stderr output of the child process is printed. This
- simply echos the child stdout and child stderr to the real stdout and
- it echos the real stdin to the child stdin. When the user types the
- escape_character this method will stop. The default for
- escape_character is ^]. This should not be confused with ASCII 27 --
- the ESC character. ASCII 29 was chosen for historical merit because
- this is the character used by 'telnet' as the escape character. The
- escape_character will not be sent to the child process.
-
- You may pass in optional input and output filter functions. These
- functions should take a string and return a string. The output_filter
- will be passed all the output from the child process. The input_filter
- will be passed all the keyboard input from the user. The input_filter
- is run BEFORE the check for the escape_character.
-
- Note that if you change the window size of the parent the SIGWINCH
- signal will not be passed through to the child. If you want the child
- window size to change when the parent's window size changes then do
- something like the following example::
-
- import pexpect, struct, fcntl, termios, signal, sys
- def sigwinch_passthrough (sig, data):
- s = struct.pack("HHHH", 0, 0, 0, 0)
- a = struct.unpack('hhhh', fcntl.ioctl(sys.stdout.fileno(), termios.TIOCGWINSZ , s))
- global p
- p.setwinsize(a[0],a[1])
- p = pexpect.spawn('/bin/bash') # Note this is global and used in sigwinch_passthrough.
- signal.signal(signal.SIGWINCH, sigwinch_passthrough)
- p.interact()
- """
-
- # Flush the buffer.
- self.stdout.write(self.buffer)
- self.stdout.flush()
- self.buffer = ''
- mode = tty.tcgetattr(self.STDIN_FILENO)
- tty.setraw(self.STDIN_FILENO)
- try:
- self.__interact_copy(escape_character, input_filter, output_filter)
- finally:
- tty.tcsetattr(self.STDIN_FILENO, tty.TCSAFLUSH, mode)
-
- def __interact_writen(self, fd, data):
- """This is used by the interact() method.
- """
-
- while data != '' and self.isalive():
- n = os.write(fd, data)
- data = data[n:]
-
- def __interact_read(self, fd):
- """This is used by the interact() method.
- """
-
- return os.read(fd, 1000)
-
- def __interact_copy(
- self,
- escape_character=None,
- input_filter=None,
- output_filter=None):
- """This is used by the interact() method.
- """
-
- while self.isalive():
- r, w, e = self.__select([self.child_fd, self.STDIN_FILENO], [], [])
- if self.child_fd in r:
- data = self.__interact_read(self.child_fd)
- if output_filter:
- data = output_filter(data)
- if self.logfile is not None:
- self.logfile.write(data)
- self.logfile.flush()
- os.write(self.STDOUT_FILENO, data)
- if self.STDIN_FILENO in r:
- data = self.__interact_read(self.STDIN_FILENO)
- if input_filter:
- data = input_filter(data)
- i = data.rfind(escape_character)
- if i != -1:
- data = data[:i]
- self.__interact_writen(self.child_fd, data)
- break
- self.__interact_writen(self.child_fd, data)
-
- def __select(self, iwtd, owtd, ewtd, timeout=None):
- """This is a wrapper around select.select() that ignores signals. If
- select.select raises a select.error exception and errno is an EINTR
- error then it is ignored. Mainly this is used to ignore sigwinch
- (terminal resize). """
-
- # if select() is interrupted by a signal (errno==EINTR) then
- # we loop back and enter the select() again.
- if timeout is not None:
- end_time = time.time() + timeout
- while True:
- try:
- return select.select(iwtd, owtd, ewtd, timeout)
- except select.error as e:
- if e[0] == errno.EINTR:
- # if we loop back we have to subtract the amount of time we
- # already waited.
- if timeout is not None:
- timeout = end_time - time.time()
- if timeout < 0:
- return ([], [], [])
- else: # something else caused the select.error, so this really is an exception
- raise
-
-##############################################################################
-# The following methods are no longer supported or allowed.
-
- def setmaxread(self, maxread):
- """This method is no longer supported or allowed. I don't like getters
- and setters without a good reason. """
-
- raise ExceptionPexpect(
- 'This method is no longer supported or allowed. Just assign a value to the maxread member variable.')
-
- def setlog(self, fileobject):
- """This method is no longer supported or allowed.
- """
-
- raise ExceptionPexpect(
- 'This method is no longer supported or allowed. Just assign a value to the logfile member variable.')
-
-##############################################################################
-# End of spawn class
-##############################################################################
-
-
-class searcher_string (object):
-
- """This is a plain string search helper for the spawn.expect_any() method.
-
- Attributes:
-
- eof_index - index of EOF, or -1
- timeout_index - index of TIMEOUT, or -1
-
- After a successful match by the search() method the following attributes
- are available:
-
- start - index into the buffer, first byte of match
- end - index into the buffer, first byte after match
- match - the matching string itself
- """
-
- def __init__(self, strings):
- """This creates an instance of searcher_string. This argument 'strings'
- may be a list; a sequence of strings; or the EOF or TIMEOUT types. """
-
- self.eof_index = -1
- self.timeout_index = -1
- self._strings = []
- for n, s in zip(range(len(strings)), strings):
- if s is EOF:
- self.eof_index = n
- continue
- if s is TIMEOUT:
- self.timeout_index = n
- continue
- self._strings.append((n, s))
-
- def __str__(self):
- """This returns a human-readable string that represents the state of
- the object."""
-
- ss = [(ns[0], ' %d: "%s"' % ns) for ns in self._strings]
- ss.append((-1, 'searcher_string:'))
- if self.eof_index >= 0:
- ss.append((self.eof_index, ' %d: EOF' % self.eof_index))
- if self.timeout_index >= 0:
- ss.append(
- (self.timeout_index,
- ' %d: TIMEOUT' %
- self.timeout_index))
- ss.sort()
- ss = zip(*ss)[1]
- return '\n'.join(ss)
-
- def search(self, buffer, freshlen, searchwindowsize=None):
- """This searches 'buffer' for the first occurence of one of the search
- strings. 'freshlen' must indicate the number of bytes at the end of
- 'buffer' which have not been searched before. It helps to avoid
- searching the same, possibly big, buffer over and over again.
-
- See class spawn for the 'searchwindowsize' argument.
-
- If there is a match this returns the index of that string, and sets
- 'start', 'end' and 'match'. Otherwise, this returns -1. """
-
- absurd_match = len(buffer)
- first_match = absurd_match
-
- # 'freshlen' helps a lot here. Further optimizations could
- # possibly include:
- #
- # using something like the Boyer-Moore Fast String Searching
- # Algorithm; pre-compiling the search through a list of
- # strings into something that can scan the input once to
- # search for all N strings; realize that if we search for
- # ['bar', 'baz'] and the input is '...foo' we need not bother
- # rescanning until we've read three more bytes.
- #
- # Sadly, I don't know enough about this interesting topic. /grahn
-
- for index, s in self._strings:
- if searchwindowsize is None:
- # the match, if any, can only be in the fresh data,
- # or at the very end of the old data
- offset = -(freshlen + len(s))
- else:
- # better obey searchwindowsize
- offset = -searchwindowsize
- n = buffer.find(s, offset)
- if n >= 0 and n < first_match:
- first_match = n
- best_index, best_match = index, s
- if first_match == absurd_match:
- return -1
- self.match = best_match
- self.start = first_match
- self.end = self.start + len(self.match)
- return best_index
-
-
-class searcher_re (object):
-
- """This is regular expression string search helper for the
- spawn.expect_any() method.
-
- Attributes:
-
- eof_index - index of EOF, or -1
- timeout_index - index of TIMEOUT, or -1
-
- After a successful match by the search() method the following attributes
- are available:
-
- start - index into the buffer, first byte of match
- end - index into the buffer, first byte after match
- match - the re.match object returned by a succesful re.search
-
- """
-
- def __init__(self, patterns):
- """This creates an instance that searches for 'patterns' Where
- 'patterns' may be a list or other sequence of compiled regular
- expressions, or the EOF or TIMEOUT types."""
-
- self.eof_index = -1
- self.timeout_index = -1
- self._searches = []
- for n, s in zip(range(len(patterns)), patterns):
- if s is EOF:
- self.eof_index = n
- continue
- if s is TIMEOUT:
- self.timeout_index = n
- continue
- self._searches.append((n, s))
-
- def __str__(self):
- """This returns a human-readable string that represents the state of
- the object."""
-
- ss = [(n, ' %d: re.compile("%s")' % (n, str(s.pattern)))
- for n, s in self._searches]
- ss.append((-1, 'searcher_re:'))
- if self.eof_index >= 0:
- ss.append((self.eof_index, ' %d: EOF' % self.eof_index))
- if self.timeout_index >= 0:
- ss.append(
- (self.timeout_index,
- ' %d: TIMEOUT' %
- self.timeout_index))
- ss.sort()
- ss = zip(*ss)[1]
- return '\n'.join(ss)
-
- def search(self, buffer, freshlen, searchwindowsize=None):
- """This searches 'buffer' for the first occurence of one of the regular
- expressions. 'freshlen' must indicate the number of bytes at the end of
- 'buffer' which have not been searched before.
-
- See class spawn for the 'searchwindowsize' argument.
-
- If there is a match this returns the index of that string, and sets
- 'start', 'end' and 'match'. Otherwise, returns -1."""
-
- absurd_match = len(buffer)
- first_match = absurd_match
- # 'freshlen' doesn't help here -- we cannot predict the
- # length of a match, and the re module provides no help.
- if searchwindowsize is None:
- searchstart = 0
- else:
- searchstart = max(0, len(buffer) - searchwindowsize)
- for index, s in self._searches:
- match = s.search(buffer, searchstart)
- if match is None:
- continue
- n = match.start()
- if n < first_match:
- first_match = n
- the_match = match
- best_index = index
- if first_match == absurd_match:
- return -1
- self.start = first_match
- self.match = the_match
- self.end = self.match.end()
- return best_index
-
-
-def which(filename):
- """This takes a given filename; tries to find it in the environment path;
- then checks if it is executable. This returns the full path to the filename
- if found and executable. Otherwise this returns None."""
-
- # Special case where filename already contains a path.
- if os.path.dirname(filename) != '':
- if os.access(filename, os.X_OK):
- return filename
-
- if 'PATH' not in os.environ or os.environ['PATH'] == '':
- p = os.defpath
- else:
- p = os.environ['PATH']
-
- # Oddly enough this was the one line that made Pexpect
- # incompatible with Python 1.5.2.
- #pathlist = p.split (os.pathsep)
- pathlist = string.split(p, os.pathsep)
-
- for path in pathlist:
- f = os.path.join(path, filename)
- if os.access(f, os.X_OK):
- return f
- return None
-
-
-def split_command_line(command_line):
- """This splits a command line into a list of arguments. It splits arguments
- on spaces, but handles embedded quotes, doublequotes, and escaped
- characters. It's impossible to do this with a regular expression, so I
- wrote a little state machine to parse the command line. """
-
- arg_list = []
- arg = ''
-
- # Constants to name the states we can be in.
- state_basic = 0
- state_esc = 1
- state_singlequote = 2
- state_doublequote = 3
- state_whitespace = 4 # The state of consuming whitespace between commands.
- state = state_basic
-
- for c in command_line:
- if state == state_basic or state == state_whitespace:
- if c == '\\': # Escape the next character
- state = state_esc
- elif c == r"'": # Handle single quote
- state = state_singlequote
- elif c == r'"': # Handle double quote
- state = state_doublequote
- elif c.isspace():
- # Add arg to arg_list if we aren't in the middle of whitespace.
- if state == state_whitespace:
- None # Do nothing.
- else:
- arg_list.append(arg)
- arg = ''
- state = state_whitespace
- else:
- arg = arg + c
- state = state_basic
- elif state == state_esc:
- arg = arg + c
- state = state_basic
- elif state == state_singlequote:
- if c == r"'":
- state = state_basic
- else:
- arg = arg + c
- elif state == state_doublequote:
- if c == r'"':
- state = state_basic
- else:
- arg = arg + c
-
- if arg != '':
- arg_list.append(arg)
- return arg_list
-
-# vi:ts=4:sw=4:expandtab:ft=python:
Index: third_party/Python/module/pexpect-2.4/pxssh.py
===================================================================
--- third_party/Python/module/pexpect-2.4/pxssh.py
+++ third_party/Python/module/pexpect-2.4/pxssh.py
@@ -1,367 +0,0 @@
-"""This class extends pexpect.spawn to specialize setting up SSH connections.
-This adds methods for login, logout, and expecting the shell prompt.
-
-$Id: pxssh.py 513 2008-02-09 18:26:13Z noah $
-"""
-
-from pexpect import *
-import pexpect
-import time
-
-__all__ = ['ExceptionPxssh', 'pxssh']
-
-# Exception classes used by this module.
-
-
-class ExceptionPxssh(ExceptionPexpect):
- """Raised for pxssh exceptions.
- """
-
-
-class pxssh (spawn):
-
- """This class extends pexpect.spawn to specialize setting up SSH
- connections. This adds methods for login, logout, and expecting the shell
- prompt. It does various tricky things to handle many situations in the SSH
- login process. For example, if the session is your first login, then pxssh
- automatically accepts the remote certificate; or if you have public key
- authentication setup then pxssh won't wait for the password prompt.
-
- pxssh uses the shell prompt to synchronize output from the remote host. In
- order to make this more robust it sets the shell prompt to something more
- unique than just $ or #. This should work on most Borne/Bash or Csh style
- shells.
-
- Example that runs a few commands on a remote server and prints the result::
-
- import pxssh
- import getpass
- try:
- s = pxssh.pxssh()
- hostname = raw_input('hostname: ')
- username = raw_input('username: ')
- password = getpass.getpass('password: ')
- s.login (hostname, username, password)
- s.sendline ('uptime') # run a command
- s.prompt() # match the prompt
- print s.before # print everything before the prompt.
- s.sendline ('ls -l')
- s.prompt()
- print s.before
- s.sendline ('df')
- s.prompt()
- print s.before
- s.logout()
- except pxssh.ExceptionPxssh, e:
- print "pxssh failed on login."
- print str(e)
-
- Note that if you have ssh-agent running while doing development with pxssh
- then this can lead to a lot of confusion. Many X display managers (xdm,
- gdm, kdm, etc.) will automatically start a GUI agent. You may see a GUI
- dialog box popup asking for a password during development. You should turn
- off any key agents during testing. The 'force_password' attribute will turn
- off public key authentication. This will only work if the remote SSH server
- is configured to allow password logins. Example of using 'force_password'
- attribute::
-
- s = pxssh.pxssh()
- s.force_password = True
- hostname = raw_input('hostname: ')
- username = raw_input('username: ')
- password = getpass.getpass('password: ')
- s.login (hostname, username, password)
- """
-
- def __init__(
- self,
- timeout=30,
- maxread=2000,
- searchwindowsize=None,
- logfile=None,
- cwd=None,
- env=None):
- spawn.__init__(
- self,
- None,
- timeout=timeout,
- maxread=maxread,
- searchwindowsize=searchwindowsize,
- logfile=logfile,
- cwd=cwd,
- env=env)
-
- self.name = ''
-
- # SUBTLE HACK ALERT! Note that the command to set the prompt uses a
- # slightly different string than the regular expression to match it. This
- # is because when you set the prompt the command will echo back, but we
- # don't want to match the echoed command. So if we make the set command
- # slightly different than the regex we eliminate the problem. To make the
- # set command different we add a backslash in front of $. The $ doesn't
- # need to be escaped, but it doesn't hurt and serves to make the set
- # prompt command different than the regex.
-
- # used to match the command-line prompt
- self.UNIQUE_PROMPT = "\[PEXPECT\][\$\#] "
- self.PROMPT = self.UNIQUE_PROMPT
-
- # used to set shell command-line prompt to UNIQUE_PROMPT.
- self.PROMPT_SET_SH = "PS1='[PEXPECT]\$ '"
- self.PROMPT_SET_CSH = "set prompt='[PEXPECT]\$ '"
- self.SSH_OPTS = "-o'RSAAuthentication=no' -o 'PubkeyAuthentication=no'"
- # Disabling X11 forwarding gets rid of the annoying SSH_ASKPASS from
- # displaying a GUI password dialog. I have not figured out how to
- # disable only SSH_ASKPASS without also disabling X11 forwarding.
- # Unsetting SSH_ASKPASS on the remote side doesn't disable it! Annoying!
- #self.SSH_OPTS = "-x -o'RSAAuthentication=no' -o 'PubkeyAuthentication=no'"
- self.force_password = False
- self.auto_prompt_reset = True
-
- def levenshtein_distance(self, a, b):
- """This calculates the Levenshtein distance between a and b.
- """
-
- n, m = len(a), len(b)
- if n > m:
- a, b = b, a
- n, m = m, n
- current = range(n + 1)
- for i in range(1, m + 1):
- previous, current = current, [i] + [0] * n
- for j in range(1, n + 1):
- add, delete = previous[j] + 1, current[j - 1] + 1
- change = previous[j - 1]
- if a[j - 1] != b[i - 1]:
- change = change + 1
- current[j] = min(add, delete, change)
- return current[n]
-
- def sync_original_prompt(self):
- """This attempts to find the prompt. Basically, press enter and record
- the response; press enter again and record the response; if the two
- responses are similar then assume we are at the original prompt. This
- is a slow function. It can take over 10 seconds. """
-
- # All of these timing pace values are magic.
- # I came up with these based on what seemed reliable for
- # connecting to a heavily loaded machine I have.
- # If latency is worse than these values then this will fail.
-
- try:
- # GAS: Clear out the cache before getting the prompt
- self.read_nonblocking(size=10000, timeout=1)
- except TIMEOUT:
- pass
- time.sleep(0.1)
- self.sendline()
- time.sleep(0.5)
- x = self.read_nonblocking(size=1000, timeout=1)
- time.sleep(0.1)
- self.sendline()
- time.sleep(0.5)
- a = self.read_nonblocking(size=1000, timeout=1)
- time.sleep(0.1)
- self.sendline()
- time.sleep(0.5)
- b = self.read_nonblocking(size=1000, timeout=1)
- ld = self.levenshtein_distance(a, b)
- len_a = len(a)
- if len_a == 0:
- return False
- if float(ld) / len_a < 0.4:
- return True
- return False
-
- # TODO: This is getting messy and I'm pretty sure this isn't perfect.
- # TODO: I need to draw a flow chart for this.
- def login(
- self,
- server,
- username,
- password='',
- terminal_type='ansi',
- original_prompt=r"[#$]",
- login_timeout=10,
- port=None,
- auto_prompt_reset=True):
- """This logs the user into the given server. It uses the
- 'original_prompt' to try to find the prompt right after login. When it
- finds the prompt it immediately tries to reset the prompt to something
- more easily matched. The default 'original_prompt' is very optimistic
- and is easily fooled. It's more reliable to try to match the original
- prompt as exactly as possible to prevent false matches by server
- strings such as the "Message Of The Day". On many systems you can
- disable the MOTD on the remote server by creating a zero-length file
- called "~/.hushlogin" on the remote server. If a prompt cannot be found
- then this will not necessarily cause the login to fail. In the case of
- a timeout when looking for the prompt we assume that the original
- prompt was so weird that we could not match it, so we use a few tricks
- to guess when we have reached the prompt. Then we hope for the best and
- blindly try to reset the prompt to something more unique. If that fails
- then login() raises an ExceptionPxssh exception.
-
- In some situations it is not possible or desirable to reset the
- original prompt. In this case, set 'auto_prompt_reset' to False to
- inhibit setting the prompt to the UNIQUE_PROMPT. Remember that pxssh
- uses a unique prompt in the prompt() method. If the original prompt is
- not reset then this will disable the prompt() method unless you
- manually set the PROMPT attribute. """
-
- ssh_options = '-q'
- if self.force_password:
- ssh_options = ssh_options + ' ' + self.SSH_OPTS
- if port is not None:
- ssh_options = ssh_options + ' -p %s' % (str(port))
- cmd = "ssh %s -l %s %s" % (ssh_options, username, server)
-
- # This does not distinguish between a remote server 'password' prompt
- # and a local ssh 'passphrase' prompt (for unlocking a private key).
- spawn._spawn(self, cmd)
- i = self.expect(
- [
- "(?i)are you sure you want to continue connecting",
- original_prompt,
- "(?i)(?:password)|(?:passphrase for key)",
- "(?i)permission denied",
- "(?i)terminal type",
- TIMEOUT,
- "(?i)connection closed by remote host"],
- timeout=login_timeout)
-
- # First phase
- if i == 0:
- # New certificate -- always accept it.
- # This is what you get if SSH does not have the remote host's
- # public key stored in the 'known_hosts' cache.
- self.sendline("yes")
- i = self.expect(
- [
- "(?i)are you sure you want to continue connecting",
- original_prompt,
- "(?i)(?:password)|(?:passphrase for key)",
- "(?i)permission denied",
- "(?i)terminal type",
- TIMEOUT])
- if i == 2: # password or passphrase
- self.sendline(password)
- i = self.expect(
- [
- "(?i)are you sure you want to continue connecting",
- original_prompt,
- "(?i)(?:password)|(?:passphrase for key)",
- "(?i)permission denied",
- "(?i)terminal type",
- TIMEOUT])
- if i == 4:
- self.sendline(terminal_type)
- i = self.expect(
- [
- "(?i)are you sure you want to continue connecting",
- original_prompt,
- "(?i)(?:password)|(?:passphrase for key)",
- "(?i)permission denied",
- "(?i)terminal type",
- TIMEOUT])
-
- # Second phase
- if i == 0:
- # This is weird. This should not happen twice in a row.
- self.close()
- raise ExceptionPxssh(
- 'Weird error. Got "are you sure" prompt twice.')
- elif i == 1: # can occur if you have a public key pair set to authenticate.
- # TODO: May NOT be OK if expect() got tricked and matched a false
- # prompt.
- pass
- elif i == 2: # password prompt again
- # For incorrect passwords, some ssh servers will
- # ask for the password again, others return 'denied' right away.
- # If we get the password prompt again then this means
- # we didn't get the password right the first time.
- self.close()
- raise ExceptionPxssh('password refused')
- elif i == 3: # permission denied -- password was bad.
- self.close()
- raise ExceptionPxssh('permission denied')
- elif i == 4: # terminal type again? WTF?
- self.close()
- raise ExceptionPxssh(
- 'Weird error. Got "terminal type" prompt twice.')
- elif i == 5: # Timeout
- # This is tricky... I presume that we are at the command-line prompt.
- # It may be that the shell prompt was so weird that we couldn't match
- # it. Or it may be that we couldn't log in for some other reason. I
- # can't be sure, but it's safe to guess that we did login because if
- # I presume wrong and we are not logged in then this should be caught
- # later when I try to set the shell prompt.
- pass
- elif i == 6: # Connection closed by remote host
- self.close()
- raise ExceptionPxssh('connection closed')
- else: # Unexpected
- self.close()
- raise ExceptionPxssh('unexpected login response')
- if not self.sync_original_prompt():
- self.close()
- raise ExceptionPxssh('could not synchronize with original prompt')
- # We appear to be in.
- # set shell prompt to something unique.
- if auto_prompt_reset:
- if not self.set_unique_prompt():
- self.close()
- raise ExceptionPxssh(
- 'could not set shell prompt\n' + self.before)
- return True
-
- def logout(self):
- """This sends exit to the remote shell. If there are stopped jobs then
- this automatically sends exit twice. """
-
- self.sendline("exit")
- index = self.expect([EOF, "(?i)there are stopped jobs"])
- if index == 1:
- self.sendline("exit")
- self.expect(EOF)
- self.close()
-
- def prompt(self, timeout=20):
- """This matches the shell prompt. This is little more than a short-cut
- to the expect() method. This returns True if the shell prompt was
- matched. This returns False if there was a timeout. Note that if you
- called login() with auto_prompt_reset set to False then you should have
- manually set the PROMPT attribute to a regex pattern for matching the
- prompt. """
-
- i = self.expect([self.PROMPT, TIMEOUT], timeout=timeout)
- if i == 1:
- return False
- return True
-
- def set_unique_prompt(self):
- """This sets the remote prompt to something more unique than # or $.
- This makes it easier for the prompt() method to match the shell prompt
- unambiguously. This method is called automatically by the login()
- method, but you may want to call it manually if you somehow reset the
- shell prompt. For example, if you 'su' to a different user then you
- will need to manually reset the prompt. This sends shell commands to
- the remote host to set the prompt, so this assumes the remote host is
- ready to receive commands.
-
- Alternatively, you may use your own prompt pattern. Just set the PROMPT
- attribute to a regular expression that matches it. In this case you
- should call login() with auto_prompt_reset=False; then set the PROMPT
- attribute. After that the prompt() method will try to match your prompt
- pattern."""
-
- self.sendline("unset PROMPT_COMMAND")
- self.sendline(self.PROMPT_SET_SH) # sh-style
- i = self.expect([TIMEOUT, self.PROMPT], timeout=10)
- if i == 0: # csh-style
- self.sendline(self.PROMPT_SET_CSH)
- i = self.expect([TIMEOUT, self.PROMPT], timeout=10)
- if i == 0:
- return False
- return True
-
-# vi:ts=4:sw=4:expandtab:ft=python:
Index: third_party/Python/module/pexpect-2.4/screen.py
===================================================================
--- third_party/Python/module/pexpect-2.4/screen.py
+++ third_party/Python/module/pexpect-2.4/screen.py
@@ -1,349 +0,0 @@
-"""This implements a virtual screen. This is used to support ANSI terminal
-emulation. The screen representation and state is implemented in this class.
-Most of the methods are inspired by ANSI screen control codes. The ANSI class
-extends this class to add parsing of ANSI escape codes.
-
-$Id: screen.py 486 2007-07-13 01:04:16Z noah $
-"""
-
-import copy
-
-NUL = 0 # Fill character; ignored on input.
-ENQ = 5 # Transmit answerback message.
-BEL = 7 # Ring the bell.
-BS = 8 # Move cursor left.
-HT = 9 # Move cursor to next tab stop.
-LF = 10 # Line feed.
-VT = 11 # Same as LF.
-FF = 12 # Same as LF.
-CR = 13 # Move cursor to left margin or newline.
-SO = 14 # Invoke G1 character set.
-SI = 15 # Invoke G0 character set.
-XON = 17 # Resume transmission.
-XOFF = 19 # Halt transmission.
-CAN = 24 # Cancel escape sequence.
-SUB = 26 # Same as CAN.
-ESC = 27 # Introduce a control sequence.
-DEL = 127 # Fill character; ignored on input.
-SPACE = chr(32) # Space or blank character.
-
-
-def constrain(n, min, max):
- """This returns a number, n constrained to the min and max bounds. """
-
- if n < min:
- return min
- if n > max:
- return max
- return n
-
-
-class screen:
-
- """This object maintains the state of a virtual text screen as a
- rectangluar array. This maintains a virtual cursor position and handles
- scrolling as characters are added. This supports most of the methods needed
- by an ANSI text screen. Row and column indexes are 1-based (not zero-based,
- like arrays). """
-
- def __init__(self, r=24, c=80):
- """This initializes a blank scree of the given dimentions."""
-
- self.rows = r
- self.cols = c
- self.cur_r = 1
- self.cur_c = 1
- self.cur_saved_r = 1
- self.cur_saved_c = 1
- self.scroll_row_start = 1
- self.scroll_row_end = self.rows
- self.w = [[SPACE] * self.cols for c in range(self.rows)]
-
- def __str__(self):
- """This returns a printable representation of the screen. The end of
- each screen line is terminated by a newline. """
-
- return '\n'.join([''.join(c) for c in self.w])
-
- def dump(self):
- """This returns a copy of the screen as a string. This is similar to
- __str__ except that lines are not terminated with line feeds. """
-
- return ''.join([''.join(c) for c in self.w])
-
- def pretty(self):
- """This returns a copy of the screen as a string with an ASCII text box
- around the screen border. This is similar to __str__ except that it
- adds a box. """
-
- top_bot = '+' + '-' * self.cols + '+\n'
- return top_bot + \
- '\n'.join(['|' + line + '|' for line in str(self).split('\n')]) + '\n' + top_bot
-
- def fill(self, ch=SPACE):
-
- self.fill_region(1, 1, self.rows, self.cols, ch)
-
- def fill_region(self, rs, cs, re, ce, ch=SPACE):
-
- rs = constrain(rs, 1, self.rows)
- re = constrain(re, 1, self.rows)
- cs = constrain(cs, 1, self.cols)
- ce = constrain(ce, 1, self.cols)
- if rs > re:
- rs, re = re, rs
- if cs > ce:
- cs, ce = ce, cs
- for r in range(rs, re + 1):
- for c in range(cs, ce + 1):
- self.put_abs(r, c, ch)
-
- def cr(self):
- """This moves the cursor to the beginning (col 1) of the current row.
- """
-
- self.cursor_home(self.cur_r, 1)
-
- def lf(self):
- """This moves the cursor down with scrolling.
- """
-
- old_r = self.cur_r
- self.cursor_down()
- if old_r == self.cur_r:
- self.scroll_up()
- self.erase_line()
-
- def crlf(self):
- """This advances the cursor with CRLF properties.
- The cursor will line wrap and the screen may scroll.
- """
-
- self.cr()
- self.lf()
-
- def newline(self):
- """This is an alias for crlf().
- """
-
- self.crlf()
-
- def put_abs(self, r, c, ch):
- """Screen array starts at 1 index."""
-
- r = constrain(r, 1, self.rows)
- c = constrain(c, 1, self.cols)
- ch = str(ch)[0]
- self.w[r - 1][c - 1] = ch
-
- def put(self, ch):
- """This puts a characters at the current cursor position.
- """
-
- self.put_abs(self.cur_r, self.cur_c, ch)
-
- def insert_abs(self, r, c, ch):
- """This inserts a character at (r,c). Everything under
- and to the right is shifted right one character.
- The last character of the line is lost.
- """
-
- r = constrain(r, 1, self.rows)
- c = constrain(c, 1, self.cols)
- for ci in range(self.cols, c, -1):
- self.put_abs(r, ci, self.get_abs(r, ci - 1))
- self.put_abs(r, c, ch)
-
- def insert(self, ch):
-
- self.insert_abs(self.cur_r, self.cur_c, ch)
-
- def get_abs(self, r, c):
-
- r = constrain(r, 1, self.rows)
- c = constrain(c, 1, self.cols)
- return self.w[r - 1][c - 1]
-
- def get(self):
-
- self.get_abs(self.cur_r, self.cur_c)
-
- def get_region(self, rs, cs, re, ce):
- """This returns a list of lines representing the region.
- """
-
- rs = constrain(rs, 1, self.rows)
- re = constrain(re, 1, self.rows)
- cs = constrain(cs, 1, self.cols)
- ce = constrain(ce, 1, self.cols)
- if rs > re:
- rs, re = re, rs
- if cs > ce:
- cs, ce = ce, cs
- sc = []
- for r in range(rs, re + 1):
- line = ''
- for c in range(cs, ce + 1):
- ch = self.get_abs(r, c)
- line = line + ch
- sc.append(line)
- return sc
-
- def cursor_constrain(self):
- """This keeps the cursor within the screen area.
- """
-
- self.cur_r = constrain(self.cur_r, 1, self.rows)
- self.cur_c = constrain(self.cur_c, 1, self.cols)
-
- def cursor_home(self, r=1, c=1): # [{ROW};{COLUMN}H
-
- self.cur_r = r
- self.cur_c = c
- self.cursor_constrain()
-
- def cursor_back(self, count=1): # [{COUNT}D (not confused with down)
-
- self.cur_c = self.cur_c - count
- self.cursor_constrain()
-
- def cursor_down(self, count=1): # [{COUNT}B (not confused with back)
-
- self.cur_r = self.cur_r + count
- self.cursor_constrain()
-
- def cursor_forward(self, count=1): # [{COUNT}C
-
- self.cur_c = self.cur_c + count
- self.cursor_constrain()
-
- def cursor_up(self, count=1): # [{COUNT}A
-
- self.cur_r = self.cur_r - count
- self.cursor_constrain()
-
- def cursor_up_reverse(self): # M (called RI -- Reverse Index)
-
- old_r = self.cur_r
- self.cursor_up()
- if old_r == self.cur_r:
- self.scroll_up()
-
- def cursor_force_position(self, r, c): # [{ROW};{COLUMN}f
- """Identical to Cursor Home."""
-
- self.cursor_home(r, c)
-
- def cursor_save(self): # [s
- """Save current cursor position."""
-
- self.cursor_save_attrs()
-
- def cursor_unsave(self): # [u
- """Restores cursor position after a Save Cursor."""
-
- self.cursor_restore_attrs()
-
- def cursor_save_attrs(self): # 7
- """Save current cursor position."""
-
- self.cur_saved_r = self.cur_r
- self.cur_saved_c = self.cur_c
-
- def cursor_restore_attrs(self): # 8
- """Restores cursor position after a Save Cursor."""
-
- self.cursor_home(self.cur_saved_r, self.cur_saved_c)
-
- def scroll_constrain(self):
- """This keeps the scroll region within the screen region."""
-
- if self.scroll_row_start <= 0:
- self.scroll_row_start = 1
- if self.scroll_row_end > self.rows:
- self.scroll_row_end = self.rows
-
- def scroll_screen(self): # [r
- """Enable scrolling for entire display."""
-
- self.scroll_row_start = 1
- self.scroll_row_end = self.rows
-
- def scroll_screen_rows(self, rs, re): # [{start};{end}r
- """Enable scrolling from row {start} to row {end}."""
-
- self.scroll_row_start = rs
- self.scroll_row_end = re
- self.scroll_constrain()
-
- def scroll_down(self): # D
- """Scroll display down one line."""
-
- # Screen is indexed from 1, but arrays are indexed from 0.
- s = self.scroll_row_start - 1
- e = self.scroll_row_end - 1
- self.w[s + 1:e + 1] = copy.deepcopy(self.w[s:e])
-
- def scroll_up(self): # M
- """Scroll display up one line."""
-
- # Screen is indexed from 1, but arrays are indexed from 0.
- s = self.scroll_row_start - 1
- e = self.scroll_row_end - 1
- self.w[s:e] = copy.deepcopy(self.w[s + 1:e + 1])
-
- def erase_end_of_line(self): # [0K -or- [K
- """Erases from the current cursor position to the end of the current
- line."""
-
- self.fill_region(self.cur_r, self.cur_c, self.cur_r, self.cols)
-
- def erase_start_of_line(self): # [1K
- """Erases from the current cursor position to the start of the current
- line."""
-
- self.fill_region(self.cur_r, 1, self.cur_r, self.cur_c)
-
- def erase_line(self): # [2K
- """Erases the entire current line."""
-
- self.fill_region(self.cur_r, 1, self.cur_r, self.cols)
-
- def erase_down(self): # [0J -or- [J
- """Erases the screen from the current line down to the bottom of the
- screen."""
-
- self.erase_end_of_line()
- self.fill_region(self.cur_r + 1, 1, self.rows, self.cols)
-
- def erase_up(self): # [1J
- """Erases the screen from the current line up to the top of the
- screen."""
-
- self.erase_start_of_line()
- self.fill_region(self.cur_r - 1, 1, 1, self.cols)
-
- def erase_screen(self): # [2J
- """Erases the screen with the background color."""
-
- self.fill()
-
- def set_tab(self): # H
- """Sets a tab at the current position."""
-
- pass
-
- def clear_tab(self): # [g
- """Clears tab at the current position."""
-
- pass
-
- def clear_all_tabs(self): # [3g
- """Clears all tabs."""
-
- pass
-
-# Insert line Esc [ Pn L
-# Delete line Esc [ Pn M
-# Delete character Esc [ Pn P
-# Scrolling region Esc [ Pn(top);Pn(bot) r
Index: third_party/Python/module/pexpect-2.4/setup.py
===================================================================
--- third_party/Python/module/pexpect-2.4/setup.py
+++ third_party/Python/module/pexpect-2.4/setup.py
@@ -1,36 +0,0 @@
-'''
-$Revision: 485 $
-$Date: 2007-07-12 15:23:15 -0700 (Thu, 12 Jul 2007) $
-'''
-from distutils.core import setup
-setup(name='pexpect',
- version='2.4',
- py_modules=['pexpect', 'pxssh', 'fdpexpect', 'FSM', 'screen', 'ANSI'],
- description='Pexpect is a pure Python Expect. It allows easy control of other applications.',
- author='Noah Spurrier',
- author_email='noah@noah.org',
- url='http://pexpect.sourceforge.net/',
- license='MIT license',
- platforms='UNIX',
- )
-
-# classifiers = [
-# 'Development Status :: 4 - Beta',
-# 'Environment :: Console',
-# 'Environment :: Console (Text Based)',
-# 'Intended Audience :: Developers',
-# 'Intended Audience :: System Administrators',
-# 'Intended Audience :: Quality Engineers',
-# 'License :: OSI Approved :: Python Software Foundation License',
-# 'Operating System :: POSIX',
-# 'Operating System :: MacOS :: MacOS X',
-# 'Programming Language :: Python',
-# 'Topic :: Software Development',
-# 'Topic :: Software Development :: Libraries :: Python Modules',
-# 'Topic :: Software Development :: Quality Assurance',
-# 'Topic :: Software Development :: Testing',
-# 'Topic :: System, System :: Archiving :: Packaging, System :: Installation/Setup',
-# 'Topic :: System :: Shells',
-# 'Topic :: System :: Software Distribution',
-# 'Topic :: Terminals, Utilities',
-# ],
Index: third_party/Python/module/pexpect-4.6/.gitignore
===================================================================
--- third_party/Python/module/pexpect-4.6/.gitignore
+++ third_party/Python/module/pexpect-4.6/.gitignore
@@ -0,0 +1,11 @@
+*.pyc
+doc/_build
+tests/log
+build/
+dist/
+MANIFEST
+*~
+.coverage*
+htmlcov
+*.egg-info/
+.cache/
Index: third_party/Python/module/pexpect-4.6/.travis.yml
===================================================================
--- third_party/Python/module/pexpect-4.6/.travis.yml
+++ third_party/Python/module/pexpect-4.6/.travis.yml
@@ -0,0 +1,31 @@
+language: python
+
+python:
+ - 2.7
+ - 3.3
+ - 3.4
+ - 3.5
+ - 3.6
+ - pypy
+ - nightly
+
+matrix:
+ allow_failures:
+ # PyPy on Travis is currently incompatible with Cryptography.
+ - python: pypy
+
+install:
+ - export PYTHONIOENCODING=UTF8
+ - pip install coveralls pytest-cov ptyprocess
+
+script:
+ - ./tools/display-sighandlers.py
+ - ./tools/display-terminalinfo.py
+ - py.test --cov pexpect --cov-config .coveragerc
+
+after_success:
+ - coverage combine
+ - coveralls
+
+# Use new Travis stack, should be faster
+sudo: false
Index: third_party/Python/module/pexpect-4.6/DEVELOPERS.rst
===================================================================
--- third_party/Python/module/pexpect-4.6/DEVELOPERS.rst
+++ third_party/Python/module/pexpect-4.6/DEVELOPERS.rst
@@ -0,0 +1,12 @@
+To run the tests, use `py.test `_::
+
+ py.test tests
+
+The tests are all located in the tests/ directory. To add a new unit
+test all you have to do is create the file in the tests/ directory with a
+filename in this format::
+
+ test_*.py
+
+New test case classes may wish to inherit from ``PexpectTestCase.PexpectTestCase``
+in the tests directory, which sets up some convenient functionality.
Index: third_party/Python/module/pexpect-4.6/LICENSE
===================================================================
--- third_party/Python/module/pexpect-4.6/LICENSE
+++ third_party/Python/module/pexpect-4.6/LICENSE
@@ -0,0 +1,20 @@
+ISC LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2013-2014, Pexpect development team
+ Copyright (c) 2012, Noah Spurrier
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
Index: third_party/Python/module/pexpect-4.6/MANIFEST.in
===================================================================
--- third_party/Python/module/pexpect-4.6/MANIFEST.in
+++ third_party/Python/module/pexpect-4.6/MANIFEST.in
@@ -0,0 +1,6 @@
+recursive-include doc *
+prune doc/_build
+recursive-include examples *
+include .coveragerc README.rst LICENSE pexpect/bashrc.sh
+recursive-include tests *
+global-exclude __pycache__ *.pyc *~
Index: third_party/Python/module/pexpect-4.6/README.rst
===================================================================
--- third_party/Python/module/pexpect-4.6/README.rst
+++ third_party/Python/module/pexpect-4.6/README.rst
@@ -0,0 +1,55 @@
+.. image:: https://travis-ci.org/pexpect/pexpect.svg?branch=master
+ :target: https://travis-ci.org/pexpect/pexpect
+ :align: right
+ :alt: Build status
+
+Pexpect is a Pure Python Expect-like module
+
+Pexpect makes Python a better tool for controlling other applications.
+
+Pexpect is a pure Python module for spawning child applications; controlling
+them; and responding to expected patterns in their output. Pexpect works like
+Don Libes' Expect. Pexpect allows your script to spawn a child application and
+control it as if a human were typing commands.
+
+Pexpect can be used for automating interactive applications such as ssh, ftp,
+passwd, telnet, etc. It can be used to a automate setup scripts for duplicating
+software package installations on different servers. It can be used for
+automated software testing. Pexpect is in the spirit of Don Libes' Expect, but
+Pexpect is pure Python.
+
+The main features of Pexpect require the pty module in the Python standard
+library, which is only available on Unix-like systems. Some features—waiting
+for patterns from file descriptors or subprocesses—are also available on
+Windows.
+
+If you want to work with the development version of the source code then please
+read the DEVELOPERS.rst document in the root of the source code tree.
+
+Free, open source, and all that good stuff.
+
+You can install Pexpect using pip::
+
+ pip install pexpect
+
+`Docs on ReadTheDocs `_
+
+PEXPECT LICENSE::
+
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2013-2016, Pexpect development team
+ Copyright (c) 2012, Noah Spurrier
+
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+This license is approved by the OSI and FSF as GPL-compatible.
Index: third_party/Python/module/pexpect-4.6/doc/FAQ.rst
===================================================================
--- third_party/Python/module/pexpect-4.6/doc/FAQ.rst
+++ third_party/Python/module/pexpect-4.6/doc/FAQ.rst
@@ -0,0 +1,145 @@
+FAQ
+===
+
+**Q: Where can I get help with pexpect? Is there a mailing list?**
+
+A: You can use the `pexpect tag on Stackoverflow `__
+to ask questions specifically related to Pexpect. For more general Python
+support, there's the python-list_ mailing list, and the `#python`_
+IRC channel. Please refrain from using github for general
+python or systems scripting support.
+
+.. _python-list: https://mail.python.org/mailman/listinfo/python-list
+.. _#python: https://www.python.org/community/irc/
+
+**Q: Why don't shell pipe and redirect (| and >) work when I spawn a command?**
+
+A: Remember that Pexpect does NOT interpret shell meta characters such as
+redirect, pipe, or wild cards (``>``, ``|``, or ``*``). That's done by a shell not
+the command you are spawning. This is a common mistake. If you want to run a
+command and pipe it through another command then you must also start a shell.
+For example::
+
+ child = pexpect.spawn('/bin/bash -c "ls -l | grep LOG > log_list.txt"')
+ child.expect(pexpect.EOF)
+
+The second form of spawn (where you pass a list of arguments) is useful in
+situations where you wish to spawn a command and pass it its own argument list.
+This can make syntax more clear. For example, the following is equivalent to the
+previous example::
+
+ shell_cmd = 'ls -l | grep LOG > log_list.txt'
+ child = pexpect.spawn('/bin/bash', ['-c', shell_cmd])
+ child.expect(pexpect.EOF)
+
+**Q: The `before` and `after` properties sound weird.**
+
+A: This is how the -B and -A options in grep works, so that made it
+easier for me to remember. Whatever makes my life easier is what's best.
+Originally I was going to model Pexpect after Expect, but then I found
+that I didn't actually like the way Expect did some things. It was more
+confusing. The `after` property can be a little confusing at first,
+because it will actually include the matched string. The `after` means
+after the point of match, not after the matched string.
+
+**Q: Why not just use Expect?**
+
+A: I love it. It's great. I has bailed me out of some real jams, but I
+wanted something that would do 90% of what I need from Expect; be 10% of
+the size; and allow me to write my code in Python instead of TCL.
+Pexpect is not nearly as big as Expect, but Pexpect does everything I
+have ever used Expect for.
+
+.. _whynotpipe:
+
+**Q: Why not just use a pipe (popen())?**
+
+A: A pipe works fine for getting the output to non-interactive programs.
+If you just want to get the output from ls, uname, or ping then this
+works. Pipes do not work very well for interactive programs and pipes
+will almost certainly fail for most applications that ask for passwords
+such as telnet, ftp, or ssh.
+
+There are two reasons for this.
+
+* First an application may bypass stdout and print directly to its
+ controlling TTY. Something like SSH will do this when it asks you for
+ a password. This is why you cannot redirect the password prompt because
+ it does not go through stdout or stderr.
+
+* The second reason is because most applications are built using the C
+ Standard IO Library (anything that uses ``#include ``). One
+ of the features of the stdio library is that it buffers all input and
+ output. Normally output is line buffered when a program is printing to
+ a TTY (your terminal screen). Everytime the program prints a line-feed
+ the currently buffered data will get printed to your screen. The
+ problem comes when you connect a pipe. The stdio library is smart and
+ can tell that it is printing to a pipe instead of a TTY. In that case
+ it switches from line buffer mode to block buffered. In this mode the
+ currently buffered data is flushed when the buffer is full. This
+ causes most interactive programs to deadlock. Block buffering is more
+ efficient when writing to disks and pipes. Take the situation where a
+ program prints a message ``"Enter your user name:\n"`` and then waits
+ for you type type something. In block buffered mode, the stdio library
+ will not put the message into the pipe even though a linefeed is
+ printed. The result is that you never receive the message, yet the
+ child application will sit and wait for you to type a response. Don't
+ confuse the stdio lib's buffer with the pipe's buffer. The pipe buffer
+ is another area that can cause problems. You could flush the input
+ side of a pipe, whereas you have no control over the stdio library buffer.
+
+More information: the Standard IO library has three states for a
+``FILE *``. These are: _IOFBF for block buffered; _IOLBF for line buffered;
+and _IONBF for unbuffered. The STDIO lib will use block buffering when
+talking to a block file descriptor such as a pipe. This is usually not
+helpful for interactive programs. Short of recompiling your program to
+include fflush() everywhere or recompiling a custom stdio library there
+is not much a controlling application can do about this if talking over
+a pipe.
+
+The program may have put data in its output that remains unflushed
+because the output buffer is not full; then the program will go and
+deadlock while waiting for input -- because you never send it any
+because you are still waiting for its output (still stuck in the STDIO's
+output buffer).
+
+The answer is to use a pseudo-tty. A TTY device will force line
+buffering (as opposed to block buffering). Line buffering means that you
+will get each line when the child program sends a line feed. This
+corresponds to the way most interactive programs operate -- send a line
+of output then wait for a line of input.
+
+I put "answer" in quotes because it's ugly solution and because there is
+no POSIX standard for pseudo-TTY devices (even though they have a TTY
+standard...). What would make more sense to me would be to have some way
+to set a mode on a file descriptor so that it will tell the STDIO to be
+line-buffered. I have investigated, and I don't think there is a way to
+set the buffered state of a child process. The STDIO Library does not
+maintain any external state in the kernel or whatnot, so I don't think
+there is any way for you to alter it. I'm not quite sure how this
+line-buffered/block-buffered state change happens internally in the
+STDIO library. I think the STDIO lib looks at the file descriptor and
+decides to change behavior based on whether it's a TTY or a block file
+(see isatty()).
+
+I hope that this qualifies as helpful. Don't use a pipe to control
+another application.
+
+**Q: Can I do screen scraping with this thing?**
+
+A: That depends. If your application just does line-oriented output then
+this is easy. If a program emits many terminal sequences, from video
+attributes to screen addressing, such as programs using curses, then
+it may become very difficult to ascertain what text is displayed on a screen.
+
+We suggest using the `pyte `_ library to
+screen-scrape. The module :mod:`pexpect.ANSI` released with previous versions
+of pexpect is now marked deprecated and may be removed in the future.
+
+**Q: I get strange behavior with pexect and gevent**
+
+A: Pexpect uses fork(2), exec(2), select(2), waitpid(2), and implements its
+own selector in expect family of calls. pexpect has been known to misbehave
+when paired with gevent. A solution might be to isolate your pexpect
+dependent code from any frameworks that manipulate event selection behavior
+by running it in an another process entirely.
Index: third_party/Python/module/pexpect-4.6/doc/Makefile
===================================================================
--- third_party/Python/module/pexpect-4.6/doc/Makefile
+++ third_party/Python/module/pexpect-4.6/doc/Makefile
@@ -0,0 +1,153 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+PAPER =
+BUILDDIR = _build
+
+# Internal variables.
+PAPEROPT_a4 = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+# the i18n builder cannot share the environment and doctrees with the others
+I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
+
+help:
+ @echo "Please use \`make ' where is one of"
+ @echo " html to make standalone HTML files"
+ @echo " dirhtml to make HTML files named index.html in directories"
+ @echo " singlehtml to make a single large HTML file"
+ @echo " pickle to make pickle files"
+ @echo " json to make JSON files"
+ @echo " htmlhelp to make HTML files and a HTML help project"
+ @echo " qthelp to make HTML files and a qthelp project"
+ @echo " devhelp to make HTML files and a Devhelp project"
+ @echo " epub to make an epub"
+ @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+ @echo " latexpdf to make LaTeX files and run them through pdflatex"
+ @echo " text to make text files"
+ @echo " man to make manual pages"
+ @echo " texinfo to make Texinfo files"
+ @echo " info to make Texinfo files and run them through makeinfo"
+ @echo " gettext to make PO message catalogs"
+ @echo " changes to make an overview of all changed/added/deprecated items"
+ @echo " linkcheck to check all external links for integrity"
+ @echo " doctest to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+ -rm -rf $(BUILDDIR)/*
+
+html:
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+ $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml:
+ $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+ @echo
+ @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+pickle:
+ $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+ @echo
+ @echo "Build finished; now you can process the pickle files."
+
+json:
+ $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+ @echo
+ @echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+ $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+ @echo
+ @echo "Build finished; now you can run HTML Help Workshop with the" \
+ ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+ $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+ @echo
+ @echo "Build finished; now you can run "qcollectiongenerator" with the" \
+ ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+ @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Pexpect.qhcp"
+ @echo "To view the help file:"
+ @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Pexpect.qhc"
+
+devhelp:
+ $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+ @echo
+ @echo "Build finished."
+ @echo "To view the help file:"
+ @echo "# mkdir -p $$HOME/.local/share/devhelp/Pexpect"
+ @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Pexpect"
+ @echo "# devhelp"
+
+epub:
+ $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+ @echo
+ @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+latex:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo
+ @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+ @echo "Run \`make' in that directory to run these through (pdf)latex" \
+ "(use \`make latexpdf' here to do that automatically)."
+
+latexpdf:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through pdflatex..."
+ $(MAKE) -C $(BUILDDIR)/latex all-pdf
+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+text:
+ $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+ @echo
+ @echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+man:
+ $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+ @echo
+ @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+texinfo:
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+ @echo
+ @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
+ @echo "Run \`make' in that directory to run these through makeinfo" \
+ "(use \`make info' here to do that automatically)."
+
+info:
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+ @echo "Running Texinfo files through makeinfo..."
+ make -C $(BUILDDIR)/texinfo info
+ @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
+
+gettext:
+ $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
+ @echo
+ @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
+
+changes:
+ $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+ @echo
+ @echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+ $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+ @echo
+ @echo "Link check complete; look for any errors in the above output " \
+ "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+ $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+ @echo "Testing of doctests in the sources finished, look at the " \
+ "results in $(BUILDDIR)/doctest/output.txt."
Index: third_party/Python/module/pexpect-4.6/doc/api/fdpexpect.rst
===================================================================
--- third_party/Python/module/pexpect-4.6/doc/api/fdpexpect.rst
+++ third_party/Python/module/pexpect-4.6/doc/api/fdpexpect.rst
@@ -0,0 +1,20 @@
+fdpexpect - use pexpect with a file descriptor
+==============================================
+
+.. automodule:: pexpect.fdpexpect
+
+fdspawn class
+-------------
+
+.. autoclass:: fdspawn
+ :show-inheritance:
+
+ .. automethod:: __init__
+ .. automethod:: isalive
+ .. automethod:: close
+
+ .. method:: expect
+ expect_exact
+ expect_list
+
+ As :class:`pexpect.spawn`.
Index: third_party/Python/module/pexpect-4.6/doc/api/index.rst
===================================================================
--- third_party/Python/module/pexpect-4.6/doc/api/index.rst
+++ third_party/Python/module/pexpect-4.6/doc/api/index.rst
@@ -0,0 +1,18 @@
+API documentation
+=================
+
+.. toctree::
+ :maxdepth: 2
+
+ pexpect
+ fdpexpect
+ popen_spawn
+ replwrap
+ pxssh
+
+The modules ``pexpect.screen`` and ``pexpect.ANSI`` have been deprecated in
+Pexpect version 4. They were separate from the main use cases for Pexpect, and
+there are better maintained Python terminal emulator packages, such as
+`pyte `__.
+These modules are still present for now, but we don't advise using them in new
+code.
Index: third_party/Python/module/pexpect-4.6/doc/api/pexpect.rst
===================================================================
--- third_party/Python/module/pexpect-4.6/doc/api/pexpect.rst
+++ third_party/Python/module/pexpect-4.6/doc/api/pexpect.rst
@@ -0,0 +1,115 @@
+Core pexpect components
+=======================
+
+.. automodule:: pexpect
+
+spawn class
+-----------
+
+.. autoclass:: spawn
+
+ .. automethod:: __init__
+ .. automethod:: expect
+ .. automethod:: expect_exact
+ .. automethod:: expect_list
+ .. automethod:: compile_pattern_list
+ .. automethod:: send
+ .. automethod:: sendline
+ .. automethod:: write
+ .. automethod:: writelines
+ .. automethod:: sendcontrol
+ .. automethod:: sendeof
+ .. automethod:: sendintr
+ .. automethod:: read
+ .. automethod:: readline
+ .. automethod:: read_nonblocking
+ .. automethod:: eof
+ .. automethod:: interact
+
+ .. attribute:: logfile
+ logfile_read
+ logfile_send
+
+ Set these to a Python file object (or :data:`sys.stdout`) to log all
+ communication, data read from the child process, or data sent to the child
+ process.
+
+ .. note::
+
+ With :class:`spawn` in bytes mode, the log files should be open for
+ writing binary data. In unicode mode, they should
+ be open for writing unicode text. See :ref:`unicode`.
+
+Controlling the child process
+`````````````````````````````
+
+.. class:: spawn
+
+ .. automethod:: kill
+ .. automethod:: terminate
+ .. automethod:: isalive
+ .. automethod:: wait
+ .. automethod:: close
+ .. automethod:: getwinsize
+ .. automethod:: setwinsize
+ .. automethod:: getecho
+ .. automethod:: setecho
+ .. automethod:: waitnoecho
+
+ .. attribute:: pid
+
+ The process ID of the child process.
+
+ .. attribute:: child_fd
+
+ The file descriptor used to communicate with the child process.
+
+.. _unicode:
+
+Handling unicode
+````````````````
+
+By default, :class:`spawn` is a bytes interface: its read methods return bytes,
+and its write/send and expect methods expect bytes. If you pass the *encoding*
+parameter to the constructor, it will instead act as a unicode interface:
+strings you send will be encoded using that encoding, and bytes received will
+be decoded before returning them to you. In this mode, patterns for
+:meth:`~spawn.expect` and :meth:`~spawn.expect_exact` should also be unicode.
+
+.. versionchanged:: 4.0
+
+ :class:`spawn` provides both the bytes and unicode interfaces. In Pexpect
+ 3.x, the unicode interface was provided by a separate ``spawnu`` class.
+
+For backwards compatibility, some Unicode is allowed in bytes mode: the
+send methods will encode arbitrary unicode as UTF-8 before sending it to the
+child process, and its expect methods can accept ascii-only unicode strings.
+
+.. note::
+
+ Unicode handling with pexpect works the same way on Python 2 and 3, despite
+ the difference in names. I.e.:
+
+ - Bytes mode works with ``str`` on Python 2, and :class:`bytes` on Python 3,
+ - Unicode mode works with ``unicode`` on Python 2, and :class:`str` on Python 3.
+
+run function
+------------
+
+.. autofunction:: run
+
+Exceptions
+----------
+
+.. autoclass:: EOF
+
+.. autoclass:: TIMEOUT
+
+.. autoclass:: ExceptionPexpect
+
+Utility functions
+-----------------
+
+.. autofunction:: which
+
+.. autofunction:: split_command_line
Index: third_party/Python/module/pexpect-4.6/doc/api/popen_spawn.rst
===================================================================
--- third_party/Python/module/pexpect-4.6/doc/api/popen_spawn.rst
+++ third_party/Python/module/pexpect-4.6/doc/api/popen_spawn.rst
@@ -0,0 +1,24 @@
+popen_spawn - use pexpect with a piped subprocess
+=================================================
+
+.. automodule:: pexpect.popen_spawn
+
+PopenSpawn class
+----------------
+
+.. autoclass:: PopenSpawn
+
+ .. automethod:: __init__
+ .. automethod:: send
+ .. automethod:: sendline
+ .. automethod:: write
+ .. automethod:: writelines
+ .. automethod:: kill
+ .. automethod:: sendeof
+ .. automethod:: wait
+
+ .. method:: expect
+ expect_exact
+ expect_list
+
+ As :class:`pexpect.spawn`.
Index: third_party/Python/module/pexpect-4.6/doc/api/pxssh.rst
===================================================================
--- third_party/Python/module/pexpect-4.6/doc/api/pxssh.rst
+++ third_party/Python/module/pexpect-4.6/doc/api/pxssh.rst
@@ -0,0 +1,34 @@
+pxssh - control an SSH session
+==============================
+
+.. automodule:: pexpect.pxssh
+
+.. autoclass:: ExceptionPxssh
+
+pxssh class
+-----------
+
+.. autoclass:: pxssh
+
+ .. automethod:: __init__
+
+ .. attribute:: PROMPT
+
+ The regex pattern to search for to find the prompt. If you call :meth:`login`
+ with ``auto_prompt_reset=False``, you must set this attribute manually.
+
+ .. attribute:: force_password
+
+ If this is set to True, public key authentication is disabled, forcing the
+ server to ask for a password. Note that the sysadmin can disable password
+ logins, in which case this won't work.
+
+ .. attribute:: options
+
+ The dictionary of user specified SSH options, eg, ``options = dict(StrictHostKeyChecking="no", UserKnownHostsFile="/dev/null")``
+
+ .. automethod:: login
+ .. automethod:: logout
+ .. automethod:: prompt
+ .. automethod:: sync_original_prompt
+ .. automethod:: set_unique_prompt
Index: third_party/Python/module/pexpect-4.6/doc/api/replwrap.rst
===================================================================
--- third_party/Python/module/pexpect-4.6/doc/api/replwrap.rst
+++ third_party/Python/module/pexpect-4.6/doc/api/replwrap.rst
@@ -0,0 +1,26 @@
+replwrap - Control read-eval-print-loops
+========================================
+
+.. automodule:: pexpect.replwrap
+
+.. versionadded:: 3.3
+
+.. autoclass:: REPLWrapper
+
+ .. automethod:: run_command
+
+.. data:: PEXPECT_PROMPT
+
+ A string that can be used as a prompt, and is unlikely to be found in output.
+
+Using the objects above, it is easy to wrap a REPL. For instance, to use a
+Python shell::
+
+ py = REPLWrapper("python", ">>> ", "import sys; sys.ps1={!r}; sys.ps2={!r}")
+ py.run_command("4+7")
+
+Convenience functions are provided for Python and bash shells:
+
+.. autofunction:: python
+
+.. autofunction:: bash
Index: third_party/Python/module/pexpect-4.6/doc/clean.css
===================================================================
--- third_party/Python/module/pexpect-4.6/doc/clean.css
+++ third_party/Python/module/pexpect-4.6/doc/clean.css
@@ -0,0 +1,103 @@
+
+body {
+ margin:0px;
+ padding:0px;
+ font-family:verdana, arial, helvetica, sans-serif;
+ color:#333;
+ background-color:white;
+ }
+pre {
+ background: #eeeeee;
+ border: 1px solid #888888;
+ color: black;
+ padding: 1em;
+ white-space: pre;
+}
+h1 {
+ margin:5px 0px 5px 0px;
+ padding:0px;
+ font-size:20px;
+ line-height:28px;
+ font-weight:900;
+ color:#44f;
+ }
+h2 {
+ margin:5px 0px 5px 0px;
+ padding:0px;
+ font-size:17px;
+ line-height:28px;
+ font-weight:900;
+ color:#226;
+ }
+h3 {
+ margin:5px 0px 5px 0px;
+ padding:0px;
+ font-size:15px;
+ line-height:28px;
+ font-weight:900;
+ }
+p
+{
+ margin:0px 0px 16px 0px;
+ font:11px/20px verdana, arial, helvetica, sans-serif;
+ padding:0px;
+}
+table
+{
+ font-size: 10pt;
+ color: #000000;
+}
+td{border:1px solid #999;}
+
+table.pymenu {color: #000000; background-color: #99ccff}
+th.pymenu {color: #ffffff; background-color: #003366}
+
+.code
+{
+ font-family: "Lucida Console", monospace; font-weight: bold;
+ color: #007700; background-color: #eeeeee
+}
+
+#Content>p {margin:0px;}
+#Content>p+p {text-indent:30px;}
+
+a {
+ text-decoration:none;
+ font-weight:600;
+ font-family:verdana, arial, helvetica, sans-serif;
+ color: #900;
+}
+//a:link {color:#09c;}
+//a x:visited {color:#07a;}
+a:hover {background-color:#ee0;}
+
+#Header {
+ margin:10px 0px 10px 0px;
+ padding:10px 0px 10px 20px;
+ /* For IE5/Win's benefit height = [correct height] + [top padding] + [top and bottom border widths] */
+ height:33px; /* 14px + 17px + 2px = 33px */
+ border-style:solid;
+ border-color:black;
+ border-width:1px 0px; /* top and bottom borders: 1px; left and right borders: 0px */
+ line-height:33px;
+ background-color:#eee;
+ height:66px; /* the correct height */
+ }
+
+#Content {
+ margin:0px 210px 50px 10px;
+ padding:10px;
+ }
+
+#Menu {
+ position:absolute;
+ top:100px;
+ right:20px;
+ width:172px;
+ padding:10px;
+ background-color:#eee;
+ border:1px solid #999; // dashed #999;
+ line-height:17px;
+ width:150px;
+ font-size:11px;
+ }
Index: third_party/Python/module/pexpect-4.6/doc/commonissues.rst
===================================================================
--- third_party/Python/module/pexpect-4.6/doc/commonissues.rst
+++ third_party/Python/module/pexpect-4.6/doc/commonissues.rst
@@ -0,0 +1,101 @@
+Common problems
+===============
+
+Threads
+-------
+
+On Linux (RH 8) you cannot spawn a child from a different thread and pass the
+handle back to a worker thread. The child is successfully spawned but you can't
+interact with it. The only way to make it work is to spawn and interact with the
+child all in the same thread. [Adam Kerrison]
+
+Timing issue with send() and sendline()
+---------------------------------------
+
+This problem has been addressed and should not affect most users.
+
+It is sometimes possible to read an echo of the string sent with
+:meth:`~pexpect.spawn.send` and :meth:`~pexpect.spawn.sendline`. If you call
+:meth:`~pexpect.spawn.send` and then immediately call :meth:`~pexpect.spawn.readline`,
+you may get part of your output echoed back. You may read back what you just
+wrote even if the child application does not explicitly echo it. Timing is
+critical. This could be a security issue when talking to an application that
+asks for a password; otherwise, this does not seem like a big deal. But why do
+TTYs do this?
+
+People usually report this when they are trying to control SSH or some other
+login. For example, if your code looks something like this::
+
+ child.expect ('[pP]assword:')
+ child.sendline (my_password)
+
+
+1. SSH prints "password:" prompt to the user.
+2. SSH turns off echo on the TTY device.
+3. SSH waits for user to enter a password.
+
+When scripting with Pexpect what can happen is that Pexpect will respond to the
+"password:" prompt before SSH has had time to turn off TTY echo. In other words,
+Pexpect sends the password between steps 1. and 2., so the password gets echoed
+back to the TTY. I would call this an SSH bug.
+
+Pexpect now automatically adds a short delay before sending data to a child
+process. This more closely mimics what happens in the usual human-to-app
+interaction. The delay can be tuned with the ``delaybeforesend`` attribute of the
+spawn class. In general, this fixes the problem for everyone and so this should
+not be an issue for most users. For some applications you might with to turn it
+off::
+
+ child = pexpect.spawn ("ssh user@example.com")
+ child.delaybeforesend = None
+
+Truncated output just before child exits
+----------------------------------------
+
+So far I have seen this only on older versions of Apple's MacOS X. If the child
+application quits it may not flush its output buffer. This means that your
+Pexpect application will receive an EOF even though it should have received a
+little more data before the child died. This is not generally a problem when
+talking to interactive child applications. One example where it is a problem is
+when trying to read output from a program like *ls*. You may receive most of the
+directory listing, but the last few lines will get lost before you receive an EOF.
+The reason for this is that *ls* runs; completes its task; and then exits. The
+buffer is not flushed before exit so the last few lines are lost. The following
+example demonstrates the problem::
+
+ child = pexpect.spawn('ls -l')
+ child.expect(pexpect.EOF)
+ print child.before
+
+Controlling SSH on Solaris
+--------------------------
+
+Pexpect does not yet work perfectly on Solaris. One common problem is that SSH
+sometimes will not allow TTY password authentication. For example, you may
+expect SSH to ask you for a password using code like this::
+
+ child = pexpect.spawn('ssh user@example.com')
+ child.expect('password')
+ child.sendline('mypassword')
+
+You may see the following error come back from a spawned child SSH::
+
+ Permission denied (publickey,keyboard-interactive).
+
+This means that SSH thinks it can't access the TTY to ask you for your password.
+The only solution I have found is to use public key authentication with SSH.
+This bypasses the need for a password. I'm not happy with this solution. The
+problem is due to poor support for Solaris Pseudo TTYs in the Python Standard
+Library.
+
+child does not receive full input, emits BEL
+--------------------------------------------
+
+You may notice when running for example cat(1) or base64(1), when sending a
+very long input line, that it is not fully received, and the BEL ('\a') may
+be found in output.
+
+By default the child terminal matches the parent, which is often in "canonical
+mode processing". You may wish to disable this mode. The exact limit of a line
+varies by operating system, and details of disabling canonical mode may be
+found in the docstring of :meth:`~pexpect.spawn.send`.
Index: third_party/Python/module/pexpect-4.6/doc/conf.py
===================================================================
--- third_party/Python/module/pexpect-4.6/doc/conf.py
+++ third_party/Python/module/pexpect-4.6/doc/conf.py
@@ -0,0 +1,250 @@
+# -*- coding: utf-8 -*-
+#
+# Pexpect documentation build configuration file, created by
+# sphinx-quickstart on Tue Sep 17 11:05:11 2013.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+sys.path.insert(0, os.path.abspath('sphinxext'))
+
+# -- General configuration -----------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx',
+ 'sphinx.ext.viewcode', 'github', # for easy GitHub links
+ ]
+
+github_project_url = "https://github.com/pexpect/pexpect"
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'Pexpect'
+copyright = u'2013, Noah Spurrier and contributors'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = '4.6'
+# The full version, including alpha/beta/rc tags.
+release = version
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['_build']
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+html_theme = 'default'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further. For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents. If None, it defaults to
+# " v documentation".
+#html_title = None
+
+# A shorter title for the navigation bar. Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a tag referring to it. The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'Pexpectdoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+latex_elements = {
+# The paper size ('letterpaper' or 'a4paper').
+#'papersize': 'letterpaper',
+
+# The font size ('10pt', '11pt' or '12pt').
+#'pointsize': '10pt',
+
+# Additional stuff for the LaTeX preamble.
+#'preamble': '',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+ ('index', 'Pexpect.tex', u'Pexpect Documentation',
+ u'Noah Spurrier and contributors', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output --------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+ ('index', 'pexpect', u'Pexpect Documentation',
+ [u'Noah Spurrier and contributors'], 1)
+]
+
+# If true, show URL addresses after external links.
+#man_show_urls = False
+
+
+# -- Options for Texinfo output ------------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+# dir menu entry, description, category)
+texinfo_documents = [
+ ('index', 'Pexpect', u'Pexpect Documentation',
+ u'Noah Spurrier and contributors', 'Pexpect', 'One line description of project.',
+ 'Miscellaneous'),
+]
+
+# Documents to append as an appendix to all manuals.
+#texinfo_appendices = []
+
+# If false, no module index is generated.
+#texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#texinfo_show_urls = 'footnote'
+
+
+# Example configuration for intersphinx: refer to the Python standard library.
+intersphinx_mapping = {'http://docs.python.org/3/': None}
Index: third_party/Python/module/pexpect-4.6/doc/examples.rst
===================================================================
--- third_party/Python/module/pexpect-4.6/doc/examples.rst
+++ third_party/Python/module/pexpect-4.6/doc/examples.rst
@@ -0,0 +1,63 @@
+Examples
+========
+
+Under the distribution tarball directory you should find an "examples" directory.
+This is the best way to learn to use Pexpect. See the descriptions of Pexpect
+Examples.
+
+`topip.py `_
+ This runs `netstat` on a local or remote server. It calculates some simple
+ statistical information on the number of external inet connections. This can
+ be used to detect if one IP address is taking up an excessive number of
+ connections. It can also send an email alert if a given IP address exceeds a
+ threshold between runs of the script. This script can be used as a drop-in
+ Munin plugin or it can be used stand-alone from cron. I used this on a busy
+ web server that would sometimes get hit with denial of service attacks. This
+ made it easy to see if a script was opening many multiple connections. A
+ typical browser would open fewer than 10 connections at once. A script might
+ open over 100 simultaneous connections.
+
+`hive.py `_
+ This script creates SSH connections to a list of hosts that you provide.
+ Then you are given a command line prompt. Each shell command that you
+ enter is sent to all the hosts. The response from each host is collected
+ and printed. For example, you could connect to a dozen different
+ machines and reboot them all at once.
+
+`script.py `_
+ This implements a command similar to the classic BSD "script" command.
+ This will start a subshell and log all input and output to a file.
+ This demonstrates the :meth:`~pexpect.spawn.interact` method of Pexpect.
+
+`ftp.py `_
+ This demonstrates an FTP "bookmark". This connects to an ftp site;
+ does a few ftp tasks; and then gives the user interactive control over
+ the session. In this case the "bookmark" is to a directory on the
+ OpenBSD ftp server. It puts you in the i386 packages directory. You
+ can easily modify this for other sites. This demonstrates the
+ :meth:`~pexpect.spawn.interact` method of Pexpect.
+
+`monitor.py `_
+ This runs a sequence of commands on a remote host using SSH. It runs a
+ simple system checks such as uptime and free to monitor the state of
+ the remote host.
+
+`passmass.py `_
+ This will login to each given server and change the password of the
+ given user. This demonstrates scripting logins and passwords.
+
+`python.py `_
+ This starts the python interpreter and prints the greeting message
+ backwards. It then gives the user iteractive control of Python. It's
+ pretty useless!
+
+`ssh_tunnel.py `_
+ This starts an SSH tunnel to a remote machine. It monitors the
+ connection and restarts the tunnel if it goes down.
+
+`uptime.py `_
+ This will run the uptime command and parse the output into variables.
+ This demonstrates using a single regular expression to match the
+ output of a command and capturing different variable in match groups.
+ The grouping regular expression handles a wide variety of different
+ uptime formats.
Index: third_party/Python/module/pexpect-4.6/doc/history.rst
===================================================================
--- third_party/Python/module/pexpect-4.6/doc/history.rst
+++ third_party/Python/module/pexpect-4.6/doc/history.rst
@@ -0,0 +1,338 @@
+History
+=======
+
+Releases
+--------
+
+Version 4.6
+```````````
+
+* The :meth:`.pxssh.login` method now supports an ``ssh_config`` parameter,
+ which can be used to specify a file path to an SSH config file
+ (:ghpull:`490`).
+* Improved compatability for the ``crlf`` parameter of :class:`~.PopenSpawn`
+ (:ghpull:`493`)
+* Fixed an issue in read timeout handling when using :class:`~.spawn` and
+ :class:`~.fdspawn` with the ``use_poll`` parameter (:ghpull:`492`).
+
+Version 4.5
+```````````
+
+* :class:`~.spawn` and :class:`~.fdspawn` now have a ``use_poll`` parameter.
+ If this is True, they will use :func:`select.poll` instead of :func:`select.select`.
+ ``poll()`` allows file descriptors above 1024, but it must be explicitly
+ enabled due to compatibility concerns (:ghpull:`474`).
+* The :meth:`.pxssh.login` method has several new and changed options:
+
+ * The option ``password_regex`` allows changing
+ the password prompt regex, for servers that include ``password:`` in a banner
+ before reaching a prompt (:ghpull:`468`).
+ * :meth:`~.pxssh.login` now allows for setting up SSH tunnels to be requested once
+ logged in to the remote server. This option is ``ssh_tunnels`` (:ghpull:`473`).
+ The structure should be like this::
+
+ {
+ 'local': ['2424:localhost:22'], # Local SSH tunnels
+ 'remote': ['2525:localhost:22'], # Remote SSH tunnels
+ 'dynamic': [8888], # Dynamic/SOCKS tunnels
+ }
+
+ * The option ``spawn_local_ssh=False`` allows subsequent logins from the
+ remote session and treats the session as if it was local (:ghpull:`472`).
+ * Setting ``sync_original_prompt=False`` will prevent changing the prompt to
+ something unique, in case the remote server is sensitive to new lines at login
+ (:ghpull:`468`).
+ * If ``ssh_key=True`` is passed, the SSH client forces forwarding the authentication
+ agent to the remote server instead of providing a key (:ghpull:`473`).
+
+Version 4.4
+```````````
+
+* :class:`~.PopenSpawn` now has a ``preexec_fn`` parameter, like :class:`~.spawn`
+ and :class:`subprocess.Popen`, for a function to be called in the child
+ process before executing the new command. Like in ``Popen``, this works only
+ in POSIX, and can cause issues if your application also uses threads
+ (:ghpull:`460`).
+* Significant performance improvements when processing large amounts of data
+ (:ghpull:`464`).
+* Ensure that ``spawn.closed`` gets set by :meth:`~.spawn.close`, and improve
+ an example for passing ``SIGWINCH`` through to a child process (:ghpull:`466`).
+
+Version 4.3.1
+`````````````
+
+* When launching bash for :mod:`pexpect.replwrap`, load the system ``bashrc``
+ from a couple of different common locations (:ghpull:`457`), and then unset
+ the ``PROMPT_COMMAND`` environment variable, which can interfere with the
+ prompt we're expecting (:ghpull:`459`).
+
+Version 4.3
+```````````
+
+* The ``async=`` parameter to integrate with asyncio has become ``async_=``
+ (:ghpull:`431`), as *async* is becoming a Python keyword from Python 3.6.
+ Pexpect will still recognise ``async`` as an alternative spelling.
+* Similarly, the module ``pexpect.async`` became ``pexpect._async``
+ (:ghpull:`450`). This module is not part of the public API.
+* Fix problems with asyncio objects closing file descriptors during garbage
+ collection (:ghissue:`347`, :ghpull:`376`).
+* Set the ``.pid`` attribute of a :class:`~.PopenSpawn` object (:ghpull:`417`).
+* Fix passing Windows paths to :class:`~.PopenSpawn` (:ghpull:`446`).
+* :class:`~.PopenSpawn` on Windows can pass string commands through to ``Popen``
+ without splitting them into a list (:ghpull:`447`).
+* Stop ``shlex`` trying to read from stdin when :class:`~.PopenSpawn` is
+ passed ``cmd=None`` (:ghissue:`433`, :ghpull:`434`).
+* Ensure that an error closing a Pexpect spawn object raises a Pexpect error,
+ rather than a Ptyprocess error (:ghissue:`383`, :ghpull:`386`).
+* Cleaned up invalid backslash escape sequences in strings (:ghpull:`430`,
+ :ghpull:`445`).
+* The pattern for a password prompt in :mod:`pexpect.pxssh` changed from
+ ``password`` to ``password:`` (:ghpull:`452`).
+* Correct docstring for using unicode with spawn (:ghpull:`395`).
+* Various other improvements to documentation.
+
+Version 4.2.1
+`````````````
+
+* Fix to allow running ``env`` in replwrap-ed bash.
+* Raise more informative exception from pxssh if it fails to connect.
+* Change ``passmass`` example to not log passwords entered.
+
+Version 4.2
+```````````
+
+* Change: When an ``env`` parameter is specified to the :class:`~.spawn` or
+ :class:`~.run` family of calls containing a value for ``PATH``, its value is
+ used to discover the target executable from a relative path, rather than the
+ current process's environment ``PATH``. This mirrors the behavior of
+ :func:`subprocess.Popen` in the standard library (:ghissue:`348`).
+
+* Regression: Re-introduce capability for :meth:`read_nonblocking` in class
+ :class:`fdspawn` as previously supported in version 3.3 (:ghissue:`359`).
+
+Version 4.0
+```````````
+
+* Integration with :mod:`asyncio`: passing ``async=True`` to :meth:`~.spawn.expect`,
+ :meth:`~.spawn.expect_exact` or :meth:`~.spawn.expect_list` will make them return a
+ coroutine. You can get the result using ``yield from``, or wrap it in an
+ :class:`asyncio.Task`. This allows the event loop to do other things while
+ waiting for output that matches a pattern.
+* Experimental support for Windows (with some caveats)—see :ref:`windows`.
+* Enhancement: allow method as callbacks of argument ``events`` for
+ :func:`pexpect.run` (:ghissue:`176`).
+* It is now possible to call :meth:`~.spawn.wait` multiple times, or after a process
+ is already determined to be terminated without raising an exception
+ (:ghpull:`211`).
+* New :class:`pexpect.spawn` keyword argument, ``dimensions=(rows, columns)``
+ allows setting terminal screen dimensions before launching a program
+ (:ghissue:`122`).
+* Fix regression that prevented executable, but unreadable files from
+ being found when not specified by absolute path -- such as
+ /usr/bin/sudo (:ghissue:`104`).
+* Fixed regression when executing pexpect with some prior releases of
+ the multiprocessing module where stdin has been closed (:ghissue:`86`).
+
+Backwards incompatible changes
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* Deprecated ``pexpect.screen`` and ``pexpect.ANSI``. Please use other packages
+ such as `pyte `__ to emulate a terminal.
+* Removed the independent top-level modules (``pxssh fdpexpect FSM screen ANSI``)
+ which were installed alongside Pexpect. These were moved into the Pexpect
+ package in 3.0, but the old names were left as aliases.
+* Child processes created by Pexpect no longer ignore SIGHUP by default: the
+ ``ignore_sighup`` parameter of :class:`pexpect.spawn` defaults to False. To
+ get the old behaviour, pass ``ignore_sighup=True``.
+
+Version 3.3
+```````````
+
+* Added a mechanism to wrap REPLs, or shells, in an object which can conveniently
+ be used to send commands and wait for the output (:mod:`pexpect.replwrap`).
+* Fixed issue where pexpect would attempt to execute a directory because
+ it has the 'execute' bit set (:ghissue:`37`).
+* Removed the ``pexpect.psh`` module. This was never documented, and we found
+ no evidence that people use it. The new :mod:`pexpect.replwrap` module
+ provides a more flexible alternative.
+* Fixed ``TypeError: got ('\r\n') as pattern`` in :meth:`spawnu.readline`
+ method (:ghissue:`67`).
+* Fixed issue where EOF was not correctly detected in :meth:`~.interact`, causing
+ a repeating loop of output on Linux, and blocking before EOF on BSD and
+ Solaris (:ghissue:`49`).
+* Several Solaris (SmartOS) bugfixes, preventing :exc:`IOError` exceptions, especially
+ when used with cron(1) (:ghissue:`44`).
+* Added new keyword argument ``echo=True`` for :class:`spawn`. On SVR4-like
+ systems, the method :meth:`~.isatty` will always return *False*: the child pty
+ does not appear as a terminal. Therefore, :meth:`~.setecho`, :meth:`~.getwinsize`,
+ :meth:`~.setwinsize`, and :meth:`~.waitnoecho` are not supported on those platforms.
+
+After this, we intend to start working on a bigger refactoring of the code, to
+be released as Pexpect 4. There may be more bugfix 3.x releases, however.
+
+Version 3.2
+```````````
+
+* Fix exception handling from :func:`select.select` on Python 2 (:ghpull:`38`).
+ This was accidentally broken in the previous release when it was fixed for
+ Python 3.
+* Removed a workaround for ``TIOCSWINSZ`` on very old systems, which was causing
+ issues on some BSD systems (:ghpull:`40`).
+* Fixed an issue with exception handling in :mod:`~pexpect.pxssh` (:ghpull:`43`)
+
+The documentation for :mod:`~pexpect.pxssh` was improved.
+
+Version 3.1
+```````````
+
+* Fix an issue that prevented importing pexpect on Python 3 when ``sys.stdout``
+ was reassigned (:ghissue:`30`).
+* Improve prompt synchronisation in :mod:`~pexpect.pxssh` (:ghpull:`28`).
+* Fix pickling exception instances (:ghpull:`34`).
+* Fix handling exceptions from :func:`select.select` on Python 3 (:ghpull:`33`).
+
+The examples have also been cleaned up somewhat - this will continue in future
+releases.
+
+Version 3.0
+```````````
+
+The new major version number doesn't indicate any deliberate API incompatibility.
+We have endeavoured to avoid breaking existing APIs. However, pexpect is under
+new maintenance after a long dormancy, so some caution is warranted.
+
+* A new :ref:`unicode API ` was introduced.
+* Python 3 is now supported, using a single codebase.
+* Pexpect now requires at least Python 2.6 or 3.2.
+* The modules other than pexpect, such as :mod:`pexpect.fdpexpect` and
+ :mod:`pexpect.pxssh`, were moved into the pexpect package. For now, wrapper
+ modules are installed to the old locations for backwards compatibility (e.g.
+ ``import pxssh`` will still work), but these will be removed at some point in
+ the future.
+* Ignoring ``SIGHUP`` is now optional - thanks to Kimmo Parviainen-Jalanko for
+ the patch.
+
+We also now have `docs on ReadTheDocs `_,
+and `continuous integration on Travis CI `_.
+
+Version 2.4
+```````````
+
+* Fix a bug regarding making the pty the controlling terminal when the process
+ spawning it is not, actually, a terminal (such as from cron)
+
+Version 2.3
+```````````
+
+* Fixed OSError exception when a pexpect object is cleaned up. Previously, you
+ might have seen this exception::
+
+ Exception exceptions.OSError: (10, 'No child processes')
+ in > ignored
+
+ You should not see that anymore. Thanks to Michael Surette.
+* Added support for buffering reads. This greatly improves speed when trying to
+ match long output from a child process. When you create an instance of the spawn
+ object you can then set a buffer size. For now you MUST do the following to turn
+ on buffering -- it may be on by default in future version::
+
+ child = pexpect.spawn ('my_command')
+ child.maxread=1000 # Sets buffer to 1000 characters.
+
+* I made a subtle change to the way TIMEOUT and EOF exceptions behave.
+ Previously you could either expect these states in which case pexpect
+ will not raise an exception, or you could just let pexpect raise an
+ exception when these states were encountered. If you expected the
+ states then the ``before`` property was set to everything before the
+ state was encountered, but if you let pexpect raise the exception then
+ ``before`` was not set. Now, the ``before`` property will get set either
+ way you choose to handle these states.
+* The spawn object now provides iterators for a *file-like interface*.
+ This makes Pexpect a more complete file-like object. You can now write
+ code like this::
+
+ child = pexpect.spawn ('ls -l')
+ for line in child:
+ print line
+
+* write and writelines() no longer return a value. Use send() if you need that
+ functionality. I did this to make the Spawn object more closely match a
+ file-like object.
+* Added the attribute ``exitstatus``. This will give the exit code returned
+ by the child process. This will be set to ``None`` while the child is still
+ alive. When ``isalive()`` returns 0 then ``exitstatus`` will be set.
+* Made a few more tweaks to ``isalive()`` so that it will operate more
+ consistently on different platforms. Solaris is the most difficult to support.
+* You can now put ``TIMEOUT`` in a list of expected patterns. This is just like
+ putting ``EOF`` in the pattern list. Expecting for a ``TIMEOUT`` may not be
+ used as often as ``EOF``, but this makes Pexpect more consistent.
+* Thanks to a suggestion and sample code from Chad J. Schroeder I added the ability
+ for Pexpect to operate on a file descriptor that is already open. This means that
+ Pexpect can be used to control streams such as those from serial port devices. Now,
+ you just pass the integer file descriptor as the "command" when constructing a
+ spawn open. For example on a Linux box with a modem on ttyS1::
+
+ fd = os.open("/dev/ttyS1", os.O_RDWR|os.O_NONBLOCK|os.O_NOCTTY)
+ m = pexpect.spawn(fd) # Note integer fd is used instead of usual string.
+ m.send("+++") # Escape sequence
+ m.send("ATZ0\r") # Reset modem to profile 0
+ rval = m.expect(["OK", "ERROR"])
+
+* ``read()`` was renamed to ``read_nonblocking()``. Added new ``read()`` method
+ that matches file-like object interface. In general, you should not notice
+ the difference except that ``read()`` no longer allows you to directly set the
+ timeout value. I hope this will not effect any existing code. Switching to
+ ``read_nonblocking()`` should fix existing code.
+* Changed the name of ``set_echo()`` to ``setecho()``.
+* Changed the name of ``send_eof()`` to ``sendeof()``.
+* Modified ``kill()`` so that it checks to make sure the pid ``isalive()``.
+* modified ``spawn()`` (really called from ``__spawn()``) so that it does not
+ raise an exception if ``setwinsize()`` fails. Some platforms such as Cygwin
+ do not like setwinsize. This was a constant problem and since it is not a
+ critical feature I decided to just silence the error. Normally I don't like
+ to do that, but in this case I'm making an exception.
+* Added a method ``close()`` that does what you think. It closes the file
+ descriptor of the child application. It makes no attempt to actually kill the
+ child or wait for its status.
+* Add variables ``__version__`` and ``__revision__`` (from cvs) to the pexpect
+ modules. This is mainly helpful to me so that I can make sure that I'm testing
+ with the right version instead of one already installed.
+* ``log_open()`` and ``log_close(`` have been removed. Now use ``setlog()``.
+ The ``setlog()`` method takes a file object. This is far more flexible than
+ the previous log method. Each time data is written to the file object it will
+ be flushed. To turn logging off simply call ``setlog()`` with None.
+* renamed the ``isAlive()`` method to ``isalive()`` to match the more typical
+ naming style in Python. Also the technique used to detect child process
+ status has been drastically modified. Previously I did some funky stuff
+ with signals which caused indigestion in other Python modules on some
+ platforms. It was a big headache. It still is, but I think it works
+ better now.
+* attribute ``matched`` renamed to ``after``
+* new attribute ``match``
+* The ``expect_eof()`` method is gone. You can now simply use the
+ ``expect()`` method to look for EOF.
+* **Pexpect works on OS X**, but the nature of the quirks cause many of the
+ tests to fail. See bugs. (Incomplete Child Output). The problem is more
+ than minor, but Pexpect is still more than useful for most tasks.
+* **Solaris**: For some reason, the *second* time a pty file descriptor is created and
+ deleted it never gets returned for use. It does not effect the first time
+ or the third time or any time after that. It's only the second time. This
+ is weird... This could be a file descriptor leak, or it could be some
+ peculiarity of how Solaris recycles them. I thought it was a UNIX requirement
+ for the OS to give you the lowest available filedescriptor number. In any case,
+ this should not be a problem unless you create hundreds of pexpect instances...
+ It may also be a pty module bug.
+
+
+Moves and forks
+---------------
+
+* Pexpect development used to be hosted on Sourceforge.
+* In 2011, Thomas Kluyver forked pexpect as 'pexpect-u', to support
+ Python 3. He later decided he had taken the wrong approach with this.
+* In 2012, Noah Spurrier, the original author of Pexpect, moved the
+ project to Github, but was still too busy to develop it much.
+* In 2013, Thomas Kluyver and Jeff Quast forked Pexpect again, intending
+ to call the new fork Pexpected. Noah Spurrier agreed to let them use
+ the name Pexpect, so Pexpect versions 3 and above are based on this
+ fork, which now lives `here on Github `_.
Index: third_party/Python/module/pexpect-4.6/doc/index.rst
===================================================================
--- third_party/Python/module/pexpect-4.6/doc/index.rst
+++ third_party/Python/module/pexpect-4.6/doc/index.rst
@@ -0,0 +1,50 @@
+Pexpect version |version|
+=========================
+
+.. image:: https://travis-ci.org/pexpect/pexpect.png?branch=master
+ :target: https://travis-ci.org/pexpect/pexpect
+ :align: right
+ :alt: Build status
+
+Pexpect makes Python a better tool for controlling other
+applications.
+
+Pexpect is a pure Python module for spawning child applications;
+controlling them; and responding to expected patterns in their output.
+Pexpect works like Don Libes' Expect. Pexpect allows your script to
+spawn a child application and control it as if a human were typing
+commands.
+
+Pexpect can be used for automating interactive applications such as
+ssh, ftp, passwd, telnet, etc. It can be used to a automate setup
+scripts for duplicating software package installations on different
+servers. It can be used for automated software testing. Pexpect is in
+the spirit of Don Libes' Expect, but Pexpect is pure Python. Unlike
+other Expect-like modules for Python, Pexpect does not require TCL or
+Expect nor does it require C extensions to be compiled. It should work
+on any platform that supports the standard Python pty module. The
+Pexpect interface was designed to be easy to use.
+
+Contents:
+
+.. toctree::
+ :maxdepth: 2
+
+ install
+ overview
+ api/index
+ examples
+ FAQ
+ commonissues
+ history
+
+Pexpect is developed `on Github `_. Please
+report `issues `_ there as well.
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+
Index: third_party/Python/module/pexpect-4.6/doc/install.rst
===================================================================
--- third_party/Python/module/pexpect-4.6/doc/install.rst
+++ third_party/Python/module/pexpect-4.6/doc/install.rst
@@ -0,0 +1,20 @@
+Installation
+============
+
+Pexpect is on PyPI, and can be installed with standard tools::
+
+ pip install pexpect
+
+Or::
+
+ easy_install pexpect
+
+Requirements
+------------
+
+This version of Pexpect requires Python 3.3 or above, or Python 2.7.
+
+As of version 4.0, Pexpect can be used on Windows and POSIX systems. However,
+:class:`pexpect.spawn` and :func:`pexpect.run` are only available on POSIX,
+where the :mod:`pty` module is present in the standard library. See
+:ref:`windows` for more information.
Index: third_party/Python/module/pexpect-4.6/doc/make.bat
===================================================================
--- third_party/Python/module/pexpect-4.6/doc/make.bat
+++ third_party/Python/module/pexpect-4.6/doc/make.bat
@@ -0,0 +1,190 @@
+@ECHO OFF
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+ set SPHINXBUILD=sphinx-build
+)
+set BUILDDIR=_build
+set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
+set I18NSPHINXOPTS=%SPHINXOPTS% .
+if NOT "%PAPER%" == "" (
+ set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
+ set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
+)
+
+if "%1" == "" goto help
+
+if "%1" == "help" (
+ :help
+ echo.Please use `make ^` where ^ is one of
+ echo. html to make standalone HTML files
+ echo. dirhtml to make HTML files named index.html in directories
+ echo. singlehtml to make a single large HTML file
+ echo. pickle to make pickle files
+ echo. json to make JSON files
+ echo. htmlhelp to make HTML files and a HTML help project
+ echo. qthelp to make HTML files and a qthelp project
+ echo. devhelp to make HTML files and a Devhelp project
+ echo. epub to make an epub
+ echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
+ echo. text to make text files
+ echo. man to make manual pages
+ echo. texinfo to make Texinfo files
+ echo. gettext to make PO message catalogs
+ echo. changes to make an overview over all changed/added/deprecated items
+ echo. linkcheck to check all external links for integrity
+ echo. doctest to run all doctests embedded in the documentation if enabled
+ goto end
+)
+
+if "%1" == "clean" (
+ for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
+ del /q /s %BUILDDIR%\*
+ goto end
+)
+
+if "%1" == "html" (
+ %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/html.
+ goto end
+)
+
+if "%1" == "dirhtml" (
+ %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
+ goto end
+)
+
+if "%1" == "singlehtml" (
+ %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
+ goto end
+)
+
+if "%1" == "pickle" (
+ %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can process the pickle files.
+ goto end
+)
+
+if "%1" == "json" (
+ %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can process the JSON files.
+ goto end
+)
+
+if "%1" == "htmlhelp" (
+ %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can run HTML Help Workshop with the ^
+.hhp project file in %BUILDDIR%/htmlhelp.
+ goto end
+)
+
+if "%1" == "qthelp" (
+ %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can run "qcollectiongenerator" with the ^
+.qhcp project file in %BUILDDIR%/qthelp, like this:
+ echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Pexpect.qhcp
+ echo.To view the help file:
+ echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Pexpect.ghc
+ goto end
+)
+
+if "%1" == "devhelp" (
+ %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished.
+ goto end
+)
+
+if "%1" == "epub" (
+ %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The epub file is in %BUILDDIR%/epub.
+ goto end
+)
+
+if "%1" == "latex" (
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
+ goto end
+)
+
+if "%1" == "text" (
+ %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The text files are in %BUILDDIR%/text.
+ goto end
+)
+
+if "%1" == "man" (
+ %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The manual pages are in %BUILDDIR%/man.
+ goto end
+)
+
+if "%1" == "texinfo" (
+ %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
+ goto end
+)
+
+if "%1" == "gettext" (
+ %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
+ goto end
+)
+
+if "%1" == "changes" (
+ %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.The overview file is in %BUILDDIR%/changes.
+ goto end
+)
+
+if "%1" == "linkcheck" (
+ %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Link check complete; look for any errors in the above output ^
+or in %BUILDDIR%/linkcheck/output.txt.
+ goto end
+)
+
+if "%1" == "doctest" (
+ %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Testing of doctests in the sources finished, look at the ^
+results in %BUILDDIR%/doctest/output.txt.
+ goto end
+)
+
+:end
Index: third_party/Python/module/pexpect-4.6/doc/overview.rst
===================================================================
--- third_party/Python/module/pexpect-4.6/doc/overview.rst
+++ third_party/Python/module/pexpect-4.6/doc/overview.rst
@@ -0,0 +1,266 @@
+API Overview
+============
+
+Pexpect can be used for automating interactive applications such as ssh, ftp,
+mencoder, passwd, etc. The Pexpect interface was designed to be easy to use.
+
+Here is an example of Pexpect in action::
+
+ # This connects to the openbsd ftp site and
+ # downloads the recursive directory listing.
+ import pexpect
+ child = pexpect.spawn('ftp ftp.openbsd.org')
+ child.expect('Name .*: ')
+ child.sendline('anonymous')
+ child.expect('Password:')
+ child.sendline('noah@example.com')
+ child.expect('ftp> ')
+ child.sendline('lcd /tmp')
+ child.expect('ftp> ')
+ child.sendline('cd pub/OpenBSD')
+ child.expect('ftp> ')
+ child.sendline('get README')
+ child.expect('ftp> ')
+ child.sendline('bye')
+
+Obviously you could write an ftp client using Python's own :mod:`ftplib` module,
+but this is just a demonstration. You can use this technique with any application.
+This is especially handy if you are writing automated test tools.
+
+There are two important methods in Pexpect -- :meth:`~pexpect.spawn.expect` and
+:meth:`~pexpect.spawn.send` (or :meth:`~pexpect.spawn.sendline` which is
+like :meth:`~pexpect.spawn.send` with a linefeed). The :meth:`~pexpect.spawn.expect`
+method waits for the child application to return a given string. The string you
+specify is a regular expression, so you can match complicated patterns. The
+:meth:`~pexpect.spawn.send` method writes a string to the child application.
+From the child's point of view it looks just like someone typed the text from a
+terminal. After each call to :meth:`~pexpect.spawn.expect` the ``before`` and ``after``
+properties will be set to the text printed by child application. The ``before``
+property will contain all text up to the expected string pattern. The ``after``
+string will contain the text that was matched by the expected pattern.
+The match property is set to the `re match object `_.
+
+An example of Pexpect in action may make things more clear. This example uses
+ftp to login to the OpenBSD site; list files in a directory; and then pass
+interactive control of the ftp session to the human user::
+
+ import pexpect
+ child = pexpect.spawn ('ftp ftp.openbsd.org')
+ child.expect ('Name .*: ')
+ child.sendline ('anonymous')
+ child.expect ('Password:')
+ child.sendline ('noah@example.com')
+ child.expect ('ftp> ')
+ child.sendline ('ls /pub/OpenBSD/')
+ child.expect ('ftp> ')
+ print child.before # Print the result of the ls command.
+ child.interact() # Give control of the child to the user.
+
+Special EOF and TIMEOUT patterns
+--------------------------------
+
+There are two special patterns to match the End Of File (:class:`~pexpect.EOF`)
+or a Timeout condition (:class:`~pexpect.TIMEOUT`). You can pass these
+patterns to :meth:`~pexpect.spawn.expect`. These patterns are not regular
+expressions. Use them like predefined constants.
+
+If the child has died and you have read all the child's output then ordinarily
+:meth:`~pexpect.spawn.expect` will raise an :class:`~pexpect.EOF` exception.
+You can read everything up to the EOF without generating an exception by using
+the EOF pattern expect. In this case everything the child has output will be
+available in the ``before`` property.
+
+The pattern given to :meth:`~pexpect.spawn.expect` may be a regular expression
+or it may also be a list of regular expressions. This allows you to match
+multiple optional responses. The :meth:`~pexpect.spawn.expect` method returns
+the index of the pattern that was matched. For example, say you wanted to login
+to a server. After entering a password you could get various responses from the
+server -- your password could be rejected; or you could be allowed in and asked
+for your terminal type; or you could be let right in and given a command prompt.
+The following code fragment gives an example of this::
+
+ child.expect('password:')
+ child.sendline(my_secret_password)
+ # We expect any of these three patterns...
+ i = child.expect (['Permission denied', 'Terminal type', '[#\$] '])
+ if i==0:
+ print('Permission denied on host. Can\'t login')
+ child.kill(0)
+ elif i==1:
+ print('Login OK... need to send terminal type.')
+ child.sendline('vt100')
+ child.expect('[#\$] ')
+ elif i==2:
+ print('Login OK.')
+ print('Shell command prompt', child.after)
+
+If nothing matches an expected pattern then :meth:`~pexpect.spawn.expect` will
+eventually raise a :class:`~pexpect.TIMEOUT` exception. The default time is 30
+seconds, but you can change this by passing a timeout argument to
+:meth:`~pexpect.spawn.expect`::
+
+ # Wait no more than 2 minutes (120 seconds) for password prompt.
+ child.expect('password:', timeout=120)
+
+Find the end of line -- CR/LF conventions
+-----------------------------------------
+
+Pexpect matches regular expressions a little differently than what you might be
+used to.
+
+The :regexp:`$` pattern for end of line match is useless. The :regexp:`$`
+matches the end of string, but Pexpect reads from the child one character at a
+time, so each character looks like the end of a line. Pexpect can't do a
+look-ahead into the child's output stream. In general you would have this
+situation when using regular expressions with any stream.
+
+.. note::
+
+ Pexpect does have an internal buffer, so reads are faster than one character
+ at a time, but from the user's perspective the regex patterns test happens
+ one character at a time.
+
+The best way to match the end of a line is to look for the newline: ``"\r\n"``
+(CR/LF). Yes, that does appear to be DOS-style. It may surprise some UNIX people
+to learn that terminal TTY device drivers (dumb, vt100, ANSI, xterm, etc.) all
+use the CR/LF combination to signify the end of line. Pexpect uses a Pseudo-TTY
+device to talk to the child application, so when the child app prints ``"\n"``
+you actually see ``"\r\n"``.
+
+UNIX uses just linefeeds to end lines of text, but not when it comes to TTY
+devices! TTY devices are more like the Windows world. Each line of text ends
+with a CR/LF combination. When you intercept data from a UNIX command from a
+TTY device you will find that the TTY device outputs a CR/LF combination. A
+UNIX command may only write a linefeed (``\n``), but the TTY device driver
+converts it to CR/LF. This means that your terminal will see lines end with
+CR/LF (hex ``0D 0A``). Since Pexpect emulates a terminal, to match ends of
+lines you have to expect the CR/LF combination::
+
+ child.expect('\r\n')
+
+If you just need to skip past a new line then ``expect('\n')`` by itself will
+work, but if you are expecting a specific pattern before the end of line then
+you need to explicitly look for the ``\r``. For example the following expects a
+word at the end of a line::
+
+ child.expect('\w+\r\n')
+
+But the following would both fail::
+
+ child.expect('\w+\n')
+
+And as explained before, trying to use :regexp:`$` to match the end of line
+would not work either::
+
+ child.expect ('\w+$')
+
+So if you need to explicitly look for the END OF LINE, you want to look for the
+CR/LF combination -- not just the LF and not the $ pattern.
+
+This problem is not limited to Pexpect. This problem happens any time you try
+to perform a regular expression match on a stream. Regular expressions need to
+look ahead. With a stream it is hard to look ahead because the process
+generating the stream may not be finished. There is no way to know if the
+process has paused momentarily or is finished and waiting for you. Pexpect must
+implicitly always do a NON greedy match (minimal) at the end of a input.
+
+Pexpect compiles all regular expressions with the :data:`re.DOTALL` flag.
+With the :data:`~re.DOTALL` flag, a ``"."`` will match a newline.
+
+Beware of + and * at the end of patterns
+----------------------------------------
+
+Remember that any time you try to match a pattern that needs look-ahead that
+you will always get a minimal match (non greedy). For example, the following
+will always return just one character::
+
+ child.expect ('.+')
+
+This example will match successfully, but will always return no characters::
+
+ child.expect ('.*')
+
+Generally any star * expression will match as little as possible.
+
+One thing you can do is to try to force a non-ambiguous character at the end of
+your :regexp:`\\d+` pattern. Expect that character to delimit the string. For
+example, you might try making the end of your pattern be :regexp:`\\D+` instead
+of :regexp:`\\D*`. Number digits alone would not satisfy the :regexp:`(\\d+)\\D+`
+pattern. You would need some numbers and at least one non-number at the end.
+
+
+Debugging
+---------
+
+If you get the string value of a :class:`pexpect.spawn` object you will get lots
+of useful debugging information. For debugging it's very useful to use the
+following pattern::
+
+ try:
+ i = child.expect ([pattern1, pattern2, pattern3, etc])
+ except:
+ print("Exception was thrown")
+ print("debug information:")
+ print(str(child))
+
+It is also useful to log the child's input and out to a file or the screen. The
+following will turn on logging and send output to stdout (the screen)::
+
+ child = pexpect.spawn(foo)
+ child.logfile = sys.stdout
+
+Exceptions
+----------
+
+:class:`~pexpect.EOF`
+
+Note that two flavors of EOF Exception may be thrown. They are virtually
+identical except for the message string. For practical purposes you should have
+no need to distinguish between them, but they do give a little extra information
+about what type of platform you are running. The two messages are:
+
+- "End Of File (EOF) in read(). Exception style platform."
+- "End Of File (EOF) in read(). Empty string style platform."
+
+Some UNIX platforms will throw an exception when you try to read from a file
+descriptor in the EOF state. Other UNIX platforms instead quietly return an
+empty string to indicate that the EOF state has been reached.
+
+If you wish to read up to the end of the child's output without generating an
+:class:`~pexpect.EOF` exception then use the ``expect(pexpect.EOF)`` method.
+
+:class:`~pexpect.TIMEOUT`
+
+The :meth:`~pexpect.spawn.expect` and :meth:`~pexpect.spawn.read` methods will
+also timeout if the child does not generate any output for a given amount of
+time. If this happens they will raise a :class:`~pexpect.TIMEOUT` exception.
+You can have these methods ignore timeout and block indefinitely by passing
+``None`` for the timeout parameter::
+
+ child.expect(pexpect.EOF, timeout=None)
+
+.. _windows:
+
+Pexpect on Windows
+------------------
+
+.. versionadded:: 4.0
+ Windows support
+
+Pexpect can be used on Windows to wait for a pattern to be produced by a child
+process, using :class:`pexpect.popen_spawn.PopenSpawn`, or a file descriptor,
+using :class:`pexpect.fdpexpect.fdspawn`.
+
+:class:`pexpect.spawn` and :func:`pexpect.run` are *not* available on Windows,
+as they rely on Unix pseudoterminals (ptys). Cross platform code must not use
+these.
+
+``PopenSpawn`` is not a direct replacement for ``spawn``. Many programs only
+offer interactive behaviour if they detect that they are running in a terminal.
+When run by ``PopenSpawn``, they may behave differently.
+
+.. seealso::
+
+ `winpexpect `__ and `wexpect `__
+ Two unmaintained pexpect-like modules for Windows, which work with a
+ hidden console.
Index: third_party/Python/module/pexpect-4.6/doc/requirements.txt
===================================================================
--- third_party/Python/module/pexpect-4.6/doc/requirements.txt
+++ third_party/Python/module/pexpect-4.6/doc/requirements.txt
@@ -0,0 +1 @@
+ptyprocess
Index: third_party/Python/module/pexpect-4.6/doc/sphinxext/github.py
===================================================================
--- third_party/Python/module/pexpect-4.6/doc/sphinxext/github.py
+++ third_party/Python/module/pexpect-4.6/doc/sphinxext/github.py
@@ -0,0 +1,155 @@
+"""Define text roles for GitHub
+
+* ghissue - Issue
+* ghpull - Pull Request
+* ghuser - User
+
+Adapted from bitbucket example here:
+https://bitbucket.org/birkenfeld/sphinx-contrib/src/tip/bitbucket/sphinxcontrib/bitbucket.py
+
+Authors
+-------
+
+* Doug Hellmann
+* Min RK
+"""
+#
+# Original Copyright (c) 2010 Doug Hellmann. All rights reserved.
+#
+
+from docutils import nodes, utils
+from docutils.parsers.rst.roles import set_classes
+
+def make_link_node(rawtext, app, type, slug, options):
+ """Create a link to a github resource.
+
+ :param rawtext: Text being replaced with link node.
+ :param app: Sphinx application context
+ :param type: Link type (issues, changeset, etc.)
+ :param slug: ID of the thing to link to
+ :param options: Options dictionary passed to role func.
+ """
+
+ try:
+ base = app.config.github_project_url
+ if not base:
+ raise AttributeError
+ if not base.endswith('/'):
+ base += '/'
+ except AttributeError as err:
+ raise ValueError('github_project_url configuration value is not set (%s)' % str(err))
+
+ ref = base + type + '/' + slug + '/'
+ set_classes(options)
+ prefix = "#"
+ if type == 'pull':
+ prefix = "PR " + prefix
+ node = nodes.reference(rawtext, prefix + utils.unescape(slug), refuri=ref,
+ **options)
+ return node
+
+def ghissue_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
+ """Link to a GitHub issue.
+
+ Returns 2 part tuple containing list of nodes to insert into the
+ document and a list of system messages. Both are allowed to be
+ empty.
+
+ :param name: The role name used in the document.
+ :param rawtext: The entire markup snippet, with role.
+ :param text: The text marked with the role.
+ :param lineno: The line number where rawtext appears in the input.
+ :param inliner: The inliner instance that called us.
+ :param options: Directive options for customization.
+ :param content: The directive content for customization.
+ """
+
+ try:
+ issue_num = int(text)
+ if issue_num <= 0:
+ raise ValueError
+ except ValueError:
+ msg = inliner.reporter.error(
+ 'GitHub issue number must be a number greater than or equal to 1; '
+ '"%s" is invalid.' % text, line=lineno)
+ prb = inliner.problematic(rawtext, rawtext, msg)
+ return [prb], [msg]
+ app = inliner.document.settings.env.app
+ #app.info('issue %r' % text)
+ if 'pull' in name.lower():
+ category = 'pull'
+ elif 'issue' in name.lower():
+ category = 'issues'
+ else:
+ msg = inliner.reporter.error(
+ 'GitHub roles include "ghpull" and "ghissue", '
+ '"%s" is invalid.' % name, line=lineno)
+ prb = inliner.problematic(rawtext, rawtext, msg)
+ return [prb], [msg]
+ node = make_link_node(rawtext, app, category, str(issue_num), options)
+ return [node], []
+
+def ghuser_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
+ """Link to a GitHub user.
+
+ Returns 2 part tuple containing list of nodes to insert into the
+ document and a list of system messages. Both are allowed to be
+ empty.
+
+ :param name: The role name used in the document.
+ :param rawtext: The entire markup snippet, with role.
+ :param text: The text marked with the role.
+ :param lineno: The line number where rawtext appears in the input.
+ :param inliner: The inliner instance that called us.
+ :param options: Directive options for customization.
+ :param content: The directive content for customization.
+ """
+ app = inliner.document.settings.env.app
+ #app.info('user link %r' % text)
+ ref = 'https://www.github.com/' + text
+ node = nodes.reference(rawtext, text, refuri=ref, **options)
+ return [node], []
+
+def ghcommit_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
+ """Link to a GitHub commit.
+
+ Returns 2 part tuple containing list of nodes to insert into the
+ document and a list of system messages. Both are allowed to be
+ empty.
+
+ :param name: The role name used in the document.
+ :param rawtext: The entire markup snippet, with role.
+ :param text: The text marked with the role.
+ :param lineno: The line number where rawtext appears in the input.
+ :param inliner: The inliner instance that called us.
+ :param options: Directive options for customization.
+ :param content: The directive content for customization.
+ """
+ app = inliner.document.settings.env.app
+ #app.info('user link %r' % text)
+ try:
+ base = app.config.github_project_url
+ if not base:
+ raise AttributeError
+ if not base.endswith('/'):
+ base += '/'
+ except AttributeError as err:
+ raise ValueError('github_project_url configuration value is not set (%s)' % str(err))
+
+ ref = base + text
+ node = nodes.reference(rawtext, text[:6], refuri=ref, **options)
+ return [node], []
+
+
+def setup(app):
+ """Install the plugin.
+
+ :param app: Sphinx application context.
+ """
+ app.info('Initializing GitHub plugin')
+ app.add_role('ghissue', ghissue_role)
+ app.add_role('ghpull', ghissue_role)
+ app.add_role('ghuser', ghuser_role)
+ app.add_role('ghcommit', ghcommit_role)
+ app.add_config_value('github_project_url', None, 'env')
+ return
Index: third_party/Python/module/pexpect-4.6/examples/README
===================================================================
--- third_party/Python/module/pexpect-4.6/examples/README
+++ third_party/Python/module/pexpect-4.6/examples/README
@@ -0,0 +1,86 @@
+This directory contains scripts that give examples of using Pexpect.
+
+hive.py
+ This script creates SSH connections to a list of hosts that
+ you provide. Then you are given a command line prompt. Each
+ shell command that you enter is sent to all the hosts. The
+ response from each host is collected and printed. For example,
+ you could connect to a dozen different machines and reboot
+ them all at once.
+
+script.py
+ This implements a command similar to the classic BSD "script" command.
+ This will start a subshell and log all input and output to a file.
+ This demonstrates the interact() method of Pexpect.
+
+fix_cvs_files.py
+ This is for cleaning up binary files improperly added to
+ CVS. This script scans the given path to find binary files;
+ checks with CVS to see if the sticky options are set to -kb;
+ finally if sticky options are not -kb then uses 'cvs admin'
+ to set the -kb option.
+
+ftp.py
+ This demonstrates an FTP "bookmark".
+ This connects to an ftp site; does a few ftp commands; and then gives the user
+ interactive control over the session. In this case the "bookmark" is to a
+ directory on the OpenBSD ftp server. It puts you in the i386 packages
+ directory. You can easily modify this for other sites.
+ This demonstrates the interact() method of Pexpect.
+
+monitor.py
+ This runs a sequence of system status commands on a remote host using SSH.
+ It runs a simple system checks such as uptime and free to monitor
+ the state of the remote host.
+
+passmass.py
+ This will login to a list of hosts and change the password of the
+ given user. This demonstrates scripting logins; although, you could
+ more easily do this using the pxssh subclass of Pexpect.
+ See also the "hive.py" example script for a more general example
+ of scripting a collection of servers.
+
+python.py
+ This starts the python interpreter and prints the greeting message backwards.
+ It then gives the user interactive control of Python. It's pretty useless!
+
+rippy.py
+ This is a wizard for mencoder. It greatly simplifies the process of
+ ripping a DVD to mpeg4 format (XviD, DivX). It can transcode from any
+ video file to another. It has options for resampling the audio stream;
+ removing interlace artifacts, fitting to a target file size, etc.
+ There are lots of options, but the process is simple and easy to use.
+
+ssh_tunnel.py
+ This starts an SSH tunnel to a remote machine. It monitors the connection
+ and restarts the tunnel if it goes down.
+
+uptime.py
+ This will run the uptime command and parse the output into python variables.
+ This demonstrates using a single regular expression to match the output
+ of a command and capturing different variable in match groups.
+ The regular expression takes into account a wide variety of different
+ formats for uptime output.
+
+df.py
+ This collects filesystem capacity info using the 'df' command.
+ Tuples of filesystem name and percentage are stored in a list.
+ A simple report is printed. Filesystems over 95% capacity are highlighted.
+
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
Index: third_party/Python/module/pexpect-4.6/examples/astat.py
===================================================================
--- third_party/Python/module/pexpect-4.6/examples/astat.py
+++ third_party/Python/module/pexpect-4.6/examples/astat.py
@@ -0,0 +1,99 @@
+#!/usr/bin/env python
+
+'''This runs Apache Status on the remote host and returns the number of requests per second.
+
+./astat.py [-s server_hostname] [-u username] [-p password]
+ -s : hostname of the remote server to login to.
+ -u : username to user for login.
+ -p : Password to user for login.
+
+Example:
+ This will print information about the given host:
+ ./astat.py -s www.example.com -u mylogin -p mypassword
+
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+from __future__ import print_function
+
+from __future__ import absolute_import
+
+import os
+import sys
+import getopt
+import getpass
+import pxssh
+
+
+try:
+ raw_input
+except NameError:
+ raw_input = input
+
+
+def exit_with_usage():
+
+ print(globals()['__doc__'])
+ os._exit(1)
+
+
+def main():
+
+ ######################################################################
+ ## Parse the options, arguments, get ready, etc.
+ ######################################################################
+ try:
+ optlist, args = getopt.getopt(sys.argv[1:], 'h?s:u:p:', ['help','h','?'])
+ except Exception as e:
+ print(str(e))
+ exit_with_usage()
+ options = dict(optlist)
+ if len(args) > 1:
+ exit_with_usage()
+
+ if [elem for elem in options if elem in ['-h','--h','-?','--?','--help']]:
+ print("Help:")
+ exit_with_usage()
+
+ if '-s' in options:
+ hostname = options['-s']
+ else:
+ hostname = raw_input('hostname: ')
+ if '-u' in options:
+ username = options['-u']
+ else:
+ username = raw_input('username: ')
+ if '-p' in options:
+ password = options['-p']
+ else:
+ password = getpass.getpass('password: ')
+
+ #
+ # Login via SSH
+ #
+ p = pxssh.pxssh()
+ p.login(hostname, username, password)
+ p.sendline('apachectl status')
+ p.expect(r'([0-9]+\.[0-9]+)\s*requests/sec')
+ requests_per_second = p.match.groups()[0]
+ p.logout()
+ print(requests_per_second)
+
+if __name__ == "__main__":
+ main()
Index: third_party/Python/module/pexpect-4.6/examples/cgishell.cgi
===================================================================
--- third_party/Python/module/pexpect-4.6/examples/cgishell.cgi
+++ third_party/Python/module/pexpect-4.6/examples/cgishell.cgi
@@ -0,0 +1,766 @@
+#!/usr/bin/python
+##!/usr/bin/env python
+"""CGI shell server
+
+This exposes a shell terminal on a web page.
+It uses AJAX to send keys and receive screen updates.
+The client web browser needs nothing but CSS and Javascript.
+
+ --hostname : sets the remote host name to open an ssh connection to.
+ --username : sets the user name to login with
+ --password : (optional) sets the password to login with
+ --port : set the local port for the server to listen on
+ --watch : show the virtual screen after each client request
+
+This project is probably not the most security conscious thing I've ever built.
+This should be considered an experimental tool -- at best.
+"""
+
+from __future__ import absolute_import
+from __future__ import print_function
+
+import sys,os
+sys.path.insert (0,os.getcwd()) # let local modules precede any installed modules
+import socket, random, string, traceback, cgi, time, getopt, getpass, threading, resource, signal
+import pxssh, pexpect, ANSI
+
+def exit_with_usage(exit_code=1):
+ print(globals()['__doc__'])
+ os._exit(exit_code)
+
+def client (command, host='localhost', port=-1):
+ """This sends a request to the server and returns the response.
+ If port <= 0 then host is assumed to be the filename of a Unix domain socket.
+ If port > 0 then host is an inet hostname.
+ """
+ if port <= 0:
+ s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+ s.connect(host)
+ else:
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ s.connect((host, port))
+ s.send(command)
+ data = s.recv (2500)
+ s.close()
+ return data
+
+def server (hostname, username, password, socket_filename='/tmp/server_sock', daemon_mode = True, verbose=False):
+ """This starts and services requests from a client.
+ If daemon_mode is True then this forks off a separate daemon process and returns the daemon's pid.
+ If daemon_mode is False then this does not return until the server is done.
+ """
+ if daemon_mode:
+ mypid_name = '/tmp/%d.pid' % os.getpid()
+ daemon_pid = daemonize(daemon_pid_filename=mypid_name)
+ time.sleep(1)
+ if daemon_pid != 0:
+ os.unlink(mypid_name)
+ return daemon_pid
+
+ virtual_screen = ANSI.ANSI (24,80)
+ child = pxssh.pxssh()
+ try:
+ child.login (hostname, username, password, login_naked=True)
+ except:
+ return
+ if verbose: print('login OK')
+ virtual_screen.write (child.before)
+ virtual_screen.write (child.after)
+
+ if os.path.exists(socket_filename): os.remove(socket_filename)
+ s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+ s.bind(socket_filename)
+ os.chmod(socket_filename, 0o777)
+ if verbose: print('Listen')
+ s.listen(1)
+
+ r = roller (endless_poll, (child, child.PROMPT, virtual_screen))
+ r.start()
+ if verbose: print("started screen-poll-updater in background thread")
+ sys.stdout.flush()
+ try:
+ while True:
+ conn, addr = s.accept()
+ if verbose: print('Connected by', addr)
+ data = conn.recv(1024)
+ request = data.split(' ', 1)
+ if len(request)>1:
+ cmd = request[0].strip()
+ arg = request[1].strip()
+ else:
+ cmd = request[0].strip()
+ arg = ''
+
+ if cmd == 'exit':
+ r.cancel()
+ break
+ elif cmd == 'sendline':
+ child.sendline (arg)
+ time.sleep(0.1)
+ shell_window = str(virtual_screen)
+ elif cmd == 'send' or cmd=='xsend':
+ if cmd=='xsend':
+ arg = arg.decode("hex")
+ child.send (arg)
+ time.sleep(0.1)
+ shell_window = str(virtual_screen)
+ elif cmd == 'cursor':
+ shell_window = '%x,%x' % (virtual_screen.cur_r, virtual_screen.cur_c)
+ elif cmd == 'refresh':
+ shell_window = str(virtual_screen)
+ elif cmd == 'hash':
+ shell_window = str(hash(str(virtual_screen)))
+
+ response = []
+ response.append (shell_window)
+ if verbose: print('\n'.join(response))
+ sent = conn.send('\n'.join(response))
+ if sent < len (response):
+ if verbose: print("Sent is too short. Some data was cut off.")
+ conn.close()
+ except e:
+ pass
+ r.cancel()
+ if verbose: print("cleaning up socket")
+ s.close()
+ if os.path.exists(socket_filename): os.remove(socket_filename)
+ if verbose: print("server done!")
+
+class roller (threading.Thread):
+ """This class continuously loops a function in a thread.
+ This is basically a thin layer around Thread with a
+ while loop and a cancel.
+ """
+ def __init__(self, function, args=[], kwargs={}):
+ threading.Thread.__init__(self)
+ self.function = function
+ self.args = args
+ self.kwargs = kwargs
+ self.finished = threading.Event()
+ def cancel(self):
+ """Stop the roller."""
+ self.finished.set()
+ def run(self):
+ while not self.finished.isSet():
+ self.function(*self.args, **self.kwargs)
+
+def endless_poll (child, prompt, screen, refresh_timeout=0.1):
+ """This keeps the screen updated with the output of the child.
+ This will be run in a separate thread. See roller class.
+ """
+ #child.logfile_read = screen
+ try:
+ s = child.read_nonblocking(4000, 0.1)
+ screen.write(s)
+ except:
+ pass
+
+def daemonize (stdin=None, stdout=None, stderr=None, daemon_pid_filename=None):
+ """This runs the current process in the background as a daemon.
+ The arguments stdin, stdout, stderr allow you to set the filename that the daemon reads and writes to.
+ If they are set to None then all stdio for the daemon will be directed to /dev/null.
+ If daemon_pid_filename is set then the pid of the daemon will be written to it as plain text
+ and the pid will be returned. If daemon_pid_filename is None then this will return None.
+ """
+ UMASK = 0
+ WORKINGDIR = "/"
+ MAXFD = 1024
+
+ # The stdio file descriptors are redirected to /dev/null by default.
+ if hasattr(os, "devnull"):
+ DEVNULL = os.devnull
+ else:
+ DEVNULL = "/dev/null"
+ if stdin is None: stdin = DEVNULL
+ if stdout is None: stdout = DEVNULL
+ if stderr is None: stderr = DEVNULL
+
+ try:
+ pid = os.fork() # fork first child
+ except OSError as e:
+ raise Exception("%s [%d]" % (e.strerror, e.errno))
+
+ if pid != 0:
+ os.waitpid(pid,0)
+ if daemon_pid_filename is not None:
+ daemon_pid = int(file(daemon_pid_filename,'r').read())
+ return daemon_pid
+ else:
+ return None
+
+ # first child
+ os.setsid()
+ signal.signal(signal.SIGHUP, signal.SIG_IGN)
+
+ try:
+ pid = os.fork() # fork second child
+ except OSError as e:
+ raise Exception("%s [%d]" % (e.strerror, e.errno))
+
+ if pid != 0:
+ if daemon_pid_filename is not None:
+ file(daemon_pid_filename,'w').write(str(pid))
+ os._exit(0) # exit parent (the first child) of the second child.
+
+ # second child
+ os.chdir(WORKINGDIR)
+ os.umask(UMASK)
+
+ maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1]
+ if maxfd == resource.RLIM_INFINITY:
+ maxfd = MAXFD
+
+ # close all file descriptors
+ for fd in range(0, maxfd):
+ try:
+ os.close(fd)
+ except OSError: # fd wasn't open to begin with (ignored)
+ pass
+
+ os.open (DEVNULL, os.O_RDWR) # standard input
+
+ # redirect standard file descriptors
+ si = open(stdin, 'r')
+ so = open(stdout, 'a+')
+ se = open(stderr, 'a+', 0)
+ os.dup2(si.fileno(), sys.stdin.fileno())
+ os.dup2(so.fileno(), sys.stdout.fileno())
+ os.dup2(se.fileno(), sys.stderr.fileno())
+
+ return 0
+
+def client_cgi ():
+ """This handles the request if this script was called as a cgi.
+ """
+ sys.stderr = sys.stdout
+ ajax_mode = False
+ TITLE="Shell"
+ SHELL_OUTPUT=""
+ SID="NOT"
+ print("Content-type: text/html;charset=utf-8\r\n")
+ try:
+ form = cgi.FieldStorage()
+ if 'ajax' in form:
+ ajax_mode = True
+ ajax_cmd = form['ajax'].value
+ SID=form['sid'].value
+ if ajax_cmd == 'send':
+ command = 'xsend'
+ arg = form['arg'].value.encode('hex')
+ result = client (command + ' ' + arg, '/tmp/'+SID)
+ print(result)
+ elif ajax_cmd == 'refresh':
+ command = 'refresh'
+ result = client (command, '/tmp/'+SID)
+ print(result)
+ elif ajax_cmd == 'cursor':
+ command = 'cursor'
+ result = client (command, '/tmp/'+SID)
+ print(result)
+ elif ajax_cmd == 'exit':
+ command = 'exit'
+ result = client (command, '/tmp/'+SID)
+ print(result)
+ elif ajax_cmd == 'hash':
+ command = 'hash'
+ result = client (command, '/tmp/'+SID)
+ print(result)
+ elif 'sid' not in form:
+ SID=random_sid()
+ print(LOGIN_HTML % locals());
+ else:
+ SID=form['sid'].value
+ if 'start_server' in form:
+ USERNAME = form['username'].value
+ PASSWORD = form['password'].value
+ dpid = server ('127.0.0.1', USERNAME, PASSWORD, '/tmp/'+SID)
+ SHELL_OUTPUT="daemon pid: " + str(dpid)
+ else:
+ if 'cli' in form:
+ command = 'sendline ' + form['cli'].value
+ else:
+ command = 'sendline'
+ SHELL_OUTPUT = client (command, '/tmp/'+SID)
+ print(CGISH_HTML % locals())
+ except:
+ tb_dump = traceback.format_exc()
+ if ajax_mode:
+ print(str(tb_dump))
+ else:
+ SHELL_OUTPUT=str(tb_dump)
+ print(CGISH_HTML % locals())
+
+def server_cli():
+ """This is the command line interface to starting the server.
+ This handles things if the script was not called as a CGI
+ (if you run it from the command line).
+ """
+ try:
+ optlist, args = getopt.getopt(sys.argv[1:], 'h?d', ['help','h','?', 'hostname=', 'username=', 'password=', 'port=', 'watch'])
+ except Exception as e:
+ print(str(e))
+ exit_with_usage()
+
+ command_line_options = dict(optlist)
+ options = dict(optlist)
+ # There are a million ways to cry for help. These are but a few of them.
+ if [elem for elem in command_line_options if elem in ['-h','--h','-?','--?','--help']]:
+ exit_with_usage(0)
+
+ hostname = "127.0.0.1"
+ #port = 1664
+ username = os.getenv('USER')
+ password = ""
+ daemon_mode = False
+ if '-d' in options:
+ daemon_mode = True
+ if '--watch' in options:
+ watch_mode = True
+ else:
+ watch_mode = False
+ if '--hostname' in options:
+ hostname = options['--hostname']
+ if '--port' in options:
+ port = int(options['--port'])
+ if '--username' in options:
+ username = options['--username']
+ if '--password' in options:
+ password = options['--password']
+ else:
+ password = getpass.getpass('password: ')
+
+ server (hostname, username, password, '/tmp/mysock', daemon_mode)
+
+def random_sid ():
+ a=random.randint(0,65535)
+ b=random.randint(0,65535)
+ return '%04x%04x.sid' % (a,b)
+
+def parse_host_connect_string (hcs):
+ """This parses a host connection string in the form
+ username:password@hostname:port. All fields are options expcet hostname. A
+ dictionary is returned with all four keys. Keys that were not included are
+ set to empty strings ''. Note that if your password has the '@' character
+ then you must backslash escape it.
+ """
+ if '@' in hcs:
+ p = re.compile (r'(?P[^@:]*)(:?)(?P.*)(?!\\)@(?P[^:]*):?(?P[0-9]*)')
+ else:
+ p = re.compile (r'(?P)(?P)(?P[^:]*):?(?P[0-9]*)')
+ m = p.search (hcs)
+ d = m.groupdict()
+ d['password'] = d['password'].replace('\\@','@')
+ return d
+
+def pretty_box (s, rows=24, cols=80):
+ """This puts an ASCII text box around the given string.
+ """
+ top_bot = '+' + '-'*cols + '+\n'
+ return top_bot + '\n'.join(['|'+line+'|' for line in s.split('\n')]) + '\n' + top_bot
+
+def main ():
+ if os.getenv('REQUEST_METHOD') is None:
+ server_cli()
+ else:
+ client_cgi()
+
+# It's mostly HTML and Javascript from here on out.
+CGISH_HTML="""
+
+
+%(TITLE)s %(SID)s
+
+
+
+
+
+
+
+
+
+
+
+"""
+
+LOGIN_HTML="""
+
+Shell Login
+
+
+
+
+
+
+
+
+
+"""
+
+if __name__ == "__main__":
+ try:
+ main()
+ except Exception as e:
+ print(str(e))
+ tb_dump = traceback.format_exc()
+ print(str(tb_dump))
+
Index: third_party/Python/module/pexpect-4.6/examples/chess.py
===================================================================
--- third_party/Python/module/pexpect-4.6/examples/chess.py
+++ third_party/Python/module/pexpect-4.6/examples/chess.py
@@ -0,0 +1,148 @@
+#!/usr/bin/env python
+
+'''This demonstrates controlling a screen oriented application (curses).
+It starts two instances of gnuchess and then pits them against each other.
+
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+from __future__ import print_function
+
+from __future__ import absolute_import
+
+import pexpect
+import ANSI
+
+REGEX_MOVE = r'(?:[a-z]|\x1b\[C)(?:[0-9]|\x1b\[C)(?:[a-z]|\x1b\[C)(?:[0-9]|\x1b\[C)'
+REGEX_MOVE_PART = r'(?:[0-9]|\x1b\[C)(?:[a-z]|\x1b\[C)(?:[0-9]|\x1b\[C)'
+
+class Chess:
+
+ def __init__(self, engine = "/usr/local/bin/gnuchess -a -h 1"):
+ self.child = pexpect.spawn (engine)
+ self.term = ANSI.ANSI ()
+
+ self.child.expect ('Chess')
+ if self.child.after != 'Chess':
+ raise IOError('incompatible chess program')
+ self.term.process_list (self.before)
+ self.term.process_list (self.after)
+ self.last_computer_move = ''
+
+ def read_until_cursor (self, r,c):
+ while 1:
+ self.child.read(1, 60)
+ self.term.process (c)
+ if self.term.cur_r == r and self.term.cur_c == c:
+ return 1
+
+ def do_first_move (self, move):
+ self.child.expect ('Your move is')
+ self.child.sendline (move)
+ self.term.process_list (self.before)
+ self.term.process_list (self.after)
+ return move
+
+ def do_move (self, move):
+ self.read_until_cursor (19,60)
+ self.child.sendline (move)
+ return move
+
+ def get_first_computer_move (self):
+ self.child.expect ('My move is')
+ self.child.expect (REGEX_MOVE)
+ return self.child.after
+
+ def get_computer_move (self):
+ print('Here')
+ i = self.child.expect ([r'\[17;59H', r'\[17;58H'])
+ print(i)
+ if i == 0:
+ self.child.expect (REGEX_MOVE)
+ if len(self.child.after) < 4:
+ self.child.after = self.child.after + self.last_computer_move[3]
+ if i == 1:
+ self.child.expect (REGEX_MOVE_PART)
+ self.child.after = self.last_computer_move[0] + self.child.after
+ print('', self.child.after)
+ self.last_computer_move = self.child.after
+ return self.child.after
+
+ def switch (self):
+ self.child.sendline ('switch')
+
+ def set_depth (self, depth):
+ self.child.sendline ('depth')
+ self.child.expect ('depth=')
+ self.child.sendline ('%d' % depth)
+
+ def quit(self):
+ self.child.sendline ('quit')
+import sys
+print('Starting...')
+white = Chess()
+white.child.echo = 1
+white.child.expect ('Your move is')
+white.set_depth(2)
+white.switch()
+
+move_white = white.get_first_computer_move()
+print('first move white:', move_white)
+
+white.do_move ('e7e5')
+move_white = white.get_computer_move()
+print('move white:', move_white)
+white.do_move ('f8c5')
+move_white = white.get_computer_move()
+print('move white:', move_white)
+white.do_move ('b8a6')
+move_white = white.get_computer_move()
+print('move white:', move_white)
+
+sys.exit(1)
+
+
+
+black = Chess()
+white = Chess()
+white.child.expect ('Your move is')
+white.switch()
+
+move_white = white.get_first_computer_move()
+print('first move white:', move_white)
+
+black.do_first_move (move_white)
+move_black = black.get_first_computer_move()
+print('first move black:', move_black)
+
+white.do_move (move_black)
+
+done = 0
+while not done:
+ move_white = white.get_computer_move()
+ print('move white:', move_white)
+
+ black.do_move (move_white)
+ move_black = black.get_computer_move()
+ print('move black:', move_black)
+
+ white.do_move (move_black)
+ print('tail of loop')
+
+g.quit()
Index: third_party/Python/module/pexpect-4.6/examples/chess2.py
===================================================================
--- third_party/Python/module/pexpect-4.6/examples/chess2.py
+++ third_party/Python/module/pexpect-4.6/examples/chess2.py
@@ -0,0 +1,153 @@
+#!/usr/bin/env python
+
+'''This demonstrates controlling a screen oriented application (curses).
+It starts two instances of gnuchess and then pits them against each other.
+
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+from __future__ import print_function
+
+from __future__ import absolute_import
+
+import pexpect
+import ANSI
+import sys
+import time
+
+class Chess:
+
+ def __init__(self, engine = "/usr/local/bin/gnuchess -a -h 1"):
+ self.child = pexpect.spawn (engine)
+ self.term = ANSI.ANSI ()
+
+ #self.child.expect ('Chess')
+ #if self.child.after != 'Chess':
+ # raise IOError, 'incompatible chess program'
+ #self.term.process_list (self.child.before)
+ #self.term.process_list (self.child.after)
+
+ self.last_computer_move = ''
+
+ def read_until_cursor (self, r,c, e=0):
+ '''Eventually something like this should move into the screen class or
+ a subclass. Maybe a combination of pexpect and screen...
+ '''
+ fout = open ('log','a')
+ while self.term.cur_r != r or self.term.cur_c != c:
+ try:
+ k = self.child.read(1, 10)
+ except Exception as e:
+ print('EXCEPTION, (r,c):(%d,%d)\n' %(self.term.cur_r, self.term.cur_c))
+ sys.stdout.flush()
+ self.term.process (k)
+ fout.write ('(r,c):(%d,%d)\n' %(self.term.cur_r, self.term.cur_c))
+ fout.flush()
+ if e:
+ sys.stdout.write (k)
+ sys.stdout.flush()
+ if self.term.cur_r == r and self.term.cur_c == c:
+ fout.close()
+ return 1
+ print('DIDNT EVEN HIT.')
+ fout.close()
+ return 1
+
+ def expect_region (self):
+ '''This is another method that would be moved into the
+ screen class.
+ '''
+ pass
+ def do_scan (self):
+ fout = open ('log','a')
+ while 1:
+ c = self.child.read(1,10)
+ self.term.process (c)
+ fout.write ('(r,c):(%d,%d)\n' %(self.term.cur_r, self.term.cur_c))
+ fout.flush()
+ sys.stdout.write (c)
+ sys.stdout.flush()
+
+ def do_move (self, move, e = 0):
+ time.sleep(1)
+ self.read_until_cursor (19,60, e)
+ self.child.sendline (move)
+
+ def wait (self, color):
+ while 1:
+ r = self.term.get_region (14,50,14,60)[0]
+ r = r.strip()
+ if r == color:
+ return
+ time.sleep (1)
+
+ def parse_computer_move (self, s):
+ i = s.find ('is: ')
+ cm = s[i+3:i+9]
+ return cm
+ def get_computer_move (self, e = 0):
+ time.sleep(1)
+ self.read_until_cursor (19,60, e)
+ time.sleep(1)
+ r = self.term.get_region (17,50,17,62)[0]
+ cm = self.parse_computer_move (r)
+ return cm
+
+ def switch (self):
+ print('switching')
+ self.child.sendline ('switch')
+
+ def set_depth (self, depth):
+ self.child.sendline ('depth')
+ self.child.expect ('depth=')
+ self.child.sendline ('%d' % depth)
+
+ def quit(self):
+ self.child.sendline ('quit')
+
+def LOG (s):
+ print(s)
+ sys.stdout.flush ()
+ fout = open ('moves.log', 'a')
+ fout.write (s + '\n')
+ fout.close()
+
+print('Starting...')
+
+black = Chess()
+white = Chess()
+white.read_until_cursor (19,60,1)
+white.switch()
+
+done = 0
+while not done:
+ white.wait ('Black')
+ move_white = white.get_computer_move(1)
+ LOG ( 'move white:'+ move_white )
+
+ black.do_move (move_white)
+ black.wait ('White')
+ move_black = black.get_computer_move()
+ LOG ( 'move black:'+ move_black )
+
+ white.do_move (move_black, 1)
+
+g.quit()
+
+
Index: third_party/Python/module/pexpect-4.6/examples/chess3.py
===================================================================
--- third_party/Python/module/pexpect-4.6/examples/chess3.py
+++ third_party/Python/module/pexpect-4.6/examples/chess3.py
@@ -0,0 +1,157 @@
+#!/usr/bin/env python
+
+'''This demonstrates controlling a screen oriented application (curses).
+It starts two instances of gnuchess and then pits them against each other.
+
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+from __future__ import print_function
+
+from __future__ import absolute_import
+
+import pexpect
+import ANSI
+
+REGEX_MOVE = r'(?:[a-z]|\x1b\[C)(?:[0-9]|\x1b\[C)(?:[a-z]|\x1b\[C)(?:[0-9]|\x1b\[C)'
+REGEX_MOVE_PART = r'(?:[0-9]|\x1b\[C)(?:[a-z]|\x1b\[C)(?:[0-9]|\x1b\[C)'
+
+class Chess:
+
+ def __init__(self, engine = "/usr/local/bin/gnuchess -a -h 1"):
+ self.child = pexpect.spawn (engine)
+ self.term = ANSI.ANSI ()
+
+# self.child.expect ('Chess')
+ # if self.child.after != 'Chess':
+ # raise IOError, 'incompatible chess program'
+ # self.term.process_list (self.before)
+ # self.term.process_list (self.after)
+ self.last_computer_move = ''
+ def read_until_cursor (self, r,c):
+ fout = open ('log','a')
+ while 1:
+ k = self.child.read(1, 10)
+ self.term.process (k)
+ fout.write ('(r,c):(%d,%d)\n' %(self.term.cur_r, self.term.cur_c))
+ fout.flush()
+ if self.term.cur_r == r and self.term.cur_c == c:
+ fout.close()
+ return 1
+ sys.stdout.write (k)
+ sys.stdout.flush()
+
+ def do_scan (self):
+ fout = open ('log','a')
+ while 1:
+ c = self.child.read(1,10)
+ self.term.process (c)
+ fout.write ('(r,c):(%d,%d)\n' %(self.term.cur_r, self.term.cur_c))
+ fout.flush()
+ sys.stdout.write (c)
+ sys.stdout.flush()
+
+ def do_move (self, move):
+ self.read_until_cursor (19,60)
+ self.child.sendline (move)
+ return move
+
+ def get_computer_move (self):
+ print('Here')
+ i = self.child.expect ([r'\[17;59H', r'\[17;58H'])
+ print(i)
+ if i == 0:
+ self.child.expect (REGEX_MOVE)
+ if len(self.child.after) < 4:
+ self.child.after = self.child.after + self.last_computer_move[3]
+ if i == 1:
+ self.child.expect (REGEX_MOVE_PART)
+ self.child.after = self.last_computer_move[0] + self.child.after
+ print('', self.child.after)
+ self.last_computer_move = self.child.after
+ return self.child.after
+
+ def switch (self):
+ self.child.sendline ('switch')
+
+ def set_depth (self, depth):
+ self.child.sendline ('depth')
+ self.child.expect ('depth=')
+ self.child.sendline ('%d' % depth)
+
+ def quit(self):
+ self.child.sendline ('quit')
+import sys
+print('Starting...')
+white = Chess()
+white.do_move('b2b4')
+white.read_until_cursor (19,60)
+c1 = white.term.get_abs(17,58)
+c2 = white.term.get_abs(17,59)
+c3 = white.term.get_abs(17,60)
+c4 = white.term.get_abs(17,61)
+fout = open ('log','a')
+fout.write ('Computer:%s%s%s%s\n' %(c1,c2,c3,c4))
+fout.close()
+white.do_move('c2c4')
+white.read_until_cursor (19,60)
+c1 = white.term.get_abs(17,58)
+c2 = white.term.get_abs(17,59)
+c3 = white.term.get_abs(17,60)
+c4 = white.term.get_abs(17,61)
+fout = open ('log','a')
+fout.write ('Computer:%s%s%s%s\n' %(c1,c2,c3,c4))
+fout.close()
+white.do_scan ()
+
+#white.do_move ('b8a6')
+#move_white = white.get_computer_move()
+#print 'move white:', move_white
+
+sys.exit(1)
+
+
+
+black = Chess()
+white = Chess()
+white.child.expect ('Your move is')
+white.switch()
+
+move_white = white.get_first_computer_move()
+print('first move white:', move_white)
+
+black.do_first_move (move_white)
+move_black = black.get_first_computer_move()
+print('first move black:', move_black)
+
+white.do_move (move_black)
+
+done = 0
+while not done:
+ move_white = white.get_computer_move()
+ print('move white:', move_white)
+
+ black.do_move (move_white)
+ move_black = black.get_computer_move()
+ print('move black:', move_black)
+
+ white.do_move (move_black)
+ print('tail of loop')
+
+g.quit()
Index: third_party/Python/module/pexpect-4.6/examples/df.py
===================================================================
--- third_party/Python/module/pexpect-4.6/examples/df.py
+++ third_party/Python/module/pexpect-4.6/examples/df.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python
+
+'''This collects filesystem capacity info using the 'df' command. Tuples of
+filesystem name and percentage are stored in a list. A simple report is
+printed. Filesystems over 95% capacity are highlighted. Note that this does not
+parse filesystem names after the first space, so names with spaces in them will
+be truncated. This will produce ambiguous results for automount filesystems on
+Apple OSX.
+
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+from __future__ import print_function
+
+from __future__ import absolute_import
+
+import pexpect
+
+child = pexpect.spawn ('df')
+
+# parse 'df' output into a list.
+pattern = r"\n(\S+).*?([0-9]+)%"
+filesystem_list = []
+for dummy in range (0, 1000):
+ i = child.expect ([pattern, pexpect.EOF])
+ if i == 0:
+ filesystem_list.append (child.match.groups())
+ else:
+ break
+
+# Print report
+print()
+for m in filesystem_list:
+ s = "Filesystem %s is at %s%%" % (m[0], m[1])
+ # highlight filesystems over 95% capacity
+ if int(m[1]) > 95:
+ s = '! ' + s
+ else:
+ s = ' ' + s
+ print(s)
+
Index: third_party/Python/module/pexpect-4.6/examples/ftp.py
===================================================================
--- third_party/Python/module/pexpect-4.6/examples/ftp.py
+++ third_party/Python/module/pexpect-4.6/examples/ftp.py
@@ -0,0 +1,73 @@
+#!/usr/bin/env python
+
+'''This demonstrates an FTP "bookmark". This connects to an ftp site; does a
+few ftp stuff; and then gives the user interactive control over the session. In
+this case the "bookmark" is to a directory on the OpenBSD ftp server. It puts
+you in the i386 packages directory. You can easily modify this for other sites.
+
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+from __future__ import absolute_import
+from __future__ import print_function
+from __future__ import unicode_literals
+
+import pexpect
+import sys
+
+# Note that, for Python 3 compatibility reasons, we are using spawnu and
+# importing unicode_literals (above). spawnu accepts Unicode input and
+# unicode_literals makes all string literals in this script Unicode by default.
+child = pexpect.spawnu('ftp ftp.openbsd.org')
+
+child.expect('(?i)name .*: ')
+child.sendline('anonymous')
+child.expect('(?i)password')
+child.sendline('pexpect@sourceforge.net')
+child.expect('ftp> ')
+child.sendline('cd /pub/OpenBSD/3.7/packages/i386')
+child.expect('ftp> ')
+child.sendline('bin')
+child.expect('ftp> ')
+child.sendline('prompt')
+child.expect('ftp> ')
+child.sendline('pwd')
+child.expect('ftp> ')
+print("Escape character is '^]'.\n")
+sys.stdout.write (child.after)
+sys.stdout.flush()
+child.interact() # Escape character defaults to ^]
+# At this point this script blocks until the user presses the escape character
+# or until the child exits. The human user and the child should be talking
+# to each other now.
+
+# At this point the script is running again.
+print('Left interactve mode.')
+
+# The rest is not strictly necessary. This just demonstrates a few functions.
+# This makes sure the child is dead; although it would be killed when Python exits.
+if child.isalive():
+ child.sendline('bye') # Try to ask ftp child to exit.
+ child.close()
+# Print the final state of the child. Normally isalive() should be FALSE.
+if child.isalive():
+ print('Child did not exit gracefully.')
+else:
+ print('Child exited gracefully.')
+
Index: third_party/Python/module/pexpect-4.6/examples/hive.py
===================================================================
--- third_party/Python/module/pexpect-4.6/examples/hive.py
+++ third_party/Python/module/pexpect-4.6/examples/hive.py
@@ -0,0 +1,466 @@
+#!/usr/bin/env python
+
+'''hive -- Hive Shell
+
+This lets you ssh to a group of servers and control them as if they were one.
+Each command you enter is sent to each host in parallel. The response of each
+host is collected and printed. In normal synchronous mode Hive will wait for
+each host to return the shell command line prompt. The shell prompt is used to
+sync output.
+
+Example:
+
+ $ hive.py --sameuser --samepass host1.example.com host2.example.net
+ username: myusername
+ password:
+ connecting to host1.example.com - OK
+ connecting to host2.example.net - OK
+ targeting hosts: 192.168.1.104 192.168.1.107
+ CMD (? for help) > uptime
+ =======================================================================
+ host1.example.com
+ -----------------------------------------------------------------------
+ uptime
+ 23:49:55 up 74 days, 5:14, 2 users, load average: 0.15, 0.05, 0.01
+ =======================================================================
+ host2.example.net
+ -----------------------------------------------------------------------
+ uptime
+ 23:53:02 up 1 day, 13:36, 2 users, load average: 0.50, 0.40, 0.46
+ =======================================================================
+
+Other Usage Examples:
+
+1. You will be asked for your username and password for each host.
+
+ hive.py host1 host2 host3 ... hostN
+
+2. You will be asked once for your username and password.
+ This will be used for each host.
+
+ hive.py --sameuser --samepass host1 host2 host3 ... hostN
+
+3. Give a username and password on the command-line:
+
+ hive.py user1:pass2@host1 user2:pass2@host2 ... userN:passN@hostN
+
+You can use an extended host notation to specify username, password, and host
+instead of entering auth information interactively. Where you would enter a
+host name use this format:
+
+ username:password@host
+
+This assumes that ':' is not part of the password. If your password contains a
+':' then you can use '\\:' to indicate a ':' and '\\\\' to indicate a single
+'\\'. Remember that this information will appear in the process listing. Anyone
+on your machine can see this auth information. This is not secure.
+
+This is a crude script that begs to be multithreaded. But it serves its
+purpose.
+
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+from __future__ import print_function
+
+from __future__ import absolute_import
+
+# TODO add feature to support username:password@host combination
+# TODO add feature to log each host output in separate file
+
+import sys
+import os
+import re
+import optparse
+import time
+import getpass
+import readline
+import atexit
+try:
+ import pexpect
+ import pxssh
+except ImportError:
+ sys.stderr.write("You do not have 'pexpect' installed.\n")
+ sys.stderr.write("On Ubuntu you need the 'python-pexpect' package.\n")
+ sys.stderr.write(" aptitude -y install python-pexpect\n")
+ exit(1)
+
+
+try:
+ raw_input
+except NameError:
+ raw_input = input
+
+
+histfile = os.path.join(os.environ["HOME"], ".hive_history")
+try:
+ readline.read_history_file(histfile)
+except IOError:
+ pass
+atexit.register(readline.write_history_file, histfile)
+
+CMD_HELP='''Hive commands are preceded by a colon : (just think of vi).
+
+:target name1 name2 name3 ...
+
+ set list of hosts to target commands
+
+:target all
+
+ reset list of hosts to target all hosts in the hive.
+
+:to name command
+
+ send a command line to the named host. This is similar to :target, but
+ sends only one command and does not change the list of targets for future
+ commands.
+
+:sync
+
+ set mode to wait for shell prompts after commands are run. This is the
+ default. When Hive first logs into a host it sets a special shell prompt
+ pattern that it can later look for to synchronize output of the hosts. If
+ you 'su' to another user then it can upset the synchronization. If you need
+ to run something like 'su' then use the following pattern:
+
+ CMD (? for help) > :async
+ CMD (? for help) > sudo su - root
+ CMD (? for help) > :prompt
+ CMD (? for help) > :sync
+
+:async
+
+ set mode to not expect command line prompts (see :sync). Afterwards
+ commands are send to target hosts, but their responses are not read back
+ until :sync is run. This is useful to run before commands that will not
+ return with the special shell prompt pattern that Hive uses to synchronize.
+
+:refresh
+
+ refresh the display. This shows the last few lines of output from all hosts.
+ This is similar to resync, but does not expect the promt. This is useful
+ for seeing what hosts are doing during long running commands.
+
+:resync
+
+ This is similar to :sync, but it does not change the mode. It looks for the
+ prompt and thus consumes all input from all targeted hosts.
+
+:prompt
+
+ force each host to reset command line prompt to the special pattern used to
+ synchronize all the hosts. This is useful if you 'su' to a different user
+ where Hive would not know the prompt to match.
+
+:send my text
+
+ This will send the 'my text' wihtout a line feed to the targeted hosts.
+ This output of the hosts is not automatically synchronized.
+
+:control X
+
+ This will send the given control character to the targeted hosts.
+ For example, ":control c" will send ASCII 3.
+
+:exit
+
+ This will exit the hive shell.
+
+'''
+
+def login (args, cli_username=None, cli_password=None):
+
+ # I have to keep a separate list of host names because Python dicts are not ordered.
+ # I want to keep the same order as in the args list.
+ host_names = []
+ hive_connect_info = {}
+ hive = {}
+ # build up the list of connection information (hostname, username, password, port)
+ for host_connect_string in args:
+ hcd = parse_host_connect_string (host_connect_string)
+ hostname = hcd['hostname']
+ port = hcd['port']
+ if port == '':
+ port = None
+ if len(hcd['username']) > 0:
+ username = hcd['username']
+ elif cli_username is not None:
+ username = cli_username
+ else:
+ username = raw_input('%s username: ' % hostname)
+ if len(hcd['password']) > 0:
+ password = hcd['password']
+ elif cli_password is not None:
+ password = cli_password
+ else:
+ password = getpass.getpass('%s password: ' % hostname)
+ host_names.append(hostname)
+ hive_connect_info[hostname] = (hostname, username, password, port)
+ # build up the list of hive connections using the connection information.
+ for hostname in host_names:
+ print('connecting to', hostname)
+ try:
+ fout = file("log_"+hostname, "w")
+ hive[hostname] = pxssh.pxssh()
+ # Disable host key checking.
+ hive[hostname].SSH_OPTS = (hive[hostname].SSH_OPTS
+ + " -o 'StrictHostKeyChecking=no'"
+ + " -o 'UserKnownHostsFile /dev/null' ")
+ hive[hostname].force_password = True
+ hive[hostname].login(*hive_connect_info[hostname])
+ print(hive[hostname].before)
+ hive[hostname].logfile = fout
+ print('- OK')
+ except Exception as e:
+ print('- ERROR', end=' ')
+ print(str(e))
+ print('Skipping', hostname)
+ hive[hostname] = None
+ return host_names, hive
+
+def main ():
+
+ global options, args, CMD_HELP
+
+ rows = 24
+ cols = 80
+
+ if options.sameuser:
+ cli_username = raw_input('username: ')
+ else:
+ cli_username = None
+
+ if options.samepass:
+ cli_password = getpass.getpass('password: ')
+ else:
+ cli_password = None
+
+ host_names, hive = login(args, cli_username, cli_password)
+
+ synchronous_mode = True
+ target_hostnames = host_names[:]
+ print('targeting hosts:', ' '.join(target_hostnames))
+ while True:
+ cmd = raw_input('CMD (? for help) > ')
+ cmd = cmd.strip()
+ if cmd=='?' or cmd==':help' or cmd==':h':
+ print(CMD_HELP)
+ continue
+ elif cmd==':refresh':
+ refresh (hive, target_hostnames, timeout=0.5)
+ for hostname in target_hostnames:
+ print('/' + '=' * (cols - 2))
+ print('| ' + hostname)
+ print('\\' + '-' * (cols - 2))
+ if hive[hostname] is None:
+ print('# DEAD: %s' % hostname)
+ else:
+ print(hive[hostname].before)
+ print('#' * 79)
+ continue
+ elif cmd==':resync':
+ resync (hive, target_hostnames, timeout=0.5)
+ for hostname in target_hostnames:
+ print('/' + '=' * (cols - 2))
+ print('| ' + hostname)
+ print('\\' + '-' * (cols - 2))
+ if hive[hostname] is None:
+ print('# DEAD: %s' % hostname)
+ else:
+ print(hive[hostname].before)
+ print('#' * 79)
+ continue
+ elif cmd==':sync':
+ synchronous_mode = True
+ resync (hive, target_hostnames, timeout=0.5)
+ continue
+ elif cmd==':async':
+ synchronous_mode = False
+ continue
+ elif cmd==':prompt':
+ for hostname in target_hostnames:
+ try:
+ if hive[hostname] is not None:
+ hive[hostname].set_unique_prompt()
+ except Exception as e:
+ print("Had trouble communicating with %s, so removing it from the target list." % hostname)
+ print(str(e))
+ hive[hostname] = None
+ continue
+ elif cmd[:5] == ':send':
+ cmd, txt = cmd.split(None,1)
+ for hostname in target_hostnames:
+ try:
+ if hive[hostname] is not None:
+ hive[hostname].send(txt)
+ except Exception as e:
+ print("Had trouble communicating with %s, so removing it from the target list." % hostname)
+ print(str(e))
+ hive[hostname] = None
+ continue
+ elif cmd[:3] == ':to':
+ cmd, hostname, txt = cmd.split(None,2)
+ print('/' + '=' * (cols - 2))
+ print('| ' + hostname)
+ print('\\' + '-' * (cols - 2))
+ if hive[hostname] is None:
+ print('# DEAD: %s' % hostname)
+ continue
+ try:
+ hive[hostname].sendline (txt)
+ hive[hostname].prompt(timeout=2)
+ print(hive[hostname].before)
+ except Exception as e:
+ print("Had trouble communicating with %s, so removing it from the target list." % hostname)
+ print(str(e))
+ hive[hostname] = None
+ continue
+ elif cmd[:7] == ':expect':
+ cmd, pattern = cmd.split(None,1)
+ print('looking for', pattern)
+ try:
+ for hostname in target_hostnames:
+ if hive[hostname] is not None:
+ hive[hostname].expect(pattern)
+ print(hive[hostname].before)
+ except Exception as e:
+ print("Had trouble communicating with %s, so removing it from the target list." % hostname)
+ print(str(e))
+ hive[hostname] = None
+ continue
+ elif cmd[:7] == ':target':
+ target_hostnames = cmd.split()[1:]
+ if len(target_hostnames) == 0 or target_hostnames[0] == all:
+ target_hostnames = host_names[:]
+ print('targeting hosts:', ' '.join(target_hostnames))
+ continue
+ elif cmd == ':exit' or cmd == ':q' or cmd == ':quit':
+ break
+ elif cmd[:8] == ':control' or cmd[:5] == ':ctrl' :
+ cmd, c = cmd.split(None,1)
+ if ord(c)-96 < 0 or ord(c)-96 > 255:
+ print('/' + '=' * (cols - 2))
+ print('| Invalid character. Must be [a-zA-Z], @, [, ], \\, ^, _, or ?')
+ print('\\' + '-' * (cols - 2))
+ continue
+ for hostname in target_hostnames:
+ try:
+ if hive[hostname] is not None:
+ hive[hostname].sendcontrol(c)
+ except Exception as e:
+ print("Had trouble communicating with %s, so removing it from the target list." % hostname)
+ print(str(e))
+ hive[hostname] = None
+ continue
+ elif cmd == ':esc':
+ for hostname in target_hostnames:
+ if hive[hostname] is not None:
+ hive[hostname].send(chr(27))
+ continue
+ #
+ # Run the command on all targets in parallel
+ #
+ for hostname in target_hostnames:
+ try:
+ if hive[hostname] is not None:
+ hive[hostname].sendline (cmd)
+ except Exception as e:
+ print("Had trouble communicating with %s, so removing it from the target list." % hostname)
+ print(str(e))
+ hive[hostname] = None
+
+ #
+ # print the response for each targeted host.
+ #
+ if synchronous_mode:
+ for hostname in target_hostnames:
+ try:
+ print('/' + '=' * (cols - 2))
+ print('| ' + hostname)
+ print('\\' + '-' * (cols - 2))
+ if hive[hostname] is None:
+ print('# DEAD: %s' % hostname)
+ else:
+ hive[hostname].prompt(timeout=2)
+ print(hive[hostname].before)
+ except Exception as e:
+ print("Had trouble communicating with %s, so removing it from the target list." % hostname)
+ print(str(e))
+ hive[hostname] = None
+ print('#' * 79)
+
+def refresh (hive, hive_names, timeout=0.5):
+
+ '''This waits for the TIMEOUT on each host.
+ '''
+
+ # TODO This is ideal for threading.
+ for hostname in hive_names:
+ if hive[hostname] is not None:
+ hive[hostname].expect([pexpect.TIMEOUT,pexpect.EOF],timeout=timeout)
+
+def resync (hive, hive_names, timeout=2, max_attempts=5):
+
+ '''This waits for the shell prompt for each host in an effort to try to get
+ them all to the same state. The timeout is set low so that hosts that are
+ already at the prompt will not slow things down too much. If a prompt match
+ is made for a hosts then keep asking until it stops matching. This is a
+ best effort to consume all input if it printed more than one prompt. It's
+ kind of kludgy. Note that this will always introduce a delay equal to the
+ timeout for each machine. So for 10 machines with a 2 second delay you will
+ get AT LEAST a 20 second delay if not more. '''
+
+ # TODO This is ideal for threading.
+ for hostname in hive_names:
+ if hive[hostname] is not None:
+ for attempts in range(0, max_attempts):
+ if not hive[hostname].prompt(timeout=timeout):
+ break
+
+def parse_host_connect_string (hcs):
+
+ '''This parses a host connection string in the form
+ username:password@hostname:port. All fields are options expcet hostname. A
+ dictionary is returned with all four keys. Keys that were not included are
+ set to empty strings ''. Note that if your password has the '@' character
+ then you must backslash escape it. '''
+
+ if '@' in hcs:
+ p = re.compile (r'(?P[^@:]*)(:?)(?P.*)(?!\\)@(?P[^:]*):?(?P[0-9]*)')
+ else:
+ p = re.compile (r'(?P)(?P)(?P[^:]*):?(?P[0-9]*)')
+ m = p.search (hcs)
+ d = m.groupdict()
+ d['password'] = d['password'].replace('\\@','@')
+ return d
+
+if __name__ == '__main__':
+ start_time = time.time()
+ parser = optparse.OptionParser(formatter=optparse.TitledHelpFormatter(), usage=globals()['__doc__'], version='$Id: hive.py 533 2012-10-20 02:19:33Z noah $',conflict_handler="resolve")
+ parser.add_option ('-v', '--verbose', action='store_true', default=False, help='verbose output')
+ parser.add_option ('--samepass', action='store_true', default=False, help='Use same password for each login.')
+ parser.add_option ('--sameuser', action='store_true', default=False, help='Use same username for each login.')
+ (options, args) = parser.parse_args()
+ if len(args) < 1:
+ parser.error ('missing argument')
+ if options.verbose: print(time.asctime())
+ main()
+ if options.verbose: print(time.asctime())
+ if options.verbose: print('TOTAL TIME IN MINUTES:', end=' ')
+ if options.verbose: print((time.time() - start_time) / 60.0)
Index: third_party/Python/module/pexpect-4.6/examples/monitor.py
===================================================================
--- third_party/Python/module/pexpect-4.6/examples/monitor.py
+++ third_party/Python/module/pexpect-4.6/examples/monitor.py
@@ -0,0 +1,229 @@
+#!/usr/bin/env python
+
+''' This runs a sequence of commands on a remote host using SSH. It runs a
+simple system checks such as uptime and free to monitor the state of the remote
+host.
+
+./monitor.py [-s server_hostname] [-u username] [-p password]
+ -s : hostname of the remote server to login to.
+ -u : username to user for login.
+ -p : Password to user for login.
+
+Example:
+ This will print information about the given host:
+ ./monitor.py -s www.example.com -u mylogin -p mypassword
+
+It works like this:
+ Login via SSH (This is the hardest part).
+ Run and parse 'uptime'.
+ Run 'iostat'.
+ Run 'vmstat'.
+ Run 'netstat'
+ Run 'free'.
+ Exit the remote host.
+
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+from __future__ import print_function
+
+from __future__ import absolute_import
+
+import os, sys, re, getopt, getpass
+import pexpect
+
+
+try:
+ raw_input
+except NameError:
+ raw_input = input
+
+
+#
+# Some constants.
+#
+COMMAND_PROMPT = '[#$] ' ### This is way too simple for industrial use -- we will change is ASAP.
+TERMINAL_PROMPT = r'(?i)terminal type\?'
+TERMINAL_TYPE = 'vt100'
+# This is the prompt we get if SSH does not have the remote host's public key stored in the cache.
+SSH_NEWKEY = '(?i)are you sure you want to continue connecting'
+
+def exit_with_usage():
+
+ print(globals()['__doc__'])
+ os._exit(1)
+
+def main():
+
+ global COMMAND_PROMPT, TERMINAL_PROMPT, TERMINAL_TYPE, SSH_NEWKEY
+ ######################################################################
+ ## Parse the options, arguments, get ready, etc.
+ ######################################################################
+ try:
+ optlist, args = getopt.getopt(sys.argv[1:], 'h?s:u:p:', ['help','h','?'])
+ except Exception as e:
+ print(str(e))
+ exit_with_usage()
+ options = dict(optlist)
+ if len(args) > 1:
+ exit_with_usage()
+
+ if [elem for elem in options if elem in ['-h','--h','-?','--?','--help']]:
+ print("Help:")
+ exit_with_usage()
+
+ if '-s' in options:
+ host = options['-s']
+ else:
+ host = raw_input('hostname: ')
+ if '-u' in options:
+ user = options['-u']
+ else:
+ user = raw_input('username: ')
+ if '-p' in options:
+ password = options['-p']
+ else:
+ password = getpass.getpass('password: ')
+
+ #
+ # Login via SSH
+ #
+ child = pexpect.spawn('ssh -l %s %s'%(user, host))
+ i = child.expect([pexpect.TIMEOUT, SSH_NEWKEY, COMMAND_PROMPT, '(?i)password'])
+ if i == 0: # Timeout
+ print('ERROR! could not login with SSH. Here is what SSH said:')
+ print(child.before, child.after)
+ print(str(child))
+ sys.exit (1)
+ if i == 1: # In this case SSH does not have the public key cached.
+ child.sendline ('yes')
+ child.expect ('(?i)password')
+ if i == 2:
+ # This may happen if a public key was setup to automatically login.
+ # But beware, the COMMAND_PROMPT at this point is very trivial and
+ # could be fooled by some output in the MOTD or login message.
+ pass
+ if i == 3:
+ child.sendline(password)
+ # Now we are either at the command prompt or
+ # the login process is asking for our terminal type.
+ i = child.expect ([COMMAND_PROMPT, TERMINAL_PROMPT])
+ if i == 1:
+ child.sendline (TERMINAL_TYPE)
+ child.expect (COMMAND_PROMPT)
+ #
+ # Set command prompt to something more unique.
+ #
+ COMMAND_PROMPT = r"\[PEXPECT\]\$ "
+ child.sendline (r"PS1='[PEXPECT]\$ '") # In case of sh-style
+ i = child.expect ([pexpect.TIMEOUT, COMMAND_PROMPT], timeout=10)
+ if i == 0:
+ print("# Couldn't set sh-style prompt -- trying csh-style.")
+ child.sendline (r"set prompt='[PEXPECT]\$ '")
+ i = child.expect ([pexpect.TIMEOUT, COMMAND_PROMPT], timeout=10)
+ if i == 0:
+ print("Failed to set command prompt using sh or csh style.")
+ print("Response was:")
+ print(child.before)
+ sys.exit (1)
+
+ # Now we should be at the command prompt and ready to run some commands.
+ print('---------------------------------------')
+ print('Report of commands run on remote host.')
+ print('---------------------------------------')
+
+ # Run uname.
+ child.sendline ('uname -a')
+ child.expect (COMMAND_PROMPT)
+ print(child.before)
+ if 'linux' in child.before.lower():
+ LINUX_MODE = 1
+ else:
+ LINUX_MODE = 0
+
+ # Run and parse 'uptime'.
+ child.sendline ('uptime')
+ child.expect(r'up\s+(.*?),\s+([0-9]+) users?,\s+load averages?: ([0-9]+\.[0-9][0-9]),?\s+([0-9]+\.[0-9][0-9]),?\s+([0-9]+\.[0-9][0-9])')
+ duration, users, av1, av5, av15 = child.match.groups()
+ days = '0'
+ hours = '0'
+ mins = '0'
+ if 'day' in duration:
+ child.match = re.search(r'([0-9]+)\s+day',duration)
+ days = str(int(child.match.group(1)))
+ if ':' in duration:
+ child.match = re.search('([0-9]+):([0-9]+)',duration)
+ hours = str(int(child.match.group(1)))
+ mins = str(int(child.match.group(2)))
+ if 'min' in duration:
+ child.match = re.search(r'([0-9]+)\s+min',duration)
+ mins = str(int(child.match.group(1)))
+ print()
+ print('Uptime: %s days, %s users, %s (1 min), %s (5 min), %s (15 min)' % (
+ duration, users, av1, av5, av15))
+ child.expect (COMMAND_PROMPT)
+
+ # Run iostat.
+ child.sendline ('iostat')
+ child.expect (COMMAND_PROMPT)
+ print(child.before)
+
+ # Run vmstat.
+ child.sendline ('vmstat')
+ child.expect (COMMAND_PROMPT)
+ print(child.before)
+
+ # Run free.
+ if LINUX_MODE:
+ child.sendline ('free') # Linux systems only.
+ child.expect (COMMAND_PROMPT)
+ print(child.before)
+
+ # Run df.
+ child.sendline ('df')
+ child.expect (COMMAND_PROMPT)
+ print(child.before)
+
+ # Run lsof.
+ child.sendline ('lsof')
+ child.expect (COMMAND_PROMPT)
+ print(child.before)
+
+# # Run netstat
+# child.sendline ('netstat')
+# child.expect (COMMAND_PROMPT)
+# print child.before
+
+# # Run MySQL show status.
+# child.sendline ('mysql -p -e "SHOW STATUS;"')
+# child.expect (PASSWORD_PROMPT_MYSQL)
+# child.sendline (password_mysql)
+# child.expect (COMMAND_PROMPT)
+# print
+# print child.before
+
+ # Now exit the remote host.
+ child.sendline ('exit')
+ index = child.expect([pexpect.EOF, "(?i)there are stopped jobs"])
+ if index==1:
+ child.sendline("exit")
+ child.expect(EOF)
+
+if __name__ == "__main__":
+ main()
Index: third_party/Python/module/pexpect-4.6/examples/passmass.py
===================================================================
--- third_party/Python/module/pexpect-4.6/examples/passmass.py
+++ third_party/Python/module/pexpect-4.6/examples/passmass.py
@@ -0,0 +1,116 @@
+#!/usr/bin/env python
+
+'''Change passwords on the named machines. passmass host1 host2 host3 . . .
+Note that login shell prompt on remote machine must end in # or $.
+
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+from __future__ import print_function
+
+from __future__ import absolute_import
+
+import pexpect
+import sys, getpass
+
+
+try:
+ raw_input
+except NameError:
+ raw_input = input
+
+
+USAGE = '''passmass host1 host2 host3 . . .'''
+COMMAND_PROMPT = '[$#] '
+TERMINAL_PROMPT = r'Terminal type\?'
+TERMINAL_TYPE = 'vt100'
+SSH_NEWKEY = r'Are you sure you want to continue connecting \(yes/no\)\?'
+
+def login(host, user, password):
+
+ child = pexpect.spawn('ssh -l %s %s'%(user, host))
+ fout = file ("LOG.TXT","wb")
+ child.logfile_read = fout #use child.logfile to also log writes (passwords!)
+
+ i = child.expect([pexpect.TIMEOUT, SSH_NEWKEY, '[Pp]assword: '])
+ if i == 0: # Timeout
+ print('ERROR!')
+ print('SSH could not login. Here is what SSH said:')
+ print(child.before, child.after)
+ sys.exit (1)
+ if i == 1: # SSH does not have the public key. Just accept it.
+ child.sendline ('yes')
+ child.expect ('[Pp]assword: ')
+ child.sendline(password)
+ # Now we are either at the command prompt or
+ # the login process is asking for our terminal type.
+ i = child.expect (['Permission denied', TERMINAL_PROMPT, COMMAND_PROMPT])
+ if i == 0:
+ print('Permission denied on host:', host)
+ sys.exit (1)
+ if i == 1:
+ child.sendline (TERMINAL_TYPE)
+ child.expect (COMMAND_PROMPT)
+ return child
+
+# (current) UNIX password:
+def change_password(child, user, oldpassword, newpassword):
+
+ child.sendline('passwd')
+ i = child.expect(['[Oo]ld [Pp]assword', '.current.*password', '[Nn]ew [Pp]assword'])
+ # Root does not require old password, so it gets to bypass the next step.
+ if i == 0 or i == 1:
+ child.sendline(oldpassword)
+ child.expect('[Nn]ew [Pp]assword')
+ child.sendline(newpassword)
+ i = child.expect(['[Nn]ew [Pp]assword', '[Rr]etype', '[Rr]e-enter'])
+ if i == 0:
+ print('Host did not like new password. Here is what it said...')
+ print(child.before)
+ child.send (chr(3)) # Ctrl-C
+ child.sendline('') # This should tell remote passwd command to quit.
+ return
+ child.sendline(newpassword)
+
+def main():
+
+ if len(sys.argv) <= 1:
+ print(USAGE)
+ return 1
+
+ user = raw_input('Username: ')
+ password = getpass.getpass('Current Password: ')
+ newpassword = getpass.getpass('New Password: ')
+ newpasswordconfirm = getpass.getpass('Confirm New Password: ')
+ if newpassword != newpasswordconfirm:
+ print('New Passwords do not match.')
+ return 1
+
+ for host in sys.argv[1:]:
+ child = login(host, user, password)
+ if child == None:
+ print('Could not login to host:', host)
+ continue
+ print('Changing password on host:', host)
+ change_password(child, user, password, newpassword)
+ child.expect(COMMAND_PROMPT)
+ child.sendline('exit')
+
+if __name__ == '__main__':
+ main()
Index: third_party/Python/module/pexpect-4.6/examples/python.py
===================================================================
--- third_party/Python/module/pexpect-4.6/examples/python.py
+++ third_party/Python/module/pexpect-4.6/examples/python.py
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+
+'''This starts the python interpreter; captures the startup message; then gives
+the user interactive control over the session. Why? For fun...
+
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+from __future__ import absolute_import
+from __future__ import print_function
+from __future__ import unicode_literals
+
+import pexpect
+
+# Don't do this unless you like being John Malkovich
+# c = pexpect.spawnu('/usr/bin/env python ./python.py')
+
+# Note that, for Python 3 compatibility reasons, we are using spawnu and
+# importing unicode_literals (above). spawnu accepts Unicode input and
+# unicode_literals makes all string literals in this script Unicode by default.
+c = pexpect.spawnu('/usr/bin/env python')
+
+c.expect('>>>')
+print('And now for something completely different...')
+print(''.join(reversed((c.before))))
+print('Yes, it\'s python, but it\'s backwards.')
+print()
+print('Escape character is \'^]\'.')
+print(c.after, end=' ')
+c.interact()
+c.kill(1)
+print('is alive:', c.isalive())
+
Index: third_party/Python/module/pexpect-4.6/examples/script.py
===================================================================
--- third_party/Python/module/pexpect-4.6/examples/script.py
+++ third_party/Python/module/pexpect-4.6/examples/script.py
@@ -0,0 +1,114 @@
+#!/usr/bin/env python
+
+'''This spawns a sub-shell (bash) and gives the user interactive control. The
+entire shell session is logged to a file called script.log. This behaves much
+like the classic BSD command 'script'.
+
+./script.py [-a] [-c command] {logfilename}
+
+ logfilename : This is the name of the log file. Default is script.log.
+ -a : Append to log file. Default is to overwrite log file.
+ -c : spawn command. Default is to spawn the sh shell.
+
+Example:
+
+ This will start a bash shell and append to the log named my_session.log:
+
+ ./script.py -a -c bash my_session.log
+
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+from __future__ import print_function
+
+from __future__ import absolute_import
+
+import os, sys, time, getopt
+import signal, fcntl, termios, struct
+import pexpect
+
+global_pexpect_instance = None # Used by signal handler
+
+def exit_with_usage():
+
+ print(globals()['__doc__'])
+ os._exit(1)
+
+def main():
+
+ ######################################################################
+ # Parse the options, arguments, get ready, etc.
+ ######################################################################
+ try:
+ optlist, args = getopt.getopt(sys.argv[1:], 'h?ac:', ['help','h','?'])
+ except Exception as e:
+ print(str(e))
+ exit_with_usage()
+ options = dict(optlist)
+ if len(args) > 1:
+ exit_with_usage()
+
+ if [elem for elem in options if elem in ['-h','--h','-?','--?','--help']]:
+ print("Help:")
+ exit_with_usage()
+
+ if len(args) == 1:
+ script_filename = args[0]
+ else:
+ script_filename = "script.log"
+ if '-a' in options:
+ fout = open(script_filename, "ab")
+ else:
+ fout = open(script_filename, "wb")
+ if '-c' in options:
+ command = options['-c']
+ else:
+ command = "sh"
+
+ # Begin log with date/time in the form CCCCyymm.hhmmss
+ fout.write ('# %4d%02d%02d.%02d%02d%02d \n' % time.localtime()[:-3])
+
+ ######################################################################
+ # Start the interactive session
+ ######################################################################
+ p = pexpect.spawn(command)
+ p.logfile = fout
+ global global_pexpect_instance
+ global_pexpect_instance = p
+ signal.signal(signal.SIGWINCH, sigwinch_passthrough)
+
+ print("Script recording started. Type ^] (ASCII 29) to escape from the script shell.")
+ p.interact(chr(29))
+ fout.close()
+ return 0
+
+def sigwinch_passthrough (sig, data):
+
+ # Check for buggy platforms (see pexpect.setwinsize()).
+ if 'TIOCGWINSZ' in dir(termios):
+ TIOCGWINSZ = termios.TIOCGWINSZ
+ else:
+ TIOCGWINSZ = 1074295912 # assume
+ s = struct.pack ("HHHH", 0, 0, 0, 0)
+ a = struct.unpack ('HHHH', fcntl.ioctl(sys.stdout.fileno(), TIOCGWINSZ , s))
+ global global_pexpect_instance
+ global_pexpect_instance.setwinsize(a[0],a[1])
+
+if __name__ == "__main__":
+ main()
Index: third_party/Python/module/pexpect-4.6/examples/ssh_tunnel.py
===================================================================
--- third_party/Python/module/pexpect-4.6/examples/ssh_tunnel.py
+++ third_party/Python/module/pexpect-4.6/examples/ssh_tunnel.py
@@ -0,0 +1,105 @@
+#!/usr/bin/env python
+
+'''This starts an SSH tunnel to a given host. If the SSH process ever dies then
+this script will detect that and restart it. I use this under Cygwin to keep
+open encrypted tunnels to port 25 (SMTP), port 143 (IMAP4), and port 110
+(POP3). I set my mail client to talk to localhost and I keep this script
+running in the background.
+
+Note that this is a rather stupid script at the moment because it just looks to
+see if any ssh process is running. It should really make sure that our specific
+ssh process is running. The problem is that ssh is missing a very useful
+feature. It has no way to report the process id of the background daemon that
+it creates with the -f command. This would be a really useful script if I could
+figure a way around this problem.
+
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+from __future__ import print_function
+
+from __future__ import absolute_import
+
+import pexpect
+import getpass
+import time
+
+
+try:
+ raw_input
+except NameError:
+ raw_input = input
+
+
+# SMTP:25 IMAP4:143 POP3:110
+tunnel_command = 'ssh -C -N -f -L 25:127.0.0.1:25 -L 143:127.0.0.1:143 -L 110:127.0.0.1:110 %(user)@%(host)'
+host = raw_input('Hostname: ')
+user = raw_input('Username: ')
+X = getpass.getpass('Password: ')
+
+def get_process_info ():
+
+ # This seems to work on both Linux and BSD, but should otherwise be considered highly UNportable.
+
+ ps = pexpect.run ('ps ax -O ppid')
+ pass
+
+def start_tunnel ():
+
+ try:
+ ssh_tunnel = pexpect.spawn (tunnel_command % globals())
+ ssh_tunnel.expect ('password:')
+ time.sleep (0.1)
+ ssh_tunnel.sendline (X)
+ time.sleep (60) # Cygwin is slow to update process status.
+ ssh_tunnel.expect (pexpect.EOF)
+
+ except Exception as e:
+ print(str(e))
+
+def main ():
+
+ while True:
+ ps = pexpect.spawn ('ps')
+ time.sleep (1)
+ index = ps.expect (['/usr/bin/ssh', pexpect.EOF, pexpect.TIMEOUT])
+ if index == 2:
+ print('TIMEOUT in ps command...')
+ print(str(ps))
+ time.sleep (13)
+ if index == 1:
+ print(time.asctime(), end=' ')
+ print('restarting tunnel')
+ start_tunnel ()
+ time.sleep (11)
+ print('tunnel OK')
+ else:
+ # print 'tunnel OK'
+ time.sleep (7)
+
+if __name__ == '__main__':
+
+ main ()
+
+# This was for older SSH versions that didn't have -f option
+#tunnel_command = 'ssh -C -n -L 25:%(host)s:25 -L 110:%(host)s:110 %(user)s@%(host)s -f nothing.sh'
+#nothing_script = '''#!/bin/sh
+#while true; do sleep 53; done
+#'''
+
Index: third_party/Python/module/pexpect-4.6/examples/table_test.html
===================================================================
--- third_party/Python/module/pexpect-4.6/examples/table_test.html
+++ third_party/Python/module/pexpect-4.6/examples/table_test.html
@@ -0,0 +1,106 @@
+
+
+
+TEST
+
+
+
+
+
+
+
+
+
/
+
h
+
o
+
m
+
e
+
/
+
n
+
o
+
a
+
h
+
/
+
+
+
+
+
+
+
\ No newline at end of file
Index: third_party/Python/module/pexpect-4.6/examples/topip.py
===================================================================
--- third_party/Python/module/pexpect-4.6/examples/topip.py
+++ third_party/Python/module/pexpect-4.6/examples/topip.py
@@ -0,0 +1,299 @@
+#!/usr/bin/env python
+
+''' This runs netstat on a local or remote server. It calculates some simple
+statistical information on the number of external inet connections. It groups
+by IP address. This can be used to detect if one IP address is taking up an
+excessive number of connections. It can also send an email alert if a given IP
+address exceeds a threshold between runs of the script. This script can be used
+as a drop-in Munin plugin or it can be used stand-alone from cron. I used this
+on a busy web server that would sometimes get hit with denial of service
+attacks. This made it easy to see if a script was opening many multiple
+connections. A typical browser would open fewer than 10 connections at once.
+A script might open over 100 simultaneous connections.
+
+./topip.py [-s server_hostname] [-u username] [-p password]
+ {-a from_addr,to_addr} {-n N} {-v} {--ipv6}
+
+ -s : hostname of the remote server to login to.
+ -u : username to user for login.
+ -p : password to user for login.
+ -n : print stddev for the the number of the top 'N' ipaddresses.
+ -v : verbose - print stats and list of top ipaddresses.
+ -a : send alert if stddev goes over 20.
+ -l : to log message to /var/log/topip.log
+ --ipv6 : this parses netstat output that includes ipv6 format.
+ Note that this actually only works with ipv4 addresses, but for
+ versions of netstat that print in ipv6 format.
+ --stdev=N : Where N is an integer. This sets the trigger point
+ for alerts and logs. Default is to trigger if the
+ max value is over 5 standard deviations.
+
+Example:
+
+ This will print stats for the top IP addresses connected to the given host:
+
+ ./topip.py -s www.example.com -u mylogin -p mypassword -n 10 -v
+
+ This will send an alert email if the maxip goes over the stddev trigger
+ value and the the current top ip is the same as the last top ip
+ (/tmp/topip.last):
+
+ ./topip.py -s www.example.com -u mylogin -p mypassword \\
+ -n 10 -v -a alert@example.com,user@example.com
+
+ This will print the connection stats for the localhost in Munin format:
+
+ ./topip.py
+
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+from __future__ import absolute_import
+from __future__ import print_function
+from __future__ import unicode_literals
+
+# See http://pexpect.sourceforge.net/
+import pexpect
+import pxssh
+import os
+import sys
+import time
+import getopt
+import pickle
+import getpass
+import smtplib
+from pprint import pprint
+
+
+try:
+ raw_input
+except NameError:
+ raw_input = input
+
+
+TOPIP_LOG_FILE = '/var/log/topip.log'
+TOPIP_LAST_RUN_STATS = '/var/run/topip.last'
+
+def exit_with_usage():
+
+ print(globals()['__doc__'])
+ os._exit(1)
+
+def stats(r):
+
+ '''This returns a dict of the median, average, standard deviation,
+ min and max of the given sequence.
+
+ >>> from topip import stats
+ >>> print stats([5,6,8,9])
+ {'med': 8, 'max': 9, 'avg': 7.0, 'stddev': 1.5811388300841898, 'min': 5}
+ >>> print stats([1000,1006,1008,1014])
+ {'med': 1008, 'max': 1014, 'avg': 1007.0, 'stddev': 5.0, 'min': 1000}
+ >>> print stats([1,3,4,5,18,16,4,3,3,5,13])
+ {'med': 4, 'max': 18, 'avg': 6.8181818181818183, 'stddev': 5.6216817577237475, 'min': 1}
+ >>> print stats([1,3,4,5,18,16,4,3,3,5,13,14,5,6,7,8,7,6,6,7,5,6,4,14,7])
+ {'med': 6, 'max': 18, 'avg': 7.0800000000000001, 'stddev': 4.3259218670706474, 'min': 1}
+ '''
+
+ total = sum(r)
+ avg = float(total)/float(len(r))
+ sdsq = sum([(i-avg)**2 for i in r])
+ s = sorted(list(r))
+ return dict(list(zip(['med', 'avg', 'stddev', 'min', 'max'],
+ (s[len(s)//2], avg, (sdsq/len(r))**.5, min(r), max(r)))))
+
+def send_alert (message, subject, addr_from, addr_to, smtp_server='localhost'):
+
+ '''This sends an email alert.
+ '''
+
+ message = ( 'From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n'
+ % (addr_from, addr_to, subject) + message )
+ server = smtplib.SMTP(smtp_server)
+ server.sendmail(addr_from, addr_to, message)
+ server.quit()
+
+def main():
+
+ # Parse the options, arguments, etc.
+ try:
+ optlist, args = getopt.getopt(sys.argv[1:],
+ 'h?valqs:u:p:n:', ['help','h','?','ipv6','stddev='])
+ except Exception as e:
+ print(str(e))
+ exit_with_usage()
+ options = dict(optlist)
+
+ munin_flag = False
+ if len(args) > 0:
+ if args[0] == 'config':
+ print('graph_title Netstat Connections per IP')
+ print('graph_vlabel Socket connections per IP')
+ print('connections_max.label max')
+ print('connections_max.info Maximum number of connections per IP')
+ print('connections_avg.label avg')
+ print('connections_avg.info Average number of connections per IP')
+ print('connections_stddev.label stddev')
+ print('connections_stddev.info Standard deviation')
+ return 0
+ elif args[0] != '':
+ print(args, len(args))
+ return 0
+ exit_with_usage()
+ if [elem for elem in options if elem in ['-h','--h','-?','--?','--help']]:
+ print('Help:')
+ exit_with_usage()
+ if '-s' in options:
+ hostname = options['-s']
+ else:
+ # if host was not specified then assume localhost munin plugin.
+ munin_flag = True
+ hostname = 'localhost'
+ # If localhost then don't ask for username/password.
+ if hostname != 'localhost' and hostname != '127.0.0.1':
+ if '-u' in options:
+ username = options['-u']
+ else:
+ username = raw_input('username: ')
+ if '-p' in options:
+ password = options['-p']
+ else:
+ password = getpass.getpass('password: ')
+ use_localhost = False
+ else:
+ use_localhost = True
+
+ if '-l' in options:
+ log_flag = True
+ else:
+ log_flag = False
+ if '-n' in options:
+ average_n = int(options['-n'])
+ else:
+ average_n = None
+ if '-v' in options:
+ verbose = True
+ else:
+ verbose = False
+ if '-a' in options:
+ alert_flag = True
+ (alert_addr_from, alert_addr_to) = tuple(options['-a'].split(','))
+ else:
+ alert_flag = False
+ if '--ipv6' in options:
+ ipv6_flag = True
+ else:
+ ipv6_flag = False
+ if '--stddev' in options:
+ stddev_trigger = float(options['--stddev'])
+ else:
+ stddev_trigger = 5
+
+ if ipv6_flag:
+ netstat_pattern = r'(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+::ffff:(\S+):(\S+)\s+.*?\r'
+ else:
+ netstat_pattern = r'(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(?:::ffff:)*(\S+):(\S+)\s+.*?\r'
+ #netstat_pattern = r'(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+):(\S+)\s+.*?\r'
+
+ # run netstat (either locally or via SSH).
+ if use_localhost:
+ p = pexpect.spawn('netstat -n -t')
+ PROMPT = pexpect.TIMEOUT
+ else:
+ p = pxssh.pxssh()
+ p.login(hostname, username, password)
+ p.sendline('netstat -n -t')
+ PROMPT = p.PROMPT
+
+ # For each matching netstat_pattern put the ip address in the list.
+ ip_list = {}
+ try:
+ while 1:
+ i = p.expect([PROMPT, netstat_pattern])
+ if i == 0:
+ break
+ k = p.match.groups()[4].decode('utf-8')
+ if k in ip_list:
+ ip_list[k] = ip_list[k] + 1
+ else:
+ ip_list[k] = 1
+ except:
+ pass
+
+ # remove a few common, uninteresting addresses from the dictionary.
+ ip_list = dict([ (key,value) for key,value in ip_list.items() if '192.168.' not in key])
+ ip_list = dict([ (key,value) for key,value in ip_list.items() if '127.0.0.1' not in key])
+
+ ip_list = list(ip_list.items())
+ if len(ip_list) < 1:
+ if verbose: print('Warning: no networks connections worth looking at.')
+ return 0
+ ip_list.sort(key=lambda x:x[1])
+
+ # generate some stats for the ip addresses found.
+ if average_n is not None and average_n <= 1:
+ average_n = None
+ # Reminder: the * unary operator treats the list elements as arguments.
+ zipped = zip(*ip_list[0:average_n])
+ s = stats(list(zipped)[1])
+ s['maxip'] = ip_list[0]
+
+ # print munin-style or verbose results for the stats.
+ if munin_flag:
+ print('connections_max.value', s['max'])
+ print('connections_avg.value', s['avg'])
+ print('connections_stddev.value', s['stddev'])
+ return 0
+ if verbose:
+ pprint (s)
+ print()
+ pprint (ip_list[0:average_n])
+
+ # load the stats from the last run.
+ try:
+ last_stats = pickle.load(file(TOPIP_LAST_RUN_STATS))
+ except:
+ last_stats = {'maxip':None}
+
+ if ( s['maxip'][1] > (s['stddev'] * stddev_trigger)
+ and s['maxip']==last_stats['maxip'] ):
+ if verbose: print('The maxip has been above trigger for two consecutive samples.')
+ if alert_flag:
+ if verbose: print('SENDING ALERT EMAIL')
+ send_alert(str(s), 'ALERT on %s'
+ % hostname, alert_addr_from, alert_addr_to)
+ if log_flag:
+ if verbose: print('LOGGING THIS EVENT')
+ fout = file(TOPIP_LOG_FILE,'a')
+ #dts = time.strftime('%Y:%m:%d:%H:%M:%S', time.localtime())
+ dts = time.asctime()
+ fout.write ('%s - %d connections from %s\n'
+ % (dts,s['maxip'][1],str(s['maxip'][0])))
+ fout.close()
+
+ # save state to TOPIP_LAST_RUN_STATS
+ try:
+ pickle.dump(s, file(TOPIP_LAST_RUN_STATS,'w'))
+ os.chmod (TOPIP_LAST_RUN_STATS, 0o664)
+ except:
+ pass
+ # p.logout()
+
+if __name__ == '__main__':
+ main()
Index: third_party/Python/module/pexpect-4.6/examples/uptime.py
===================================================================
--- third_party/Python/module/pexpect-4.6/examples/uptime.py
+++ third_party/Python/module/pexpect-4.6/examples/uptime.py
@@ -0,0 +1,81 @@
+#!/usr/bin/env python
+
+'''This displays uptime information using uptime. This is redundant,
+but it demonstrates expecting for a regular expression that uses subgroups.
+
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+from __future__ import absolute_import
+from __future__ import print_function
+from __future__ import unicode_literals
+
+import pexpect
+import re
+
+# There are many different styles of uptime results. I try to parse them all. Yeee!
+# Examples from different machines:
+# [x86] Linux 2.4 (Redhat 7.3)
+# 2:06pm up 63 days, 18 min, 3 users, load average: 0.32, 0.08, 0.02
+# [x86] Linux 2.4.18-14 (Redhat 8.0)
+# 3:07pm up 29 min, 1 user, load average: 2.44, 2.51, 1.57
+# [PPC - G4] MacOS X 10.1 SERVER Edition
+# 2:11PM up 3 days, 13:50, 3 users, load averages: 0.01, 0.00, 0.00
+# [powerpc] Darwin v1-58.corefa.com 8.2.0 Darwin Kernel Version 8.2.0
+# 10:35 up 18:06, 4 users, load averages: 0.52 0.47 0.36
+# [Sparc - R220] Sun Solaris (8)
+# 2:13pm up 22 min(s), 1 user, load average: 0.02, 0.01, 0.01
+# [x86] Linux 2.4.18-14 (Redhat 8)
+# 11:36pm up 4 days, 17:58, 1 user, load average: 0.03, 0.01, 0.00
+# AIX jwdir 2 5 0001DBFA4C00
+# 09:43AM up 23:27, 1 user, load average: 0.49, 0.32, 0.23
+# OpenBSD box3 2.9 GENERIC#653 i386
+# 6:08PM up 4 days, 22:26, 1 user, load averages: 0.13, 0.09, 0.08
+
+# Note that, for Python 3 compatibility reasons, we are using spawnu and
+# importing unicode_literals (above). spawnu accepts Unicode input and
+# unicode_literals makes all string literals in this script Unicode by default.
+p = pexpect.spawnu('uptime')
+
+# This parses uptime output into the major groups using regex group matching.
+p.expect(r'up\s+(.*?),\s+([0-9]+) users?,\s+load averages?: ([0-9]+\.[0-9][0-9]),?\s+([0-9]+\.[0-9][0-9]),?\s+([0-9]+\.[0-9][0-9])')
+duration, users, av1, av5, av15 = p.match.groups()
+
+# The duration is a little harder to parse because of all the different
+# styles of uptime. I'm sure there is a way to do this all at once with
+# one single regex, but I bet it would be hard to read and maintain.
+# If anyone wants to send me a version using a single regex I'd be happy to see it.
+days = '0'
+hours = '0'
+mins = '0'
+if 'day' in duration:
+ p.match = re.search(r'([0-9]+)\s+day',duration)
+ days = str(int(p.match.group(1)))
+if ':' in duration:
+ p.match = re.search('([0-9]+):([0-9]+)',duration)
+ hours = str(int(p.match.group(1)))
+ mins = str(int(p.match.group(2)))
+if 'min' in duration:
+ p.match = re.search(r'([0-9]+)\s+min',duration)
+ mins = str(int(p.match.group(1)))
+
+# Print the parsed fields in CSV format.
+print('days, hours, minutes, users, cpu avg 1 min, cpu avg 5 min, cpu avg 15 min')
+print('%s, %s, %s, %s, %s, %s, %s' % (days, hours, mins, users, av1, av5, av15))
+
Index: third_party/Python/module/pexpect-4.6/notes/my_forkpty.py
===================================================================
--- third_party/Python/module/pexpect-4.6/notes/my_forkpty.py
+++ third_party/Python/module/pexpect-4.6/notes/my_forkpty.py
@@ -0,0 +1,89 @@
+import os, fcntl, termios
+import time
+
+def my_forkpty():
+
+ (master_fd, slave_fd) = os.openpty()
+
+ if (master_fd < 0 or slave_fd < 0):
+ raise ExceptionPexpect("Forkpty failed")
+
+ # slave_name = ptsname(master_fd);
+
+ pid = os.fork();
+ if pid == -1:
+ raise ExceptionPexpect("Forkpty failed")
+ elif pid == 0: # Child
+ if hasattr(termios, 'TIOCNOTTY'):
+ # Some platforms require an explicit detach of the
+ # current controlling tty before closing stdin, stdout, stderr.
+ # OpenBSD says that this is obsolete, but doesn't hurt.
+ try:
+ fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY)
+ except:
+ pass
+ else: #if fd >= 0:
+ fcntl.ioctl(fd, termios.TIOCNOTTY, 0)
+ os.close(fd)
+
+ # The setsid() system call will place the process into its own session
+ # which has the effect of disassociating it from the controlling terminal.
+ # This is known to be true for OpenBSD.
+ os.setsid()
+ # except: return posix_error();
+
+ # Verify that we are disconnected from the controlling tty.
+ try:
+ fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY)
+ os.close(fd)
+ raise ExceptionPexpect("Forkpty failed")
+ except:
+ pass
+ if 'TIOCSCTTY' in dir(termios):
+ # Make the pseudo terminal the controlling terminal for this process
+ # (the process must not currently have a controlling terminal).
+ if fcntl.ioctl(slave_fd, termios.TIOCSCTTY, '') < 0:
+ raise ExceptionPexpect("Forkpty failed")
+
+# # Verify that we can open to the slave pty file. */
+# fd = os.open(slave_name, os.O_RDWR);
+# if fd < 0:
+# raise ExceptionPexpect("Forkpty failed")
+# else:
+# os.close(fd);
+
+ # Verify that we now have a controlling tty.
+ fd = os.open("/dev/tty", os.O_WRONLY)
+ if fd < 0:
+ raise ExceptionPexpect("This process could not get a controlling tty.")
+ else:
+ os.close(fd)
+
+ os.close(master_fd)
+ os.dup2(slave_fd, 0)
+ os.dup2(slave_fd, 1)
+ os.dup2(slave_fd, 2)
+ if slave_fd > 2:
+ os.close(slave_fd)
+ pid = 0
+
+ else:
+ # PARENT
+ os.close(slave_fd);
+
+ if pid == -1:
+ raise ExceptionPexpect("This process could not get a controlling tty.")
+# if (pid == 0)
+# PyOS_AfterFork();
+
+ return (pid, master_fd)
+
+pid, fd = my_forkpty ()
+if pid == 0: # child
+ print 'I am not a robot!'
+else:
+ print '(pid, fd) = (%d, %d)' % (pid, fd)
+ time.sleep(1) # Give the child a chance to print.
+ print 'Robots always say:', os.read(fd,100)
+ os.close(fd)
+
Index: third_party/Python/module/pexpect-4.6/notes/notes.txt
===================================================================
--- third_party/Python/module/pexpect-4.6/notes/notes.txt
+++ third_party/Python/module/pexpect-4.6/notes/notes.txt
@@ -0,0 +1,50 @@
+
+####################
+#
+# NOTES
+#
+####################
+
+## def send_human(self, text, delay_min = 0, delay_max = 1):
+## pass
+## def spawn2(self, command, args):
+## """return pid, fd_stdio, fd_stderr
+## """
+## pass
+
+
+# Reason for double fork:
+# http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC15
+# Reason for ptys:
+# http://www.erlenstar.demon.co.uk/unix/faq_4.html#SEC52
+
+# Nonblocking on Win32?
+# Research this as a way to maybe make pipe work for Win32.
+# http://groups.google.com/groups?q=setraw+tty&hl=en&selm=uvgpvisvk.fsf%40roundpoint.com&rnum=7
+#
+# if istty:
+# if os.name=='posix':
+# import tty
+# tty.setraw(sys.stdin.fileno())
+# elif os.name=='nt':
+# import win32file, win32con
+# hstdin = win32file._get_osfhandle(sys.stdin.fileno())
+# modes = (win32file.GetConsoleMode(hstdin)
+# & ~(win32con.ENABLE_LINE_INPUT
+# |win32con.ENABLE_ECHO_INPUT))
+# win32file.SetConsoleMode(hstdin, modes)
+
+# Basic documentation:
+# Explain use of lists of patterns and return index.
+# Explain exceptions for non-handled special cases like EOF
+
+# Test bad fork
+# Test ENOENT. In other words, no more TTY devices.
+
+#GLOBAL_SIGCHLD_RECEIVED = 0
+#def childdied (signum, frame):
+# print 'Signal handler called with signal', signum
+# frame.f_globals['pexpect'].GLOBAL_SIGCHLD_RECEIVED = 1
+# print str(frame.f_globals['pexpect'].GLOBAL_SIGCHLD_RECEIVED)
+# GLOBAL_SIGCHLD_RECEIVED = 1
+
Index: third_party/Python/module/pexpect-4.6/notes/posixmodule.c.diff
===================================================================
--- third_party/Python/module/pexpect-4.6/notes/posixmodule.c.diff
+++ third_party/Python/module/pexpect-4.6/notes/posixmodule.c.diff
@@ -0,0 +1,233 @@
+*** Python-2.2.1.orig/Modules/posixmodule.c Tue Mar 12 16:38:31 2002
+--- Python-2.2.1/Modules/posixmodule.c Tue May 21 01:16:29 2002
+***************
+*** 1904,1910 ****
+ }
+ #endif
+
+! #if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY)
+ #ifdef HAVE_PTY_H
+ #include
+ #else
+--- 1904,1913 ----
+ }
+ #endif
+
+! #if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(sun)
+! #ifdef sun
+! #include
+! #endif
+ #ifdef HAVE_PTY_H
+ #include
+ #else
+***************
+*** 1914,1920 ****
+ #endif /* HAVE_PTY_H */
+ #endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) */
+
+! #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY)
+ static char posix_openpty__doc__[] =
+ "openpty() -> (master_fd, slave_fd)\n\
+ Open a pseudo-terminal, returning open fd's for both master and slave end.\n";
+--- 1917,1923 ----
+ #endif /* HAVE_PTY_H */
+ #endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) */
+
+! #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(sun)
+ static char posix_openpty__doc__[] =
+ "openpty() -> (master_fd, slave_fd)\n\
+ Open a pseudo-terminal, returning open fd's for both master and slave end.\n";
+***************
+*** 1925,1932 ****
+ int master_fd, slave_fd;
+ #ifndef HAVE_OPENPTY
+ char * slave_name;
+ #endif
+!
+ if (!PyArg_ParseTuple(args, ":openpty"))
+ return NULL;
+
+--- 1928,1941 ----
+ int master_fd, slave_fd;
+ #ifndef HAVE_OPENPTY
+ char * slave_name;
++ #ifdef sun
++ void *sig_saved;
+ #endif
+! #endif
+! #if !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY) && defined(sun)
+! extern char *ptsname();
+! #endif
+!
+ if (!PyArg_ParseTuple(args, ":openpty"))
+ return NULL;
+
+***************
+*** 1933,1939 ****
+ #ifdef HAVE_OPENPTY
+ if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
+ return posix_error();
+! #else
+ slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
+ if (slave_name == NULL)
+ return posix_error();
+--- 1942,1948 ----
+ #ifdef HAVE_OPENPTY
+ if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
+ return posix_error();
+! #elif HAVE__GETPTY
+ slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
+ if (slave_name == NULL)
+ return posix_error();
+***************
+*** 1941,1946 ****
+--- 1950,1966 ----
+ slave_fd = open(slave_name, O_RDWR);
+ if (slave_fd < 0)
+ return posix_error();
++ #else
++ master_fd = open("/dev/ptmx", O_RDWR|O_NOCTTY); /* open master */
++ sig_saved = signal(SIGCHLD, SIG_DFL);
++ grantpt(master_fd); /* change permission of slave */
++ unlockpt(master_fd); /* unlock slave */
++ signal(SIGCHLD,sig_saved);
++ slave_name = ptsname(master_fd); /* get name of slave */
++ slave_fd = open(slave_name, O_RDWR); /* open slave */
++ ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
++ ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm*/
++ ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat*/
+ #endif /* HAVE_OPENPTY */
+
+ return Py_BuildValue("(ii)", master_fd, slave_fd);
+***************
+*** 1948,1954 ****
+ }
+ #endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) */
+
+! #ifdef HAVE_FORKPTY
+ static char posix_forkpty__doc__[] =
+ "forkpty() -> (pid, master_fd)\n\
+ Fork a new process with a new pseudo-terminal as controlling tty.\n\n\
+--- 1968,1974 ----
+ }
+ #endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) */
+
+! #if defined(HAVE_FORKPTY) || defined(sun)
+ static char posix_forkpty__doc__[] =
+ "forkpty() -> (pid, master_fd)\n\
+ Fork a new process with a new pseudo-terminal as controlling tty.\n\n\
+***************
+*** 1959,1968 ****
+--- 1979,2067 ----
+ posix_forkpty(PyObject *self, PyObject *args)
+ {
+ int master_fd, pid;
++ #if defined(sun)
++ int slave;
++ char * slave_name;
++ void *sig_saved;
++ int fd;
++ #endif
+
+ if (!PyArg_ParseTuple(args, ":forkpty"))
+ return NULL;
++ #if defined(sun)
++ master_fd = open("/dev/ptmx", O_RDWR|O_NOCTTY); /* open master */
++ sig_saved = signal(SIGCHLD, SIG_DFL);
++ grantpt(master_fd); /* change permission of slave */
++ unlockpt(master_fd); /* unlock slave */
++ signal(SIGCHLD,sig_saved);
++ slave_name = ptsname(master_fd); /* get name of slave */
++ slave = open(slave_name, O_RDWR); /* open slave */
++ ioctl(slave, I_PUSH, "ptem"); /* push ptem */
++ ioctl(slave, I_PUSH, "ldterm"); /* push ldterm*/
++ ioctl(slave, I_PUSH, "ttcompat"); /* push ttcompat*/
++ if (master_fd < 0 || slave < 0)
++ {
++ return posix_error();
++ }
++ switch (pid = fork()) {
++ case -1:
++ return posix_error();
++ case 0:
++ /* First disconnect from the old controlling tty. */
++ #ifdef TIOCNOTTY
++ fd = open("/dev/tty", O_RDWR | O_NOCTTY);
++ if (fd >= 0) {
++ (void) ioctl(fd, TIOCNOTTY, NULL);
++ close(fd);
++ }
++ #endif /* TIOCNOTTY */
++ if (setsid() < 0)
++ return posix_error();
++
++ /*
++ * Verify that we are successfully disconnected from the controlling
++ * tty.
++ */
++ fd = open("/dev/tty", O_RDWR | O_NOCTTY);
++ if (fd >= 0) {
++ return posix_error();
++ close(fd);
++ }
++ /* Make it our controlling tty. */
++ #ifdef TIOCSCTTY
++ if (ioctl(slave, TIOCSCTTY, NULL) < 0)
++ return posix_error();
++ #endif /* TIOCSCTTY */
++ fd = open(slave_name, O_RDWR);
++ if (fd < 0) {
++ return posix_error();
++ } else {
++ close(fd);
++ }
++ /* Verify that we now have a controlling tty. */
++ fd = open("/dev/tty", O_WRONLY);
++ if (fd < 0)
++ return posix_error();
++ else {
++ close(fd);
++ }
++ (void) close(master_fd);
++ (void) dup2(slave, 0);
++ (void) dup2(slave, 1);
++ (void) dup2(slave, 2);
++ if (slave > 2)
++ (void) close(slave);
++ pid = 0;
++ break;
++ defautlt:
++ /*
++ * parent
++ */
++ (void) close(slave);
++ }
++ #else
+ pid = forkpty(&master_fd, NULL, NULL, NULL);
++ #endif
+ if (pid == -1)
+ return posix_error();
+ if (pid == 0)
+***************
+*** 5607,5616 ****
+ #ifdef HAVE_FORK
+ {"fork", posix_fork, METH_VARARGS, posix_fork__doc__},
+ #endif /* HAVE_FORK */
+! #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY)
+ {"openpty", posix_openpty, METH_VARARGS, posix_openpty__doc__},
+ #endif /* HAVE_OPENPTY || HAVE__GETPTY */
+! #ifdef HAVE_FORKPTY
+ {"forkpty", posix_forkpty, METH_VARARGS, posix_forkpty__doc__},
+ #endif /* HAVE_FORKPTY */
+ #ifdef HAVE_GETEGID
+--- 5706,5715 ----
+ #ifdef HAVE_FORK
+ {"fork", posix_fork, METH_VARARGS, posix_fork__doc__},
+ #endif /* HAVE_FORK */
+! #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(sun)
+ {"openpty", posix_openpty, METH_VARARGS, posix_openpty__doc__},
+ #endif /* HAVE_OPENPTY || HAVE__GETPTY */
+! #if defined(HAVE_FORKPTY) || defined(sun)
+ {"forkpty", posix_forkpty, METH_VARARGS, posix_forkpty__doc__},
+ #endif /* HAVE_FORKPTY */
+ #ifdef HAVE_GETEGID
Index: third_party/Python/module/pexpect-4.6/pexpect/ANSI.py
===================================================================
--- third_party/Python/module/pexpect-4.6/pexpect/ANSI.py
+++ third_party/Python/module/pexpect-4.6/pexpect/ANSI.py
@@ -0,0 +1,351 @@
+'''This implements an ANSI (VT100) terminal emulator as a subclass of screen.
+
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+# references:
+# http://en.wikipedia.org/wiki/ANSI_escape_code
+# http://www.retards.org/terminals/vt102.html
+# http://vt100.net/docs/vt102-ug/contents.html
+# http://vt100.net/docs/vt220-rm/
+# http://www.termsys.demon.co.uk/vtansi.htm
+
+from . import screen
+from . import FSM
+import string
+
+#
+# The 'Do.*' functions are helper functions for the ANSI class.
+#
+def DoEmit (fsm):
+
+ screen = fsm.memory[0]
+ screen.write_ch(fsm.input_symbol)
+
+def DoStartNumber (fsm):
+
+ fsm.memory.append (fsm.input_symbol)
+
+def DoBuildNumber (fsm):
+
+ ns = fsm.memory.pop()
+ ns = ns + fsm.input_symbol
+ fsm.memory.append (ns)
+
+def DoBackOne (fsm):
+
+ screen = fsm.memory[0]
+ screen.cursor_back ()
+
+def DoBack (fsm):
+
+ count = int(fsm.memory.pop())
+ screen = fsm.memory[0]
+ screen.cursor_back (count)
+
+def DoDownOne (fsm):
+
+ screen = fsm.memory[0]
+ screen.cursor_down ()
+
+def DoDown (fsm):
+
+ count = int(fsm.memory.pop())
+ screen = fsm.memory[0]
+ screen.cursor_down (count)
+
+def DoForwardOne (fsm):
+
+ screen = fsm.memory[0]
+ screen.cursor_forward ()
+
+def DoForward (fsm):
+
+ count = int(fsm.memory.pop())
+ screen = fsm.memory[0]
+ screen.cursor_forward (count)
+
+def DoUpReverse (fsm):
+
+ screen = fsm.memory[0]
+ screen.cursor_up_reverse()
+
+def DoUpOne (fsm):
+
+ screen = fsm.memory[0]
+ screen.cursor_up ()
+
+def DoUp (fsm):
+
+ count = int(fsm.memory.pop())
+ screen = fsm.memory[0]
+ screen.cursor_up (count)
+
+def DoHome (fsm):
+
+ c = int(fsm.memory.pop())
+ r = int(fsm.memory.pop())
+ screen = fsm.memory[0]
+ screen.cursor_home (r,c)
+
+def DoHomeOrigin (fsm):
+
+ c = 1
+ r = 1
+ screen = fsm.memory[0]
+ screen.cursor_home (r,c)
+
+def DoEraseDown (fsm):
+
+ screen = fsm.memory[0]
+ screen.erase_down()
+
+def DoErase (fsm):
+
+ arg = int(fsm.memory.pop())
+ screen = fsm.memory[0]
+ if arg == 0:
+ screen.erase_down()
+ elif arg == 1:
+ screen.erase_up()
+ elif arg == 2:
+ screen.erase_screen()
+
+def DoEraseEndOfLine (fsm):
+
+ screen = fsm.memory[0]
+ screen.erase_end_of_line()
+
+def DoEraseLine (fsm):
+
+ arg = int(fsm.memory.pop())
+ screen = fsm.memory[0]
+ if arg == 0:
+ screen.erase_end_of_line()
+ elif arg == 1:
+ screen.erase_start_of_line()
+ elif arg == 2:
+ screen.erase_line()
+
+def DoEnableScroll (fsm):
+
+ screen = fsm.memory[0]
+ screen.scroll_screen()
+
+def DoCursorSave (fsm):
+
+ screen = fsm.memory[0]
+ screen.cursor_save_attrs()
+
+def DoCursorRestore (fsm):
+
+ screen = fsm.memory[0]
+ screen.cursor_restore_attrs()
+
+def DoScrollRegion (fsm):
+
+ screen = fsm.memory[0]
+ r2 = int(fsm.memory.pop())
+ r1 = int(fsm.memory.pop())
+ screen.scroll_screen_rows (r1,r2)
+
+def DoMode (fsm):
+
+ screen = fsm.memory[0]
+ mode = fsm.memory.pop() # Should be 4
+ # screen.setReplaceMode ()
+
+def DoLog (fsm):
+
+ screen = fsm.memory[0]
+ fsm.memory = [screen]
+ fout = open ('log', 'a')
+ fout.write (fsm.input_symbol + ',' + fsm.current_state + '\n')
+ fout.close()
+
+class term (screen.screen):
+
+ '''This class is an abstract, generic terminal.
+ This does nothing. This is a placeholder that
+ provides a common base class for other terminals
+ such as an ANSI terminal. '''
+
+ def __init__ (self, r=24, c=80, *args, **kwargs):
+
+ screen.screen.__init__(self, r,c,*args,**kwargs)
+
+class ANSI (term):
+ '''This class implements an ANSI (VT100) terminal.
+ It is a stream filter that recognizes ANSI terminal
+ escape sequences and maintains the state of a screen object. '''
+
+ def __init__ (self, r=24,c=80,*args,**kwargs):
+
+ term.__init__(self,r,c,*args,**kwargs)
+
+ #self.screen = screen (24,80)
+ self.state = FSM.FSM ('INIT',[self])
+ self.state.set_default_transition (DoLog, 'INIT')
+ self.state.add_transition_any ('INIT', DoEmit, 'INIT')
+ self.state.add_transition ('\x1b', 'INIT', None, 'ESC')
+ self.state.add_transition_any ('ESC', DoLog, 'INIT')
+ self.state.add_transition ('(', 'ESC', None, 'G0SCS')
+ self.state.add_transition (')', 'ESC', None, 'G1SCS')
+ self.state.add_transition_list ('AB012', 'G0SCS', None, 'INIT')
+ self.state.add_transition_list ('AB012', 'G1SCS', None, 'INIT')
+ self.state.add_transition ('7', 'ESC', DoCursorSave, 'INIT')
+ self.state.add_transition ('8', 'ESC', DoCursorRestore, 'INIT')
+ self.state.add_transition ('M', 'ESC', DoUpReverse, 'INIT')
+ self.state.add_transition ('>', 'ESC', DoUpReverse, 'INIT')
+ self.state.add_transition ('<', 'ESC', DoUpReverse, 'INIT')
+ self.state.add_transition ('=', 'ESC', None, 'INIT') # Selects application keypad.
+ self.state.add_transition ('#', 'ESC', None, 'GRAPHICS_POUND')
+ self.state.add_transition_any ('GRAPHICS_POUND', None, 'INIT')
+ self.state.add_transition ('[', 'ESC', None, 'ELB')
+ # ELB means Escape Left Bracket. That is ^[[
+ self.state.add_transition ('H', 'ELB', DoHomeOrigin, 'INIT')
+ self.state.add_transition ('D', 'ELB', DoBackOne, 'INIT')
+ self.state.add_transition ('B', 'ELB', DoDownOne, 'INIT')
+ self.state.add_transition ('C', 'ELB', DoForwardOne, 'INIT')
+ self.state.add_transition ('A', 'ELB', DoUpOne, 'INIT')
+ self.state.add_transition ('J', 'ELB', DoEraseDown, 'INIT')
+ self.state.add_transition ('K', 'ELB', DoEraseEndOfLine, 'INIT')
+ self.state.add_transition ('r', 'ELB', DoEnableScroll, 'INIT')
+ self.state.add_transition ('m', 'ELB', self.do_sgr, 'INIT')
+ self.state.add_transition ('?', 'ELB', None, 'MODECRAP')
+ self.state.add_transition_list (string.digits, 'ELB', DoStartNumber, 'NUMBER_1')
+ self.state.add_transition_list (string.digits, 'NUMBER_1', DoBuildNumber, 'NUMBER_1')
+ self.state.add_transition ('D', 'NUMBER_1', DoBack, 'INIT')
+ self.state.add_transition ('B', 'NUMBER_1', DoDown, 'INIT')
+ self.state.add_transition ('C', 'NUMBER_1', DoForward, 'INIT')
+ self.state.add_transition ('A', 'NUMBER_1', DoUp, 'INIT')
+ self.state.add_transition ('J', 'NUMBER_1', DoErase, 'INIT')
+ self.state.add_transition ('K', 'NUMBER_1', DoEraseLine, 'INIT')
+ self.state.add_transition ('l', 'NUMBER_1', DoMode, 'INIT')
+ ### It gets worse... the 'm' code can have infinite number of
+ ### number;number;number before it. I've never seen more than two,
+ ### but the specs say it's allowed. crap!
+ self.state.add_transition ('m', 'NUMBER_1', self.do_sgr, 'INIT')
+ ### LED control. Same implementation problem as 'm' code.
+ self.state.add_transition ('q', 'NUMBER_1', self.do_decsca, 'INIT')
+
+ # \E[?47h switch to alternate screen
+ # \E[?47l restores to normal screen from alternate screen.
+ self.state.add_transition_list (string.digits, 'MODECRAP', DoStartNumber, 'MODECRAP_NUM')
+ self.state.add_transition_list (string.digits, 'MODECRAP_NUM', DoBuildNumber, 'MODECRAP_NUM')
+ self.state.add_transition ('l', 'MODECRAP_NUM', self.do_modecrap, 'INIT')
+ self.state.add_transition ('h', 'MODECRAP_NUM', self.do_modecrap, 'INIT')
+
+#RM Reset Mode Esc [ Ps l none
+ self.state.add_transition (';', 'NUMBER_1', None, 'SEMICOLON')
+ self.state.add_transition_any ('SEMICOLON', DoLog, 'INIT')
+ self.state.add_transition_list (string.digits, 'SEMICOLON', DoStartNumber, 'NUMBER_2')
+ self.state.add_transition_list (string.digits, 'NUMBER_2', DoBuildNumber, 'NUMBER_2')
+ self.state.add_transition_any ('NUMBER_2', DoLog, 'INIT')
+ self.state.add_transition ('H', 'NUMBER_2', DoHome, 'INIT')
+ self.state.add_transition ('f', 'NUMBER_2', DoHome, 'INIT')
+ self.state.add_transition ('r', 'NUMBER_2', DoScrollRegion, 'INIT')
+ ### It gets worse... the 'm' code can have infinite number of
+ ### number;number;number before it. I've never seen more than two,
+ ### but the specs say it's allowed. crap!
+ self.state.add_transition ('m', 'NUMBER_2', self.do_sgr, 'INIT')
+ ### LED control. Same problem as 'm' code.
+ self.state.add_transition ('q', 'NUMBER_2', self.do_decsca, 'INIT')
+ self.state.add_transition (';', 'NUMBER_2', None, 'SEMICOLON_X')
+
+ # Create a state for 'q' and 'm' which allows an infinite number of ignored numbers
+ self.state.add_transition_any ('SEMICOLON_X', DoLog, 'INIT')
+ self.state.add_transition_list (string.digits, 'SEMICOLON_X', DoStartNumber, 'NUMBER_X')
+ self.state.add_transition_list (string.digits, 'NUMBER_X', DoBuildNumber, 'NUMBER_X')
+ self.state.add_transition_any ('NUMBER_X', DoLog, 'INIT')
+ self.state.add_transition ('m', 'NUMBER_X', self.do_sgr, 'INIT')
+ self.state.add_transition ('q', 'NUMBER_X', self.do_decsca, 'INIT')
+ self.state.add_transition (';', 'NUMBER_X', None, 'SEMICOLON_X')
+
+ def process (self, c):
+ """Process a single character. Called by :meth:`write`."""
+ if isinstance(c, bytes):
+ c = self._decode(c)
+ self.state.process(c)
+
+ def process_list (self, l):
+
+ self.write(l)
+
+ def write (self, s):
+ """Process text, writing it to the virtual screen while handling
+ ANSI escape codes.
+ """
+ if isinstance(s, bytes):
+ s = self._decode(s)
+ for c in s:
+ self.process(c)
+
+ def flush (self):
+ pass
+
+ def write_ch (self, ch):
+ '''This puts a character at the current cursor position. The cursor
+ position is moved forward with wrap-around, but no scrolling is done if
+ the cursor hits the lower-right corner of the screen. '''
+
+ if isinstance(ch, bytes):
+ ch = self._decode(ch)
+
+ #\r and \n both produce a call to cr() and lf(), respectively.
+ ch = ch[0]
+
+ if ch == u'\r':
+ self.cr()
+ return
+ if ch == u'\n':
+ self.crlf()
+ return
+ if ch == chr(screen.BS):
+ self.cursor_back()
+ return
+ self.put_abs(self.cur_r, self.cur_c, ch)
+ old_r = self.cur_r
+ old_c = self.cur_c
+ self.cursor_forward()
+ if old_c == self.cur_c:
+ self.cursor_down()
+ if old_r != self.cur_r:
+ self.cursor_home (self.cur_r, 1)
+ else:
+ self.scroll_up ()
+ self.cursor_home (self.cur_r, 1)
+ self.erase_line()
+
+ def do_sgr (self, fsm):
+ '''Select Graphic Rendition, e.g. color. '''
+ screen = fsm.memory[0]
+ fsm.memory = [screen]
+
+ def do_decsca (self, fsm):
+ '''Select character protection attribute. '''
+ screen = fsm.memory[0]
+ fsm.memory = [screen]
+
+ def do_modecrap (self, fsm):
+ '''Handler for \x1b[?h and \x1b[?l. If anyone
+ wanted to actually use these, they'd need to add more states to the
+ FSM rather than just improve or override this method. '''
+ screen = fsm.memory[0]
+ fsm.memory = [screen]
Index: third_party/Python/module/pexpect-4.6/pexpect/FSM.py
===================================================================
--- third_party/Python/module/pexpect-4.6/pexpect/FSM.py
+++ third_party/Python/module/pexpect-4.6/pexpect/FSM.py
@@ -0,0 +1,334 @@
+#!/usr/bin/env python
+
+'''This module implements a Finite State Machine (FSM). In addition to state
+this FSM also maintains a user defined "memory". So this FSM can be used as a
+Push-down Automata (PDA) since a PDA is a FSM + memory.
+
+The following describes how the FSM works, but you will probably also need to
+see the example function to understand how the FSM is used in practice.
+
+You define an FSM by building tables of transitions. For a given input symbol
+the process() method uses these tables to decide what action to call and what
+the next state will be. The FSM has a table of transitions that associate:
+
+ (input_symbol, current_state) --> (action, next_state)
+
+Where "action" is a function you define. The symbols and states can be any
+objects. You use the add_transition() and add_transition_list() methods to add
+to the transition table. The FSM also has a table of transitions that
+associate:
+
+ (current_state) --> (action, next_state)
+
+You use the add_transition_any() method to add to this transition table. The
+FSM also has one default transition that is not associated with any specific
+input_symbol or state. You use the set_default_transition() method to set the
+default transition.
+
+When an action function is called it is passed a reference to the FSM. The
+action function may then access attributes of the FSM such as input_symbol,
+current_state, or "memory". The "memory" attribute can be any object that you
+want to pass along to the action functions. It is not used by the FSM itself.
+For parsing you would typically pass a list to be used as a stack.
+
+The processing sequence is as follows. The process() method is given an
+input_symbol to process. The FSM will search the table of transitions that
+associate:
+
+ (input_symbol, current_state) --> (action, next_state)
+
+If the pair (input_symbol, current_state) is found then process() will call the
+associated action function and then set the current state to the next_state.
+
+If the FSM cannot find a match for (input_symbol, current_state) it will then
+search the table of transitions that associate:
+
+ (current_state) --> (action, next_state)
+
+If the current_state is found then the process() method will call the
+associated action function and then set the current state to the next_state.
+Notice that this table lacks an input_symbol. It lets you define transitions
+for a current_state and ANY input_symbol. Hence, it is called the "any" table.
+Remember, it is always checked after first searching the table for a specific
+(input_symbol, current_state).
+
+For the case where the FSM did not match either of the previous two cases the
+FSM will try to use the default transition. If the default transition is
+defined then the process() method will call the associated action function and
+then set the current state to the next_state. This lets you define a default
+transition as a catch-all case. You can think of it as an exception handler.
+There can be only one default transition.
+
+Finally, if none of the previous cases are defined for an input_symbol and
+current_state then the FSM will raise an exception. This may be desirable, but
+you can always prevent this just by defining a default transition.
+
+Noah Spurrier 20020822
+
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+class ExceptionFSM(Exception):
+
+ '''This is the FSM Exception class.'''
+
+ def __init__(self, value):
+ self.value = value
+
+ def __str__(self):
+ return 'ExceptionFSM: ' + str(self.value)
+
+class FSM:
+
+ '''This is a Finite State Machine (FSM).
+ '''
+
+ def __init__(self, initial_state, memory=None):
+
+ '''This creates the FSM. You set the initial state here. The "memory"
+ attribute is any object that you want to pass along to the action
+ functions. It is not used by the FSM. For parsing you would typically
+ pass a list to be used as a stack. '''
+
+ # Map (input_symbol, current_state) --> (action, next_state).
+ self.state_transitions = {}
+ # Map (current_state) --> (action, next_state).
+ self.state_transitions_any = {}
+ self.default_transition = None
+
+ self.input_symbol = None
+ self.initial_state = initial_state
+ self.current_state = self.initial_state
+ self.next_state = None
+ self.action = None
+ self.memory = memory
+
+ def reset (self):
+
+ '''This sets the current_state to the initial_state and sets
+ input_symbol to None. The initial state was set by the constructor
+ __init__(). '''
+
+ self.current_state = self.initial_state
+ self.input_symbol = None
+
+ def add_transition (self, input_symbol, state, action=None, next_state=None):
+
+ '''This adds a transition that associates:
+
+ (input_symbol, current_state) --> (action, next_state)
+
+ The action may be set to None in which case the process() method will
+ ignore the action and only set the next_state. The next_state may be
+ set to None in which case the current state will be unchanged.
+
+ You can also set transitions for a list of symbols by using
+ add_transition_list(). '''
+
+ if next_state is None:
+ next_state = state
+ self.state_transitions[(input_symbol, state)] = (action, next_state)
+
+ def add_transition_list (self, list_input_symbols, state, action=None, next_state=None):
+
+ '''This adds the same transition for a list of input symbols.
+ You can pass a list or a string. Note that it is handy to use
+ string.digits, string.whitespace, string.letters, etc. to add
+ transitions that match character classes.
+
+ The action may be set to None in which case the process() method will
+ ignore the action and only set the next_state. The next_state may be
+ set to None in which case the current state will be unchanged. '''
+
+ if next_state is None:
+ next_state = state
+ for input_symbol in list_input_symbols:
+ self.add_transition (input_symbol, state, action, next_state)
+
+ def add_transition_any (self, state, action=None, next_state=None):
+
+ '''This adds a transition that associates:
+
+ (current_state) --> (action, next_state)
+
+ That is, any input symbol will match the current state.
+ The process() method checks the "any" state associations after it first
+ checks for an exact match of (input_symbol, current_state).
+
+ The action may be set to None in which case the process() method will
+ ignore the action and only set the next_state. The next_state may be
+ set to None in which case the current state will be unchanged. '''
+
+ if next_state is None:
+ next_state = state
+ self.state_transitions_any [state] = (action, next_state)
+
+ def set_default_transition (self, action, next_state):
+
+ '''This sets the default transition. This defines an action and
+ next_state if the FSM cannot find the input symbol and the current
+ state in the transition list and if the FSM cannot find the
+ current_state in the transition_any list. This is useful as a final
+ fall-through state for catching errors and undefined states.
+
+ The default transition can be removed by setting the attribute
+ default_transition to None. '''
+
+ self.default_transition = (action, next_state)
+
+ def get_transition (self, input_symbol, state):
+
+ '''This returns (action, next state) given an input_symbol and state.
+ This does not modify the FSM state, so calling this method has no side
+ effects. Normally you do not call this method directly. It is called by
+ process().
+
+ The sequence of steps to check for a defined transition goes from the
+ most specific to the least specific.
+
+ 1. Check state_transitions[] that match exactly the tuple,
+ (input_symbol, state)
+
+ 2. Check state_transitions_any[] that match (state)
+ In other words, match a specific state and ANY input_symbol.
+
+ 3. Check if the default_transition is defined.
+ This catches any input_symbol and any state.
+ This is a handler for errors, undefined states, or defaults.
+
+ 4. No transition was defined. If we get here then raise an exception.
+ '''
+
+ if (input_symbol, state) in self.state_transitions:
+ return self.state_transitions[(input_symbol, state)]
+ elif state in self.state_transitions_any:
+ return self.state_transitions_any[state]
+ elif self.default_transition is not None:
+ return self.default_transition
+ else:
+ raise ExceptionFSM ('Transition is undefined: (%s, %s).' %
+ (str(input_symbol), str(state)) )
+
+ def process (self, input_symbol):
+
+ '''This is the main method that you call to process input. This may
+ cause the FSM to change state and call an action. This method calls
+ get_transition() to find the action and next_state associated with the
+ input_symbol and current_state. If the action is None then the action
+ is not called and only the current state is changed. This method
+ processes one complete input symbol. You can process a list of symbols
+ (or a string) by calling process_list(). '''
+
+ self.input_symbol = input_symbol
+ (self.action, self.next_state) = self.get_transition (self.input_symbol, self.current_state)
+ if self.action is not None:
+ self.action (self)
+ self.current_state = self.next_state
+ self.next_state = None
+
+ def process_list (self, input_symbols):
+
+ '''This takes a list and sends each element to process(). The list may
+ be a string or any iterable object. '''
+
+ for s in input_symbols:
+ self.process (s)
+
+##############################################################################
+# The following is an example that demonstrates the use of the FSM class to
+# process an RPN expression. Run this module from the command line. You will
+# get a prompt > for input. Enter an RPN Expression. Numbers may be integers.
+# Operators are * / + - Use the = sign to evaluate and print the expression.
+# For example:
+#
+# 167 3 2 2 * * * 1 - =
+#
+# will print:
+#
+# 2003
+##############################################################################
+
+import sys
+import string
+
+PY3 = (sys.version_info[0] >= 3)
+
+#
+# These define the actions.
+# Note that "memory" is a list being used as a stack.
+#
+
+def BeginBuildNumber (fsm):
+ fsm.memory.append (fsm.input_symbol)
+
+def BuildNumber (fsm):
+ s = fsm.memory.pop ()
+ s = s + fsm.input_symbol
+ fsm.memory.append (s)
+
+def EndBuildNumber (fsm):
+ s = fsm.memory.pop ()
+ fsm.memory.append (int(s))
+
+def DoOperator (fsm):
+ ar = fsm.memory.pop()
+ al = fsm.memory.pop()
+ if fsm.input_symbol == '+':
+ fsm.memory.append (al + ar)
+ elif fsm.input_symbol == '-':
+ fsm.memory.append (al - ar)
+ elif fsm.input_symbol == '*':
+ fsm.memory.append (al * ar)
+ elif fsm.input_symbol == '/':
+ fsm.memory.append (al / ar)
+
+def DoEqual (fsm):
+ print(str(fsm.memory.pop()))
+
+def Error (fsm):
+ print('That does not compute.')
+ print(str(fsm.input_symbol))
+
+def main():
+
+ '''This is where the example starts and the FSM state transitions are
+ defined. Note that states are strings (such as 'INIT'). This is not
+ necessary, but it makes the example easier to read. '''
+
+ f = FSM ('INIT', [])
+ f.set_default_transition (Error, 'INIT')
+ f.add_transition_any ('INIT', None, 'INIT')
+ f.add_transition ('=', 'INIT', DoEqual, 'INIT')
+ f.add_transition_list (string.digits, 'INIT', BeginBuildNumber, 'BUILDING_NUMBER')
+ f.add_transition_list (string.digits, 'BUILDING_NUMBER', BuildNumber, 'BUILDING_NUMBER')
+ f.add_transition_list (string.whitespace, 'BUILDING_NUMBER', EndBuildNumber, 'INIT')
+ f.add_transition_list ('+-*/', 'INIT', DoOperator, 'INIT')
+
+ print()
+ print('Enter an RPN Expression.')
+ print('Numbers may be integers. Operators are * / + -')
+ print('Use the = sign to evaluate and print the expression.')
+ print('For example: ')
+ print(' 167 3 2 2 * * * 1 - =')
+ inputstr = (input if PY3 else raw_input)('> ') # analysis:ignore
+ f.process_list(inputstr)
+
+
+if __name__ == '__main__':
+ main()
Index: third_party/Python/module/pexpect-4.6/pexpect/__init__.py
===================================================================
--- third_party/Python/module/pexpect-4.6/pexpect/__init__.py
+++ third_party/Python/module/pexpect-4.6/pexpect/__init__.py
@@ -0,0 +1,85 @@
+'''Pexpect is a Python module for spawning child applications and controlling
+them automatically. Pexpect can be used for automating interactive applications
+such as ssh, ftp, passwd, telnet, etc. It can be used to a automate setup
+scripts for duplicating software package installations on different servers. It
+can be used for automated software testing. Pexpect is in the spirit of Don
+Libes' Expect, but Pexpect is pure Python. Other Expect-like modules for Python
+require TCL and Expect or require C extensions to be compiled. Pexpect does not
+use C, Expect, or TCL extensions. It should work on any platform that supports
+the standard Python pty module. The Pexpect interface focuses on ease of use so
+that simple tasks are easy.
+
+There are two main interfaces to the Pexpect system; these are the function,
+run() and the class, spawn. The spawn class is more powerful. The run()
+function is simpler than spawn, and is good for quickly calling program. When
+you call the run() function it executes a given program and then returns the
+output. This is a handy replacement for os.system().
+
+For example::
+
+ pexpect.run('ls -la')
+
+The spawn class is the more powerful interface to the Pexpect system. You can
+use this to spawn a child program then interact with it by sending input and
+expecting responses (waiting for patterns in the child's output).
+
+For example::
+
+ child = pexpect.spawn('scp foo user@example.com:.')
+ child.expect('Password:')
+ child.sendline(mypassword)
+
+This works even for commands that ask for passwords or other input outside of
+the normal stdio streams. For example, ssh reads input directly from the TTY
+device which bypasses stdin.
+
+Credits: Noah Spurrier, Richard Holden, Marco Molteni, Kimberley Burchett,
+Robert Stone, Hartmut Goebel, Chad Schroeder, Erick Tryzelaar, Dave Kirby, Ids
+vander Molen, George Todd, Noel Taylor, Nicolas D. Cesar, Alexander Gattin,
+Jacques-Etienne Baudoux, Geoffrey Marshall, Francisco Lourenco, Glen Mabey,
+Karthik Gurusamy, Fernando Perez, Corey Minyard, Jon Cohen, Guillaume
+Chazarain, Andrew Ryan, Nick Craig-Wood, Andrew Stone, Jorgen Grahn, John
+Spiegel, Jan Grant, and Shane Kerr. Let me know if I forgot anyone.
+
+Pexpect is free, open source, and all that good stuff.
+http://pexpect.sourceforge.net/
+
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+import sys
+PY3 = (sys.version_info[0] >= 3)
+
+from .exceptions import ExceptionPexpect, EOF, TIMEOUT
+from .utils import split_command_line, which, is_executable_file
+from .expect import Expecter, searcher_re, searcher_string
+
+if sys.platform != 'win32':
+ # On Unix, these are available at the top level for backwards compatibility
+ from .pty_spawn import spawn, spawnu
+ from .run import run, runu
+
+__version__ = '4.6.0'
+__revision__ = ''
+__all__ = ['ExceptionPexpect', 'EOF', 'TIMEOUT', 'spawn', 'spawnu', 'run', 'runu',
+ 'which', 'split_command_line', '__version__', '__revision__']
+
+
+
+# vim: set shiftround expandtab tabstop=4 shiftwidth=4 ft=python autoindent :
Index: third_party/Python/module/pexpect-4.6/pexpect/_async.py
===================================================================
--- third_party/Python/module/pexpect-4.6/pexpect/_async.py
+++ third_party/Python/module/pexpect-4.6/pexpect/_async.py
@@ -0,0 +1,87 @@
+import asyncio
+import errno
+
+from pexpect import EOF
+
+@asyncio.coroutine
+def expect_async(expecter, timeout=None):
+ # First process data that was previously read - if it maches, we don't need
+ # async stuff.
+ previously_read = expecter.spawn.buffer
+ expecter.spawn._buffer = expecter.spawn.buffer_type()
+ expecter.spawn._before = expecter.spawn.buffer_type()
+ idx = expecter.new_data(previously_read)
+ if idx is not None:
+ return idx
+ if not expecter.spawn.async_pw_transport:
+ pw = PatternWaiter()
+ pw.set_expecter(expecter)
+ transport, pw = yield from asyncio.get_event_loop()\
+ .connect_read_pipe(lambda: pw, expecter.spawn)
+ expecter.spawn.async_pw_transport = pw, transport
+ else:
+ pw, transport = expecter.spawn.async_pw_transport
+ pw.set_expecter(expecter)
+ transport.resume_reading()
+ try:
+ return (yield from asyncio.wait_for(pw.fut, timeout))
+ except asyncio.TimeoutError as e:
+ transport.pause_reading()
+ return expecter.timeout(e)
+
+
+class PatternWaiter(asyncio.Protocol):
+ transport = None
+
+ def set_expecter(self, expecter):
+ self.expecter = expecter
+ self.fut = asyncio.Future()
+
+ def found(self, result):
+ if not self.fut.done():
+ self.fut.set_result(result)
+ self.transport.pause_reading()
+
+ def error(self, exc):
+ if not self.fut.done():
+ self.fut.set_exception(exc)
+ self.transport.pause_reading()
+
+ def connection_made(self, transport):
+ self.transport = transport
+
+ def data_received(self, data):
+ spawn = self.expecter.spawn
+ s = spawn._decoder.decode(data)
+ spawn._log(s, 'read')
+
+ if self.fut.done():
+ spawn._buffer.write(s)
+ return
+
+ try:
+ index = self.expecter.new_data(s)
+ if index is not None:
+ # Found a match
+ self.found(index)
+ except Exception as e:
+ self.expecter.errored()
+ self.error(e)
+
+ def eof_received(self):
+ # N.B. If this gets called, async will close the pipe (the spawn object)
+ # for us
+ try:
+ self.expecter.spawn.flag_eof = True
+ index = self.expecter.eof()
+ except EOF as e:
+ self.error(e)
+ else:
+ self.found(index)
+
+ def connection_lost(self, exc):
+ if isinstance(exc, OSError) and exc.errno == errno.EIO:
+ # We may get here without eof_received being called, e.g on Linux
+ self.eof_received()
+ elif exc is not None:
+ self.error(exc)
Index: third_party/Python/module/pexpect-4.6/pexpect/bashrc.sh
===================================================================
--- third_party/Python/module/pexpect-4.6/pexpect/bashrc.sh
+++ third_party/Python/module/pexpect-4.6/pexpect/bashrc.sh
@@ -0,0 +1,16 @@
+# Different platforms have different names for the systemwide bashrc
+if [[ -f /etc/bashrc ]]; then
+ source /etc/bashrc
+fi
+if [[ -f /etc/bash.bashrc ]]; then
+ source /etc/bash.bashrc
+fi
+if [[ -f ~/.bashrc ]]; then
+ source ~/.bashrc
+fi
+
+# Reset PS1 so pexpect can find it
+PS1="$"
+
+# Unset PROMPT_COMMAND, so that it can't change PS1 to something unexpected.
+unset PROMPT_COMMAND
Index: third_party/Python/module/pexpect-4.6/pexpect/exceptions.py
===================================================================
--- third_party/Python/module/pexpect-4.6/pexpect/exceptions.py
+++ third_party/Python/module/pexpect-4.6/pexpect/exceptions.py
@@ -0,0 +1,35 @@
+"""Exception classes used by Pexpect"""
+
+import traceback
+import sys
+
+class ExceptionPexpect(Exception):
+ '''Base class for all exceptions raised by this module.
+ '''
+
+ def __init__(self, value):
+ super(ExceptionPexpect, self).__init__(value)
+ self.value = value
+
+ def __str__(self):
+ return str(self.value)
+
+ def get_trace(self):
+ '''This returns an abbreviated stack trace with lines that only concern
+ the caller. In other words, the stack trace inside the Pexpect module
+ is not included. '''
+
+ tblist = traceback.extract_tb(sys.exc_info()[2])
+ tblist = [item for item in tblist if ('pexpect/__init__' not in item[0])
+ and ('pexpect/expect' not in item[0])]
+ tblist = traceback.format_list(tblist)
+ return ''.join(tblist)
+
+
+class EOF(ExceptionPexpect):
+ '''Raised when EOF is read from a child.
+ This usually means the child has exited.'''
+
+
+class TIMEOUT(ExceptionPexpect):
+ '''Raised when a read time exceeds the timeout. '''
Index: third_party/Python/module/pexpect-4.6/pexpect/expect.py
===================================================================
--- third_party/Python/module/pexpect-4.6/pexpect/expect.py
+++ third_party/Python/module/pexpect-4.6/pexpect/expect.py
@@ -0,0 +1,306 @@
+import time
+
+from .exceptions import EOF, TIMEOUT
+
+class Expecter(object):
+ def __init__(self, spawn, searcher, searchwindowsize=-1):
+ self.spawn = spawn
+ self.searcher = searcher
+ if searchwindowsize == -1:
+ searchwindowsize = spawn.searchwindowsize
+ self.searchwindowsize = searchwindowsize
+
+ def new_data(self, data):
+ spawn = self.spawn
+ searcher = self.searcher
+
+ pos = spawn._buffer.tell()
+ spawn._buffer.write(data)
+ spawn._before.write(data)
+
+ # determine which chunk of data to search; if a windowsize is
+ # specified, this is the *new* data + the preceding bytes
+ if self.searchwindowsize:
+ spawn._buffer.seek(max(0, pos - self.searchwindowsize))
+ window = spawn._buffer.read(self.searchwindowsize + len(data))
+ else:
+ # otherwise, search the whole buffer (really slow for large datasets)
+ window = spawn.buffer
+ index = searcher.search(window, len(data))
+ if index >= 0:
+ spawn._buffer = spawn.buffer_type()
+ spawn._buffer.write(window[searcher.end:])
+ spawn.before = spawn._before.getvalue()[0:-(len(window) - searcher.start)]
+ spawn._before = spawn.buffer_type()
+ spawn.after = window[searcher.start: searcher.end]
+ spawn.match = searcher.match
+ spawn.match_index = index
+ # Found a match
+ return index
+ elif self.searchwindowsize:
+ spawn._buffer = spawn.buffer_type()
+ spawn._buffer.write(window)
+
+ def eof(self, err=None):
+ spawn = self.spawn
+
+ spawn.before = spawn.buffer
+ spawn._buffer = spawn.buffer_type()
+ spawn._before = spawn.buffer_type()
+ spawn.after = EOF
+ index = self.searcher.eof_index
+ if index >= 0:
+ spawn.match = EOF
+ spawn.match_index = index
+ return index
+ else:
+ spawn.match = None
+ spawn.match_index = None
+ msg = str(spawn)
+ msg += '\nsearcher: %s' % self.searcher
+ if err is not None:
+ msg = str(err) + '\n' + msg
+ raise EOF(msg)
+
+ def timeout(self, err=None):
+ spawn = self.spawn
+
+ spawn.before = spawn.buffer
+ spawn.after = TIMEOUT
+ index = self.searcher.timeout_index
+ if index >= 0:
+ spawn.match = TIMEOUT
+ spawn.match_index = index
+ return index
+ else:
+ spawn.match = None
+ spawn.match_index = None
+ msg = str(spawn)
+ msg += '\nsearcher: %s' % self.searcher
+ if err is not None:
+ msg = str(err) + '\n' + msg
+ raise TIMEOUT(msg)
+
+ def errored(self):
+ spawn = self.spawn
+ spawn.before = spawn.buffer
+ spawn.after = None
+ spawn.match = None
+ spawn.match_index = None
+
+ def expect_loop(self, timeout=-1):
+ """Blocking expect"""
+ spawn = self.spawn
+
+ if timeout is not None:
+ end_time = time.time() + timeout
+
+ try:
+ incoming = spawn.buffer
+ spawn._buffer = spawn.buffer_type()
+ spawn._before = spawn.buffer_type()
+ while True:
+ idx = self.new_data(incoming)
+ # Keep reading until exception or return.
+ if idx is not None:
+ return idx
+ # No match at this point
+ if (timeout is not None) and (timeout < 0):
+ return self.timeout()
+ # Still have time left, so read more data
+ incoming = spawn.read_nonblocking(spawn.maxread, timeout)
+ if self.spawn.delayafterread is not None:
+ time.sleep(self.spawn.delayafterread)
+ if timeout is not None:
+ timeout = end_time - time.time()
+ except EOF as e:
+ return self.eof(e)
+ except TIMEOUT as e:
+ return self.timeout(e)
+ except:
+ self.errored()
+ raise
+
+
+class searcher_string(object):
+ '''This is a plain string search helper for the spawn.expect_any() method.
+ This helper class is for speed. For more powerful regex patterns
+ see the helper class, searcher_re.
+
+ Attributes:
+
+ eof_index - index of EOF, or -1
+ timeout_index - index of TIMEOUT, or -1
+
+ After a successful match by the search() method the following attributes
+ are available:
+
+ start - index into the buffer, first byte of match
+ end - index into the buffer, first byte after match
+ match - the matching string itself
+
+ '''
+
+ def __init__(self, strings):
+ '''This creates an instance of searcher_string. This argument 'strings'
+ may be a list; a sequence of strings; or the EOF or TIMEOUT types. '''
+
+ self.eof_index = -1
+ self.timeout_index = -1
+ self._strings = []
+ for n, s in enumerate(strings):
+ if s is EOF:
+ self.eof_index = n
+ continue
+ if s is TIMEOUT:
+ self.timeout_index = n
+ continue
+ self._strings.append((n, s))
+
+ def __str__(self):
+ '''This returns a human-readable string that represents the state of
+ the object.'''
+
+ ss = [(ns[0], ' %d: %r' % ns) for ns in self._strings]
+ ss.append((-1, 'searcher_string:'))
+ if self.eof_index >= 0:
+ ss.append((self.eof_index, ' %d: EOF' % self.eof_index))
+ if self.timeout_index >= 0:
+ ss.append((self.timeout_index,
+ ' %d: TIMEOUT' % self.timeout_index))
+ ss.sort()
+ ss = list(zip(*ss))[1]
+ return '\n'.join(ss)
+
+ def search(self, buffer, freshlen, searchwindowsize=None):
+ '''This searches 'buffer' for the first occurrence of one of the search
+ strings. 'freshlen' must indicate the number of bytes at the end of
+ 'buffer' which have not been searched before. It helps to avoid
+ searching the same, possibly big, buffer over and over again.
+
+ See class spawn for the 'searchwindowsize' argument.
+
+ If there is a match this returns the index of that string, and sets
+ 'start', 'end' and 'match'. Otherwise, this returns -1. '''
+
+ first_match = None
+
+ # 'freshlen' helps a lot here. Further optimizations could
+ # possibly include:
+ #
+ # using something like the Boyer-Moore Fast String Searching
+ # Algorithm; pre-compiling the search through a list of
+ # strings into something that can scan the input once to
+ # search for all N strings; realize that if we search for
+ # ['bar', 'baz'] and the input is '...foo' we need not bother
+ # rescanning until we've read three more bytes.
+ #
+ # Sadly, I don't know enough about this interesting topic. /grahn
+
+ for index, s in self._strings:
+ if searchwindowsize is None:
+ # the match, if any, can only be in the fresh data,
+ # or at the very end of the old data
+ offset = -(freshlen + len(s))
+ else:
+ # better obey searchwindowsize
+ offset = -searchwindowsize
+ n = buffer.find(s, offset)
+ if n >= 0 and (first_match is None or n < first_match):
+ first_match = n
+ best_index, best_match = index, s
+ if first_match is None:
+ return -1
+ self.match = best_match
+ self.start = first_match
+ self.end = self.start + len(self.match)
+ return best_index
+
+
+class searcher_re(object):
+ '''This is regular expression string search helper for the
+ spawn.expect_any() method. This helper class is for powerful
+ pattern matching. For speed, see the helper class, searcher_string.
+
+ Attributes:
+
+ eof_index - index of EOF, or -1
+ timeout_index - index of TIMEOUT, or -1
+
+ After a successful match by the search() method the following attributes
+ are available:
+
+ start - index into the buffer, first byte of match
+ end - index into the buffer, first byte after match
+ match - the re.match object returned by a successful re.search
+
+ '''
+
+ def __init__(self, patterns):
+ '''This creates an instance that searches for 'patterns' Where
+ 'patterns' may be a list or other sequence of compiled regular
+ expressions, or the EOF or TIMEOUT types.'''
+
+ self.eof_index = -1
+ self.timeout_index = -1
+ self._searches = []
+ for n, s in zip(list(range(len(patterns))), patterns):
+ if s is EOF:
+ self.eof_index = n
+ continue
+ if s is TIMEOUT:
+ self.timeout_index = n
+ continue
+ self._searches.append((n, s))
+
+ def __str__(self):
+ '''This returns a human-readable string that represents the state of
+ the object.'''
+
+ #ss = [(n, ' %d: re.compile("%s")' %
+ # (n, repr(s.pattern))) for n, s in self._searches]
+ ss = list()
+ for n, s in self._searches:
+ ss.append((n, ' %d: re.compile(%r)' % (n, s.pattern)))
+ ss.append((-1, 'searcher_re:'))
+ if self.eof_index >= 0:
+ ss.append((self.eof_index, ' %d: EOF' % self.eof_index))
+ if self.timeout_index >= 0:
+ ss.append((self.timeout_index, ' %d: TIMEOUT' %
+ self.timeout_index))
+ ss.sort()
+ ss = list(zip(*ss))[1]
+ return '\n'.join(ss)
+
+ def search(self, buffer, freshlen, searchwindowsize=None):
+ '''This searches 'buffer' for the first occurrence of one of the regular
+ expressions. 'freshlen' must indicate the number of bytes at the end of
+ 'buffer' which have not been searched before.
+
+ See class spawn for the 'searchwindowsize' argument.
+
+ If there is a match this returns the index of that string, and sets
+ 'start', 'end' and 'match'. Otherwise, returns -1.'''
+
+ first_match = None
+ # 'freshlen' doesn't help here -- we cannot predict the
+ # length of a match, and the re module provides no help.
+ if searchwindowsize is None:
+ searchstart = 0
+ else:
+ searchstart = max(0, len(buffer) - searchwindowsize)
+ for index, s in self._searches:
+ match = s.search(buffer, searchstart)
+ if match is None:
+ continue
+ n = match.start()
+ if first_match is None or n < first_match:
+ first_match = n
+ the_match = match
+ best_index = index
+ if first_match is None:
+ return -1
+ self.start = first_match
+ self.match = the_match
+ self.end = self.match.end()
+ return best_index
Index: third_party/Python/module/pexpect-4.6/pexpect/fdpexpect.py
===================================================================
--- third_party/Python/module/pexpect-4.6/pexpect/fdpexpect.py
+++ third_party/Python/module/pexpect-4.6/pexpect/fdpexpect.py
@@ -0,0 +1,148 @@
+'''This is like pexpect, but it will work with any file descriptor that you
+pass it. You are responsible for opening and close the file descriptor.
+This allows you to use Pexpect with sockets and named pipes (FIFOs).
+
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+from .spawnbase import SpawnBase
+from .exceptions import ExceptionPexpect, TIMEOUT
+from .utils import select_ignore_interrupts, poll_ignore_interrupts
+import os
+
+__all__ = ['fdspawn']
+
+class fdspawn(SpawnBase):
+ '''This is like pexpect.spawn but allows you to supply your own open file
+ descriptor. For example, you could use it to read through a file looking
+ for patterns, or to control a modem or serial device. '''
+
+ def __init__ (self, fd, args=None, timeout=30, maxread=2000, searchwindowsize=None,
+ logfile=None, encoding=None, codec_errors='strict', use_poll=False):
+ '''This takes a file descriptor (an int) or an object that support the
+ fileno() method (returning an int). All Python file-like objects
+ support fileno(). '''
+
+ if type(fd) != type(0) and hasattr(fd, 'fileno'):
+ fd = fd.fileno()
+
+ if type(fd) != type(0):
+ raise ExceptionPexpect('The fd argument is not an int. If this is a command string then maybe you want to use pexpect.spawn.')
+
+ try: # make sure fd is a valid file descriptor
+ os.fstat(fd)
+ except OSError:
+ raise ExceptionPexpect('The fd argument is not a valid file descriptor.')
+
+ self.args = None
+ self.command = None
+ SpawnBase.__init__(self, timeout, maxread, searchwindowsize, logfile,
+ encoding=encoding, codec_errors=codec_errors)
+ self.child_fd = fd
+ self.own_fd = False
+ self.closed = False
+ self.name = '' % fd
+ self.use_poll = use_poll
+
+ def close (self):
+ """Close the file descriptor.
+
+ Calling this method a second time does nothing, but if the file
+ descriptor was closed elsewhere, :class:`OSError` will be raised.
+ """
+ if self.child_fd == -1:
+ return
+
+ self.flush()
+ os.close(self.child_fd)
+ self.child_fd = -1
+ self.closed = True
+
+ def isalive (self):
+ '''This checks if the file descriptor is still valid. If :func:`os.fstat`
+ does not raise an exception then we assume it is alive. '''
+
+ if self.child_fd == -1:
+ return False
+ try:
+ os.fstat(self.child_fd)
+ return True
+ except:
+ return False
+
+ def terminate (self, force=False): # pragma: no cover
+ '''Deprecated and invalid. Just raises an exception.'''
+ raise ExceptionPexpect('This method is not valid for file descriptors.')
+
+ # These four methods are left around for backwards compatibility, but not
+ # documented as part of fdpexpect. You're encouraged to use os.write
+ # directly.
+ def send(self, s):
+ "Write to fd, return number of bytes written"
+ s = self._coerce_send_string(s)
+ self._log(s, 'send')
+
+ b = self._encoder.encode(s, final=False)
+ return os.write(self.child_fd, b)
+
+ def sendline(self, s):
+ "Write to fd with trailing newline, return number of bytes written"
+ s = self._coerce_send_string(s)
+ return self.send(s + self.linesep)
+
+ def write(self, s):
+ "Write to fd, return None"
+ self.send(s)
+
+ def writelines(self, sequence):
+ "Call self.write() for each item in sequence"
+ for s in sequence:
+ self.write(s)
+
+ def read_nonblocking(self, size=1, timeout=-1):
+ """
+ Read from the file descriptor and return the result as a string.
+
+ The read_nonblocking method of :class:`SpawnBase` assumes that a call
+ to os.read will not block (timeout parameter is ignored). This is not
+ the case for POSIX file-like objects such as sockets and serial ports.
+
+ Use :func:`select.select`, timeout is implemented conditionally for
+ POSIX systems.
+
+ :param int size: Read at most *size* bytes.
+ :param int timeout: Wait timeout seconds for file descriptor to be
+ ready to read. When -1 (default), use self.timeout. When 0, poll.
+ :return: String containing the bytes read
+ """
+ if os.name == 'posix':
+ if timeout == -1:
+ timeout = self.timeout
+ rlist = [self.child_fd]
+ wlist = []
+ xlist = []
+ if self.use_poll:
+ rlist = poll_ignore_interrupts(rlist, timeout)
+ else:
+ rlist, wlist, xlist = select_ignore_interrupts(
+ rlist, wlist, xlist, timeout
+ )
+ if self.child_fd not in rlist:
+ raise TIMEOUT('Timeout exceeded.')
+ return super(fdspawn, self).read_nonblocking(size)
Index: third_party/Python/module/pexpect-4.6/pexpect/popen_spawn.py
===================================================================
--- third_party/Python/module/pexpect-4.6/pexpect/popen_spawn.py
+++ third_party/Python/module/pexpect-4.6/pexpect/popen_spawn.py
@@ -0,0 +1,188 @@
+"""Provides an interface like pexpect.spawn interface using subprocess.Popen
+"""
+import os
+import threading
+import subprocess
+import sys
+import time
+import signal
+import shlex
+
+try:
+ from queue import Queue, Empty # Python 3
+except ImportError:
+ from Queue import Queue, Empty # Python 2
+
+from .spawnbase import SpawnBase, PY3
+from .exceptions import EOF
+from .utils import string_types
+
+class PopenSpawn(SpawnBase):
+ def __init__(self, cmd, timeout=30, maxread=2000, searchwindowsize=None,
+ logfile=None, cwd=None, env=None, encoding=None,
+ codec_errors='strict', preexec_fn=None):
+ super(PopenSpawn, self).__init__(timeout=timeout, maxread=maxread,
+ searchwindowsize=searchwindowsize, logfile=logfile,
+ encoding=encoding, codec_errors=codec_errors)
+
+ # Note that `SpawnBase` initializes `self.crlf` to `\r\n`
+ # because the default behaviour for a PTY is to convert
+ # incoming LF to `\r\n` (see the `onlcr` flag and
+ # https://stackoverflow.com/a/35887657/5397009). Here we set
+ # it to `os.linesep` because that is what the spawned
+ # application outputs by default and `popen` doesn't translate
+ # anything.
+ if encoding is None:
+ self.crlf = os.linesep.encode ("ascii")
+ else:
+ self.crlf = self.string_type (os.linesep)
+
+ kwargs = dict(bufsize=0, stdin=subprocess.PIPE,
+ stderr=subprocess.STDOUT, stdout=subprocess.PIPE,
+ cwd=cwd, preexec_fn=preexec_fn, env=env)
+
+ if sys.platform == 'win32':
+ startupinfo = subprocess.STARTUPINFO()
+ startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
+ kwargs['startupinfo'] = startupinfo
+ kwargs['creationflags'] = subprocess.CREATE_NEW_PROCESS_GROUP
+
+ if isinstance(cmd, string_types) and sys.platform != 'win32':
+ cmd = shlex.split(cmd, posix=os.name == 'posix')
+
+ self.proc = subprocess.Popen(cmd, **kwargs)
+ self.pid = self.proc.pid
+ self.closed = False
+ self._buf = self.string_type()
+
+ self._read_queue = Queue()
+ self._read_thread = threading.Thread(target=self._read_incoming)
+ self._read_thread.setDaemon(True)
+ self._read_thread.start()
+
+ _read_reached_eof = False
+
+ def read_nonblocking(self, size, timeout):
+ buf = self._buf
+ if self._read_reached_eof:
+ # We have already finished reading. Use up any buffered data,
+ # then raise EOF
+ if buf:
+ self._buf = buf[size:]
+ return buf[:size]
+ else:
+ self.flag_eof = True
+ raise EOF('End Of File (EOF).')
+
+ if timeout == -1:
+ timeout = self.timeout
+ elif timeout is None:
+ timeout = 1e6
+
+ t0 = time.time()
+ while (time.time() - t0) < timeout and size and len(buf) < size:
+ try:
+ incoming = self._read_queue.get_nowait()
+ except Empty:
+ break
+ else:
+ if incoming is None:
+ self._read_reached_eof = True
+ break
+
+ buf += self._decoder.decode(incoming, final=False)
+
+ r, self._buf = buf[:size], buf[size:]
+
+ self._log(r, 'read')
+ return r
+
+ def _read_incoming(self):
+ """Run in a thread to move output from a pipe to a queue."""
+ fileno = self.proc.stdout.fileno()
+ while 1:
+ buf = b''
+ try:
+ buf = os.read(fileno, 1024)
+ except OSError as e:
+ self._log(e, 'read')
+
+ if not buf:
+ # This indicates we have reached EOF
+ self._read_queue.put(None)
+ return
+
+ self._read_queue.put(buf)
+
+ def write(self, s):
+ '''This is similar to send() except that there is no return value.
+ '''
+ self.send(s)
+
+ def writelines(self, sequence):
+ '''This calls write() for each element in the sequence.
+
+ The sequence can be any iterable object producing strings, typically a
+ list of strings. This does not add line separators. There is no return
+ value.
+ '''
+ for s in sequence:
+ self.send(s)
+
+ def send(self, s):
+ '''Send data to the subprocess' stdin.
+
+ Returns the number of bytes written.
+ '''
+ s = self._coerce_send_string(s)
+ self._log(s, 'send')
+
+ b = self._encoder.encode(s, final=False)
+ if PY3:
+ return self.proc.stdin.write(b)
+ else:
+ # On Python 2, .write() returns None, so we return the length of
+ # bytes written ourselves. This assumes they all got written.
+ self.proc.stdin.write(b)
+ return len(b)
+
+ def sendline(self, s=''):
+ '''Wraps send(), sending string ``s`` to child process, with os.linesep
+ automatically appended. Returns number of bytes written. '''
+
+ n = self.send(s)
+ return n + self.send(self.linesep)
+
+ def wait(self):
+ '''Wait for the subprocess to finish.
+
+ Returns the exit code.
+ '''
+ status = self.proc.wait()
+ if status >= 0:
+ self.exitstatus = status
+ self.signalstatus = None
+ else:
+ self.exitstatus = None
+ self.signalstatus = -status
+ self.terminated = True
+ return status
+
+ def kill(self, sig):
+ '''Sends a Unix signal to the subprocess.
+
+ Use constants from the :mod:`signal` module to specify which signal.
+ '''
+ if sys.platform == 'win32':
+ if sig in [signal.SIGINT, signal.CTRL_C_EVENT]:
+ sig = signal.CTRL_C_EVENT
+ elif sig in [signal.SIGBREAK, signal.CTRL_BREAK_EVENT]:
+ sig = signal.CTRL_BREAK_EVENT
+ else:
+ sig = signal.SIGTERM
+
+ os.kill(self.proc.pid, sig)
+
+ def sendeof(self):
+ '''Closes the stdin pipe from the writing end.'''
+ self.proc.stdin.close()
Index: third_party/Python/module/pexpect-4.6/pexpect/pty_spawn.py
===================================================================
--- third_party/Python/module/pexpect-4.6/pexpect/pty_spawn.py
+++ third_party/Python/module/pexpect-4.6/pexpect/pty_spawn.py
@@ -0,0 +1,833 @@
+import os
+import sys
+import time
+import pty
+import tty
+import errno
+import signal
+from contextlib import contextmanager
+
+import ptyprocess
+from ptyprocess.ptyprocess import use_native_pty_fork
+
+from .exceptions import ExceptionPexpect, EOF, TIMEOUT
+from .spawnbase import SpawnBase
+from .utils import (
+ which, split_command_line, select_ignore_interrupts, poll_ignore_interrupts
+)
+
+@contextmanager
+def _wrap_ptyprocess_err():
+ """Turn ptyprocess errors into our own ExceptionPexpect errors"""
+ try:
+ yield
+ except ptyprocess.PtyProcessError as e:
+ raise ExceptionPexpect(*e.args)
+
+PY3 = (sys.version_info[0] >= 3)
+
+class spawn(SpawnBase):
+ '''This is the main class interface for Pexpect. Use this class to start
+ and control child applications. '''
+
+ # This is purely informational now - changing it has no effect
+ use_native_pty_fork = use_native_pty_fork
+
+ def __init__(self, command, args=[], timeout=30, maxread=2000,
+ searchwindowsize=None, logfile=None, cwd=None, env=None,
+ ignore_sighup=False, echo=True, preexec_fn=None,
+ encoding=None, codec_errors='strict', dimensions=None,
+ use_poll=False):
+ '''This is the constructor. The command parameter may be a string that
+ includes a command and any arguments to the command. For example::
+
+ child = pexpect.spawn('/usr/bin/ftp')
+ child = pexpect.spawn('/usr/bin/ssh user@example.com')
+ child = pexpect.spawn('ls -latr /tmp')
+
+ You may also construct it with a list of arguments like so::
+
+ child = pexpect.spawn('/usr/bin/ftp', [])
+ child = pexpect.spawn('/usr/bin/ssh', ['user@example.com'])
+ child = pexpect.spawn('ls', ['-latr', '/tmp'])
+
+ After this the child application will be created and will be ready to
+ talk to. For normal use, see expect() and send() and sendline().
+
+ Remember that Pexpect does NOT interpret shell meta characters such as
+ redirect, pipe, or wild cards (``>``, ``|``, or ``*``). This is a
+ common mistake. If you want to run a command and pipe it through
+ another command then you must also start a shell. For example::
+
+ child = pexpect.spawn('/bin/bash -c "ls -l | grep LOG > logs.txt"')
+ child.expect(pexpect.EOF)
+
+ The second form of spawn (where you pass a list of arguments) is useful
+ in situations where you wish to spawn a command and pass it its own
+ argument list. This can make syntax more clear. For example, the
+ following is equivalent to the previous example::
+
+ shell_cmd = 'ls -l | grep LOG > logs.txt'
+ child = pexpect.spawn('/bin/bash', ['-c', shell_cmd])
+ child.expect(pexpect.EOF)
+
+ The maxread attribute sets the read buffer size. This is maximum number
+ of bytes that Pexpect will try to read from a TTY at one time. Setting
+ the maxread size to 1 will turn off buffering. Setting the maxread
+ value higher may help performance in cases where large amounts of
+ output are read back from the child. This feature is useful in
+ conjunction with searchwindowsize.
+
+ When the keyword argument *searchwindowsize* is None (default), the
+ full buffer is searched at each iteration of receiving incoming data.
+ The default number of bytes scanned at each iteration is very large
+ and may be reduced to collaterally reduce search cost. After
+ :meth:`~.expect` returns, the full buffer attribute remains up to
+ size *maxread* irrespective of *searchwindowsize* value.
+
+ When the keyword argument ``timeout`` is specified as a number,
+ (default: *30*), then :class:`TIMEOUT` will be raised after the value
+ specified has elapsed, in seconds, for any of the :meth:`~.expect`
+ family of method calls. When None, TIMEOUT will not be raised, and
+ :meth:`~.expect` may block indefinitely until match.
+
+
+ The logfile member turns on or off logging. All input and output will
+ be copied to the given file object. Set logfile to None to stop
+ logging. This is the default. Set logfile to sys.stdout to echo
+ everything to standard output. The logfile is flushed after each write.
+
+ Example log input and output to a file::
+
+ child = pexpect.spawn('some_command')
+ fout = open('mylog.txt','wb')
+ child.logfile = fout
+
+ Example log to stdout::
+
+ # In Python 2:
+ child = pexpect.spawn('some_command')
+ child.logfile = sys.stdout
+
+ # In Python 3, we'll use the ``encoding`` argument to decode data
+ # from the subprocess and handle it as unicode:
+ child = pexpect.spawn('some_command', encoding='utf-8')
+ child.logfile = sys.stdout
+
+ The logfile_read and logfile_send members can be used to separately log
+ the input from the child and output sent to the child. Sometimes you
+ don't want to see everything you write to the child. You only want to
+ log what the child sends back. For example::
+
+ child = pexpect.spawn('some_command')
+ child.logfile_read = sys.stdout
+
+ You will need to pass an encoding to spawn in the above code if you are
+ using Python 3.
+
+ To separately log output sent to the child use logfile_send::
+
+ child.logfile_send = fout
+
+ If ``ignore_sighup`` is True, the child process will ignore SIGHUP
+ signals. The default is False from Pexpect 4.0, meaning that SIGHUP
+ will be handled normally by the child.
+
+ The delaybeforesend helps overcome a weird behavior that many users
+ were experiencing. The typical problem was that a user would expect() a
+ "Password:" prompt and then immediately call sendline() to send the
+ password. The user would then see that their password was echoed back
+ to them. Passwords don't normally echo. The problem is caused by the
+ fact that most applications print out the "Password" prompt and then
+ turn off stdin echo, but if you send your password before the
+ application turned off echo, then you get your password echoed.
+ Normally this wouldn't be a problem when interacting with a human at a
+ real keyboard. If you introduce a slight delay just before writing then
+ this seems to clear up the problem. This was such a common problem for
+ many users that I decided that the default pexpect behavior should be
+ to sleep just before writing to the child application. 1/20th of a
+ second (50 ms) seems to be enough to clear up the problem. You can set
+ delaybeforesend to None to return to the old behavior.
+
+ Note that spawn is clever about finding commands on your path.
+ It uses the same logic that "which" uses to find executables.
+
+ If you wish to get the exit status of the child you must call the
+ close() method. The exit or signal status of the child will be stored
+ in self.exitstatus or self.signalstatus. If the child exited normally
+ then exitstatus will store the exit return code and signalstatus will
+ be None. If the child was terminated abnormally with a signal then
+ signalstatus will store the signal value and exitstatus will be None::
+
+ child = pexpect.spawn('some_command')
+ child.close()
+ print(child.exitstatus, child.signalstatus)
+
+ If you need more detail you can also read the self.status member which
+ stores the status returned by os.waitpid. You can interpret this using
+ os.WIFEXITED/os.WEXITSTATUS or os.WIFSIGNALED/os.TERMSIG.
+
+ The echo attribute may be set to False to disable echoing of input.
+ As a pseudo-terminal, all input echoed by the "keyboard" (send()
+ or sendline()) will be repeated to output. For many cases, it is
+ not desirable to have echo enabled, and it may be later disabled
+ using setecho(False) followed by waitnoecho(). However, for some
+ platforms such as Solaris, this is not possible, and should be
+ disabled immediately on spawn.
+
+ If preexec_fn is given, it will be called in the child process before
+ launching the given command. This is useful to e.g. reset inherited
+ signal handlers.
+
+ The dimensions attribute specifies the size of the pseudo-terminal as
+ seen by the subprocess, and is specified as a two-entry tuple (rows,
+ columns). If this is unspecified, the defaults in ptyprocess will apply.
+
+ The use_poll attribute enables using select.poll() over select.select()
+ for socket handling. This is handy if your system could have > 1024 fds
+ '''
+ super(spawn, self).__init__(timeout=timeout, maxread=maxread, searchwindowsize=searchwindowsize,
+ logfile=logfile, encoding=encoding, codec_errors=codec_errors)
+ self.STDIN_FILENO = pty.STDIN_FILENO
+ self.STDOUT_FILENO = pty.STDOUT_FILENO
+ self.STDERR_FILENO = pty.STDERR_FILENO
+ self.cwd = cwd
+ self.env = env
+ self.echo = echo
+ self.ignore_sighup = ignore_sighup
+ self.__irix_hack = sys.platform.lower().startswith('irix')
+ if command is None:
+ self.command = None
+ self.args = None
+ self.name = ''
+ else:
+ self._spawn(command, args, preexec_fn, dimensions)
+ self.use_poll = use_poll
+
+ def __str__(self):
+ '''This returns a human-readable string that represents the state of
+ the object. '''
+
+ s = []
+ s.append(repr(self))
+ s.append('command: ' + str(self.command))
+ s.append('args: %r' % (self.args,))
+ s.append('buffer (last 100 chars): %r' % self.buffer[-100:])
+ s.append('before (last 100 chars): %r' % self.before[-100:] if self.before else '')
+ s.append('after: %r' % (self.after,))
+ s.append('match: %r' % (self.match,))
+ s.append('match_index: ' + str(self.match_index))
+ s.append('exitstatus: ' + str(self.exitstatus))
+ if hasattr(self, 'ptyproc'):
+ s.append('flag_eof: ' + str(self.flag_eof))
+ s.append('pid: ' + str(self.pid))
+ s.append('child_fd: ' + str(self.child_fd))
+ s.append('closed: ' + str(self.closed))
+ s.append('timeout: ' + str(self.timeout))
+ s.append('delimiter: ' + str(self.delimiter))
+ s.append('logfile: ' + str(self.logfile))
+ s.append('logfile_read: ' + str(self.logfile_read))
+ s.append('logfile_send: ' + str(self.logfile_send))
+ s.append('maxread: ' + str(self.maxread))
+ s.append('ignorecase: ' + str(self.ignorecase))
+ s.append('searchwindowsize: ' + str(self.searchwindowsize))
+ s.append('delaybeforesend: ' + str(self.delaybeforesend))
+ s.append('delayafterclose: ' + str(self.delayafterclose))
+ s.append('delayafterterminate: ' + str(self.delayafterterminate))
+ return '\n'.join(s)
+
+ def _spawn(self, command, args=[], preexec_fn=None, dimensions=None):
+ '''This starts the given command in a child process. This does all the
+ fork/exec type of stuff for a pty. This is called by __init__. If args
+ is empty then command will be parsed (split on spaces) and args will be
+ set to parsed arguments. '''
+
+ # The pid and child_fd of this object get set by this method.
+ # Note that it is difficult for this method to fail.
+ # You cannot detect if the child process cannot start.
+ # So the only way you can tell if the child process started
+ # or not is to try to read from the file descriptor. If you get
+ # EOF immediately then it means that the child is already dead.
+ # That may not necessarily be bad because you may have spawned a child
+ # that performs some task; creates no stdout output; and then dies.
+
+ # If command is an int type then it may represent a file descriptor.
+ if isinstance(command, type(0)):
+ raise ExceptionPexpect('Command is an int type. ' +
+ 'If this is a file descriptor then maybe you want to ' +
+ 'use fdpexpect.fdspawn which takes an existing ' +
+ 'file descriptor instead of a command string.')
+
+ if not isinstance(args, type([])):
+ raise TypeError('The argument, args, must be a list.')
+
+ if args == []:
+ self.args = split_command_line(command)
+ self.command = self.args[0]
+ else:
+ # Make a shallow copy of the args list.
+ self.args = args[:]
+ self.args.insert(0, command)
+ self.command = command
+
+ command_with_path = which(self.command, env=self.env)
+ if command_with_path is None:
+ raise ExceptionPexpect('The command was not found or was not ' +
+ 'executable: %s.' % self.command)
+ self.command = command_with_path
+ self.args[0] = self.command
+
+ self.name = '<' + ' '.join(self.args) + '>'
+
+ assert self.pid is None, 'The pid member must be None.'
+ assert self.command is not None, 'The command member must not be None.'
+
+ kwargs = {'echo': self.echo, 'preexec_fn': preexec_fn}
+ if self.ignore_sighup:
+ def preexec_wrapper():
+ "Set SIGHUP to be ignored, then call the real preexec_fn"
+ signal.signal(signal.SIGHUP, signal.SIG_IGN)
+ if preexec_fn is not None:
+ preexec_fn()
+ kwargs['preexec_fn'] = preexec_wrapper
+
+ if dimensions is not None:
+ kwargs['dimensions'] = dimensions
+
+ if self.encoding is not None:
+ # Encode command line using the specified encoding
+ self.args = [a if isinstance(a, bytes) else a.encode(self.encoding)
+ for a in self.args]
+
+ self.ptyproc = self._spawnpty(self.args, env=self.env,
+ cwd=self.cwd, **kwargs)
+
+ self.pid = self.ptyproc.pid
+ self.child_fd = self.ptyproc.fd
+
+
+ self.terminated = False
+ self.closed = False
+
+ def _spawnpty(self, args, **kwargs):
+ '''Spawn a pty and return an instance of PtyProcess.'''
+ return ptyprocess.PtyProcess.spawn(args, **kwargs)
+
+ def close(self, force=True):
+ '''This closes the connection with the child application. Note that
+ calling close() more than once is valid. This emulates standard Python
+ behavior with files. Set force to True if you want to make sure that
+ the child is terminated (SIGKILL is sent if the child ignores SIGHUP
+ and SIGINT). '''
+
+ self.flush()
+ with _wrap_ptyprocess_err():
+ # PtyProcessError may be raised if it is not possible to terminate
+ # the child.
+ self.ptyproc.close(force=force)
+ self.isalive() # Update exit status from ptyproc
+ self.child_fd = -1
+ self.closed = True
+
+ def isatty(self):
+ '''This returns True if the file descriptor is open and connected to a
+ tty(-like) device, else False.
+
+ On SVR4-style platforms implementing streams, such as SunOS and HP-UX,
+ the child pty may not appear as a terminal device. This means
+ methods such as setecho(), setwinsize(), getwinsize() may raise an
+ IOError. '''
+
+ return os.isatty(self.child_fd)
+
+ def waitnoecho(self, timeout=-1):
+ '''This waits until the terminal ECHO flag is set False. This returns
+ True if the echo mode is off. This returns False if the ECHO flag was
+ not set False before the timeout. This can be used to detect when the
+ child is waiting for a password. Usually a child application will turn
+ off echo mode when it is waiting for the user to enter a password. For
+ example, instead of expecting the "password:" prompt you can wait for
+ the child to set ECHO off::
+
+ p = pexpect.spawn('ssh user@example.com')
+ p.waitnoecho()
+ p.sendline(mypassword)
+
+ If timeout==-1 then this method will use the value in self.timeout.
+ If timeout==None then this method to block until ECHO flag is False.
+ '''
+
+ if timeout == -1:
+ timeout = self.timeout
+ if timeout is not None:
+ end_time = time.time() + timeout
+ while True:
+ if not self.getecho():
+ return True
+ if timeout < 0 and timeout is not None:
+ return False
+ if timeout is not None:
+ timeout = end_time - time.time()
+ time.sleep(0.1)
+
+ def getecho(self):
+ '''This returns the terminal echo mode. This returns True if echo is
+ on or False if echo is off. Child applications that are expecting you
+ to enter a password often set ECHO False. See waitnoecho().
+
+ Not supported on platforms where ``isatty()`` returns False. '''
+ return self.ptyproc.getecho()
+
+ def setecho(self, state):
+ '''This sets the terminal echo mode on or off. Note that anything the
+ child sent before the echo will be lost, so you should be sure that
+ your input buffer is empty before you call setecho(). For example, the
+ following will work as expected::
+
+ p = pexpect.spawn('cat') # Echo is on by default.
+ p.sendline('1234') # We expect see this twice from the child...
+ p.expect(['1234']) # ... once from the tty echo...
+ p.expect(['1234']) # ... and again from cat itself.
+ p.setecho(False) # Turn off tty echo
+ p.sendline('abcd') # We will set this only once (echoed by cat).
+ p.sendline('wxyz') # We will set this only once (echoed by cat)
+ p.expect(['abcd'])
+ p.expect(['wxyz'])
+
+ The following WILL NOT WORK because the lines sent before the setecho
+ will be lost::
+
+ p = pexpect.spawn('cat')
+ p.sendline('1234')
+ p.setecho(False) # Turn off tty echo
+ p.sendline('abcd') # We will set this only once (echoed by cat).
+ p.sendline('wxyz') # We will set this only once (echoed by cat)
+ p.expect(['1234'])
+ p.expect(['1234'])
+ p.expect(['abcd'])
+ p.expect(['wxyz'])
+
+
+ Not supported on platforms where ``isatty()`` returns False.
+ '''
+ return self.ptyproc.setecho(state)
+
+ def read_nonblocking(self, size=1, timeout=-1):
+ '''This reads at most size characters from the child application. It
+ includes a timeout. If the read does not complete within the timeout
+ period then a TIMEOUT exception is raised. If the end of file is read
+ then an EOF exception will be raised. If a logfile is specified, a
+ copy is written to that log.
+
+ If timeout is None then the read may block indefinitely.
+ If timeout is -1 then the self.timeout value is used. If timeout is 0
+ then the child is polled and if there is no data immediately ready
+ then this will raise a TIMEOUT exception.
+
+ The timeout refers only to the amount of time to read at least one
+ character. This is not affected by the 'size' parameter, so if you call
+ read_nonblocking(size=100, timeout=30) and only one character is
+ available right away then one character will be returned immediately.
+ It will not wait for 30 seconds for another 99 characters to come in.
+
+ This is a wrapper around os.read(). It uses select.select() to
+ implement the timeout. '''
+
+ if self.closed:
+ raise ValueError('I/O operation on closed file.')
+
+ if timeout == -1:
+ timeout = self.timeout
+
+ # Note that some systems such as Solaris do not give an EOF when
+ # the child dies. In fact, you can still try to read
+ # from the child_fd -- it will block forever or until TIMEOUT.
+ # For this case, I test isalive() before doing any reading.
+ # If isalive() is false, then I pretend that this is the same as EOF.
+ if not self.isalive():
+ # timeout of 0 means "poll"
+ if self.use_poll:
+ r = poll_ignore_interrupts([self.child_fd], timeout)
+ else:
+ r, w, e = select_ignore_interrupts([self.child_fd], [], [], 0)
+ if not r:
+ self.flag_eof = True
+ raise EOF('End Of File (EOF). Braindead platform.')
+ elif self.__irix_hack:
+ # Irix takes a long time before it realizes a child was terminated.
+ # FIXME So does this mean Irix systems are forced to always have
+ # FIXME a 2 second delay when calling read_nonblocking? That sucks.
+ if self.use_poll:
+ r = poll_ignore_interrupts([self.child_fd], timeout)
+ else:
+ r, w, e = select_ignore_interrupts([self.child_fd], [], [], 2)
+ if not r and not self.isalive():
+ self.flag_eof = True
+ raise EOF('End Of File (EOF). Slow platform.')
+ if self.use_poll:
+ r = poll_ignore_interrupts([self.child_fd], timeout)
+ else:
+ r, w, e = select_ignore_interrupts(
+ [self.child_fd], [], [], timeout
+ )
+
+ if not r:
+ if not self.isalive():
+ # Some platforms, such as Irix, will claim that their
+ # processes are alive; timeout on the select; and
+ # then finally admit that they are not alive.
+ self.flag_eof = True
+ raise EOF('End of File (EOF). Very slow platform.')
+ else:
+ raise TIMEOUT('Timeout exceeded.')
+
+ if self.child_fd in r:
+ return super(spawn, self).read_nonblocking(size)
+
+ raise ExceptionPexpect('Reached an unexpected state.') # pragma: no cover
+
+ def write(self, s):
+ '''This is similar to send() except that there is no return value.
+ '''
+
+ self.send(s)
+
+ def writelines(self, sequence):
+ '''This calls write() for each element in the sequence. The sequence
+ can be any iterable object producing strings, typically a list of
+ strings. This does not add line separators. There is no return value.
+ '''
+
+ for s in sequence:
+ self.write(s)
+
+ def send(self, s):
+ '''Sends string ``s`` to the child process, returning the number of
+ bytes written. If a logfile is specified, a copy is written to that
+ log.
+
+ The default terminal input mode is canonical processing unless set
+ otherwise by the child process. This allows backspace and other line
+ processing to be performed prior to transmitting to the receiving
+ program. As this is buffered, there is a limited size of such buffer.
+
+ On Linux systems, this is 4096 (defined by N_TTY_BUF_SIZE). All
+ other systems honor the POSIX.1 definition PC_MAX_CANON -- 1024
+ on OSX, 256 on OpenSolaris, and 1920 on FreeBSD.
+
+ This value may be discovered using fpathconf(3)::
+
+ >>> from os import fpathconf
+ >>> print(fpathconf(0, 'PC_MAX_CANON'))
+ 256
+
+ On such a system, only 256 bytes may be received per line. Any
+ subsequent bytes received will be discarded. BEL (``'\a'``) is then
+ sent to output if IMAXBEL (termios.h) is set by the tty driver.
+ This is usually enabled by default. Linux does not honor this as
+ an option -- it behaves as though it is always set on.
+
+ Canonical input processing may be disabled altogether by executing
+ a shell, then stty(1), before executing the final program::
+
+ >>> bash = pexpect.spawn('/bin/bash', echo=False)
+ >>> bash.sendline('stty -icanon')
+ >>> bash.sendline('base64')
+ >>> bash.sendline('x' * 5000)
+ '''
+
+ if self.delaybeforesend is not None:
+ time.sleep(self.delaybeforesend)
+
+ s = self._coerce_send_string(s)
+ self._log(s, 'send')
+
+ b = self._encoder.encode(s, final=False)
+ return os.write(self.child_fd, b)
+
+ def sendline(self, s=''):
+ '''Wraps send(), sending string ``s`` to child process, with
+ ``os.linesep`` automatically appended. Returns number of bytes
+ written. Only a limited number of bytes may be sent for each
+ line in the default terminal mode, see docstring of :meth:`send`.
+ '''
+ s = self._coerce_send_string(s)
+ return self.send(s + self.linesep)
+
+ def _log_control(self, s):
+ """Write control characters to the appropriate log files"""
+ if self.encoding is not None:
+ s = s.decode(self.encoding, 'replace')
+ self._log(s, 'send')
+
+ def sendcontrol(self, char):
+ '''Helper method that wraps send() with mnemonic access for sending control
+ character to the child (such as Ctrl-C or Ctrl-D). For example, to send
+ Ctrl-G (ASCII 7, bell, '\a')::
+
+ child.sendcontrol('g')
+
+ See also, sendintr() and sendeof().
+ '''
+ n, byte = self.ptyproc.sendcontrol(char)
+ self._log_control(byte)
+ return n
+
+ def sendeof(self):
+ '''This sends an EOF to the child. This sends a character which causes
+ the pending parent output buffer to be sent to the waiting child
+ program without waiting for end-of-line. If it is the first character
+ of the line, the read() in the user program returns 0, which signifies
+ end-of-file. This means to work as expected a sendeof() has to be
+ called at the beginning of a line. This method does not send a newline.
+ It is the responsibility of the caller to ensure the eof is sent at the
+ beginning of a line. '''
+
+ n, byte = self.ptyproc.sendeof()
+ self._log_control(byte)
+
+ def sendintr(self):
+ '''This sends a SIGINT to the child. It does not require
+ the SIGINT to be the first character on a line. '''
+
+ n, byte = self.ptyproc.sendintr()
+ self._log_control(byte)
+
+ @property
+ def flag_eof(self):
+ return self.ptyproc.flag_eof
+
+ @flag_eof.setter
+ def flag_eof(self, value):
+ self.ptyproc.flag_eof = value
+
+ def eof(self):
+ '''This returns True if the EOF exception was ever raised.
+ '''
+ return self.flag_eof
+
+ def terminate(self, force=False):
+ '''This forces a child process to terminate. It starts nicely with
+ SIGHUP and SIGINT. If "force" is True then moves onto SIGKILL. This
+ returns True if the child was terminated. This returns False if the
+ child could not be terminated. '''
+
+ if not self.isalive():
+ return True
+ try:
+ self.kill(signal.SIGHUP)
+ time.sleep(self.delayafterterminate)
+ if not self.isalive():
+ return True
+ self.kill(signal.SIGCONT)
+ time.sleep(self.delayafterterminate)
+ if not self.isalive():
+ return True
+ self.kill(signal.SIGINT)
+ time.sleep(self.delayafterterminate)
+ if not self.isalive():
+ return True
+ if force:
+ self.kill(signal.SIGKILL)
+ time.sleep(self.delayafterterminate)
+ if not self.isalive():
+ return True
+ else:
+ return False
+ return False
+ except OSError:
+ # I think there are kernel timing issues that sometimes cause
+ # this to happen. I think isalive() reports True, but the
+ # process is dead to the kernel.
+ # Make one last attempt to see if the kernel is up to date.
+ time.sleep(self.delayafterterminate)
+ if not self.isalive():
+ return True
+ else:
+ return False
+
+ def wait(self):
+ '''This waits until the child exits. This is a blocking call. This will
+ not read any data from the child, so this will block forever if the
+ child has unread output and has terminated. In other words, the child
+ may have printed output then called exit(), but, the child is
+ technically still alive until its output is read by the parent.
+
+ This method is non-blocking if :meth:`wait` has already been called
+ previously or :meth:`isalive` method returns False. It simply returns
+ the previously determined exit status.
+ '''
+
+ ptyproc = self.ptyproc
+ with _wrap_ptyprocess_err():
+ # exception may occur if "Is some other process attempting
+ # "job control with our child pid?"
+ exitstatus = ptyproc.wait()
+ self.status = ptyproc.status
+ self.exitstatus = ptyproc.exitstatus
+ self.signalstatus = ptyproc.signalstatus
+ self.terminated = True
+
+ return exitstatus
+
+ def isalive(self):
+ '''This tests if the child process is running or not. This is
+ non-blocking. If the child was terminated then this will read the
+ exitstatus or signalstatus of the child. This returns True if the child
+ process appears to be running or False if not. It can take literally
+ SECONDS for Solaris to return the right status. '''
+
+ ptyproc = self.ptyproc
+ with _wrap_ptyprocess_err():
+ alive = ptyproc.isalive()
+
+ if not alive:
+ self.status = ptyproc.status
+ self.exitstatus = ptyproc.exitstatus
+ self.signalstatus = ptyproc.signalstatus
+ self.terminated = True
+
+ return alive
+
+ def kill(self, sig):
+
+ '''This sends the given signal to the child application. In keeping
+ with UNIX tradition it has a misleading name. It does not necessarily
+ kill the child unless you send the right signal. '''
+
+ # Same as os.kill, but the pid is given for you.
+ if self.isalive():
+ os.kill(self.pid, sig)
+
+ def getwinsize(self):
+ '''This returns the terminal window size of the child tty. The return
+ value is a tuple of (rows, cols). '''
+ return self.ptyproc.getwinsize()
+
+ def setwinsize(self, rows, cols):
+ '''This sets the terminal window size of the child tty. This will cause
+ a SIGWINCH signal to be sent to the child. This does not change the
+ physical window size. It changes the size reported to TTY-aware
+ applications like vi or curses -- applications that respond to the
+ SIGWINCH signal. '''
+ return self.ptyproc.setwinsize(rows, cols)
+
+
+ def interact(self, escape_character=chr(29),
+ input_filter=None, output_filter=None):
+
+ '''This gives control of the child process to the interactive user (the
+ human at the keyboard). Keystrokes are sent to the child process, and
+ the stdout and stderr output of the child process is printed. This
+ simply echos the child stdout and child stderr to the real stdout and
+ it echos the real stdin to the child stdin. When the user types the
+ escape_character this method will return None. The escape_character
+ will not be transmitted. The default for escape_character is
+ entered as ``Ctrl - ]``, the very same as BSD telnet. To prevent
+ escaping, escape_character may be set to None.
+
+ If a logfile is specified, then the data sent and received from the
+ child process in interact mode is duplicated to the given log.
+
+ You may pass in optional input and output filter functions. These
+ functions should take a string and return a string. The output_filter
+ will be passed all the output from the child process. The input_filter
+ will be passed all the keyboard input from the user. The input_filter
+ is run BEFORE the check for the escape_character.
+
+ Note that if you change the window size of the parent the SIGWINCH
+ signal will not be passed through to the child. If you want the child
+ window size to change when the parent's window size changes then do
+ something like the following example::
+
+ import pexpect, struct, fcntl, termios, signal, sys
+ def sigwinch_passthrough (sig, data):
+ s = struct.pack("HHHH", 0, 0, 0, 0)
+ a = struct.unpack('hhhh', fcntl.ioctl(sys.stdout.fileno(),
+ termios.TIOCGWINSZ , s))
+ if not p.closed:
+ p.setwinsize(a[0],a[1])
+
+ # Note this 'p' is global and used in sigwinch_passthrough.
+ p = pexpect.spawn('/bin/bash')
+ signal.signal(signal.SIGWINCH, sigwinch_passthrough)
+ p.interact()
+ '''
+
+ # Flush the buffer.
+ self.write_to_stdout(self.buffer)
+ self.stdout.flush()
+ self._buffer = self.buffer_type()
+ mode = tty.tcgetattr(self.STDIN_FILENO)
+ tty.setraw(self.STDIN_FILENO)
+ if escape_character is not None and PY3:
+ escape_character = escape_character.encode('latin-1')
+ try:
+ self.__interact_copy(escape_character, input_filter, output_filter)
+ finally:
+ tty.tcsetattr(self.STDIN_FILENO, tty.TCSAFLUSH, mode)
+
+ def __interact_writen(self, fd, data):
+ '''This is used by the interact() method.
+ '''
+
+ while data != b'' and self.isalive():
+ n = os.write(fd, data)
+ data = data[n:]
+
+ def __interact_read(self, fd):
+ '''This is used by the interact() method.
+ '''
+
+ return os.read(fd, 1000)
+
+ def __interact_copy(
+ self, escape_character=None, input_filter=None, output_filter=None
+ ):
+
+ '''This is used by the interact() method.
+ '''
+
+ while self.isalive():
+ if self.use_poll:
+ r = poll_ignore_interrupts([self.child_fd, self.STDIN_FILENO])
+ else:
+ r, w, e = select_ignore_interrupts(
+ [self.child_fd, self.STDIN_FILENO], [], []
+ )
+ if self.child_fd in r:
+ try:
+ data = self.__interact_read(self.child_fd)
+ except OSError as err:
+ if err.args[0] == errno.EIO:
+ # Linux-style EOF
+ break
+ raise
+ if data == b'':
+ # BSD-style EOF
+ break
+ if output_filter:
+ data = output_filter(data)
+ self._log(data, 'read')
+ os.write(self.STDOUT_FILENO, data)
+ if self.STDIN_FILENO in r:
+ data = self.__interact_read(self.STDIN_FILENO)
+ if input_filter:
+ data = input_filter(data)
+ i = -1
+ if escape_character is not None:
+ i = data.rfind(escape_character)
+ if i != -1:
+ data = data[:i]
+ if data:
+ self._log(data, 'send')
+ self.__interact_writen(self.child_fd, data)
+ break
+ self._log(data, 'send')
+ self.__interact_writen(self.child_fd, data)
+
+
+def spawnu(*args, **kwargs):
+ """Deprecated: pass encoding to spawn() instead."""
+ kwargs.setdefault('encoding', 'utf-8')
+ return spawn(*args, **kwargs)
Index: third_party/Python/module/pexpect-4.6/pexpect/pxssh.py
===================================================================
--- third_party/Python/module/pexpect-4.6/pexpect/pxssh.py
+++ third_party/Python/module/pexpect-4.6/pexpect/pxssh.py
@@ -0,0 +1,499 @@
+'''This class extends pexpect.spawn to specialize setting up SSH connections.
+This adds methods for login, logout, and expecting the shell prompt.
+
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+from pexpect import ExceptionPexpect, TIMEOUT, EOF, spawn
+import time
+import os
+import sys
+import re
+
+__all__ = ['ExceptionPxssh', 'pxssh']
+
+# Exception classes used by this module.
+class ExceptionPxssh(ExceptionPexpect):
+ '''Raised for pxssh exceptions.
+ '''
+
+if sys.version_info > (3, 0):
+ from shlex import quote
+else:
+ _find_unsafe = re.compile(r'[^\w@%+=:,./-]').search
+
+ def quote(s):
+ """Return a shell-escaped version of the string *s*."""
+ if not s:
+ return "''"
+ if _find_unsafe(s) is None:
+ return s
+
+ # use single quotes, and put single quotes into double quotes
+ # the string $'b is then quoted as '$'"'"'b'
+ return "'" + s.replace("'", "'\"'\"'") + "'"
+
+class pxssh (spawn):
+ '''This class extends pexpect.spawn to specialize setting up SSH
+ connections. This adds methods for login, logout, and expecting the shell
+ prompt. It does various tricky things to handle many situations in the SSH
+ login process. For example, if the session is your first login, then pxssh
+ automatically accepts the remote certificate; or if you have public key
+ authentication setup then pxssh won't wait for the password prompt.
+
+ pxssh uses the shell prompt to synchronize output from the remote host. In
+ order to make this more robust it sets the shell prompt to something more
+ unique than just $ or #. This should work on most Borne/Bash or Csh style
+ shells.
+
+ Example that runs a few commands on a remote server and prints the result::
+
+ from pexpect import pxssh
+ import getpass
+ try:
+ s = pxssh.pxssh()
+ hostname = raw_input('hostname: ')
+ username = raw_input('username: ')
+ password = getpass.getpass('password: ')
+ s.login(hostname, username, password)
+ s.sendline('uptime') # run a command
+ s.prompt() # match the prompt
+ print(s.before) # print everything before the prompt.
+ s.sendline('ls -l')
+ s.prompt()
+ print(s.before)
+ s.sendline('df')
+ s.prompt()
+ print(s.before)
+ s.logout()
+ except pxssh.ExceptionPxssh as e:
+ print("pxssh failed on login.")
+ print(e)
+
+ Example showing how to specify SSH options::
+
+ from pexpect import pxssh
+ s = pxssh.pxssh(options={
+ "StrictHostKeyChecking": "no",
+ "UserKnownHostsFile": "/dev/null"})
+ ...
+
+ Note that if you have ssh-agent running while doing development with pxssh
+ then this can lead to a lot of confusion. Many X display managers (xdm,
+ gdm, kdm, etc.) will automatically start a GUI agent. You may see a GUI
+ dialog box popup asking for a password during development. You should turn
+ off any key agents during testing. The 'force_password' attribute will turn
+ off public key authentication. This will only work if the remote SSH server
+ is configured to allow password logins. Example of using 'force_password'
+ attribute::
+
+ s = pxssh.pxssh()
+ s.force_password = True
+ hostname = raw_input('hostname: ')
+ username = raw_input('username: ')
+ password = getpass.getpass('password: ')
+ s.login (hostname, username, password)
+
+ `debug_command_string` is only for the test suite to confirm that the string
+ generated for SSH is correct, using this will not allow you to do
+ anything other than get a string back from `pxssh.pxssh.login()`.
+ '''
+
+ def __init__ (self, timeout=30, maxread=2000, searchwindowsize=None,
+ logfile=None, cwd=None, env=None, ignore_sighup=True, echo=True,
+ options={}, encoding=None, codec_errors='strict',
+ debug_command_string=False):
+
+ spawn.__init__(self, None, timeout=timeout, maxread=maxread,
+ searchwindowsize=searchwindowsize, logfile=logfile,
+ cwd=cwd, env=env, ignore_sighup=ignore_sighup, echo=echo,
+ encoding=encoding, codec_errors=codec_errors)
+
+ self.name = ''
+
+ #SUBTLE HACK ALERT! Note that the command that SETS the prompt uses a
+ #slightly different string than the regular expression to match it. This
+ #is because when you set the prompt the command will echo back, but we
+ #don't want to match the echoed command. So if we make the set command
+ #slightly different than the regex we eliminate the problem. To make the
+ #set command different we add a backslash in front of $. The $ doesn't
+ #need to be escaped, but it doesn't hurt and serves to make the set
+ #prompt command different than the regex.
+
+ # used to match the command-line prompt
+ self.UNIQUE_PROMPT = r"\[PEXPECT\][\$\#] "
+ self.PROMPT = self.UNIQUE_PROMPT
+
+ # used to set shell command-line prompt to UNIQUE_PROMPT.
+ self.PROMPT_SET_SH = r"PS1='[PEXPECT]\$ '"
+ self.PROMPT_SET_CSH = r"set prompt='[PEXPECT]\$ '"
+ self.SSH_OPTS = ("-o'RSAAuthentication=no'"
+ + " -o 'PubkeyAuthentication=no'")
+# Disabling host key checking, makes you vulnerable to MITM attacks.
+# + " -o 'StrictHostKeyChecking=no'"
+# + " -o 'UserKnownHostsFile /dev/null' ")
+ # Disabling X11 forwarding gets rid of the annoying SSH_ASKPASS from
+ # displaying a GUI password dialog. I have not figured out how to
+ # disable only SSH_ASKPASS without also disabling X11 forwarding.
+ # Unsetting SSH_ASKPASS on the remote side doesn't disable it! Annoying!
+ #self.SSH_OPTS = "-x -o'RSAAuthentication=no' -o 'PubkeyAuthentication=no'"
+ self.force_password = False
+
+ self.debug_command_string = debug_command_string
+
+ # User defined SSH options, eg,
+ # ssh.otions = dict(StrictHostKeyChecking="no",UserKnownHostsFile="/dev/null")
+ self.options = options
+
+ def levenshtein_distance(self, a, b):
+ '''This calculates the Levenshtein distance between a and b.
+ '''
+
+ n, m = len(a), len(b)
+ if n > m:
+ a,b = b,a
+ n,m = m,n
+ current = range(n+1)
+ for i in range(1,m+1):
+ previous, current = current, [i]+[0]*n
+ for j in range(1,n+1):
+ add, delete = previous[j]+1, current[j-1]+1
+ change = previous[j-1]
+ if a[j-1] != b[i-1]:
+ change = change + 1
+ current[j] = min(add, delete, change)
+ return current[n]
+
+ def try_read_prompt(self, timeout_multiplier):
+ '''This facilitates using communication timeouts to perform
+ synchronization as quickly as possible, while supporting high latency
+ connections with a tunable worst case performance. Fast connections
+ should be read almost immediately. Worst case performance for this
+ method is timeout_multiplier * 3 seconds.
+ '''
+
+ # maximum time allowed to read the first response
+ first_char_timeout = timeout_multiplier * 0.5
+
+ # maximum time allowed between subsequent characters
+ inter_char_timeout = timeout_multiplier * 0.1
+
+ # maximum time for reading the entire prompt
+ total_timeout = timeout_multiplier * 3.0
+
+ prompt = self.string_type()
+ begin = time.time()
+ expired = 0.0
+ timeout = first_char_timeout
+
+ while expired < total_timeout:
+ try:
+ prompt += self.read_nonblocking(size=1, timeout=timeout)
+ expired = time.time() - begin # updated total time expired
+ timeout = inter_char_timeout
+ except TIMEOUT:
+ break
+
+ return prompt
+
+ def sync_original_prompt (self, sync_multiplier=1.0):
+ '''This attempts to find the prompt. Basically, press enter and record
+ the response; press enter again and record the response; if the two
+ responses are similar then assume we are at the original prompt.
+ This can be a slow function. Worst case with the default sync_multiplier
+ can take 12 seconds. Low latency connections are more likely to fail
+ with a low sync_multiplier. Best case sync time gets worse with a
+ high sync multiplier (500 ms with default). '''
+
+ # All of these timing pace values are magic.
+ # I came up with these based on what seemed reliable for
+ # connecting to a heavily loaded machine I have.
+ self.sendline()
+ time.sleep(0.1)
+
+ try:
+ # Clear the buffer before getting the prompt.
+ self.try_read_prompt(sync_multiplier)
+ except TIMEOUT:
+ pass
+
+ self.sendline()
+ x = self.try_read_prompt(sync_multiplier)
+
+ self.sendline()
+ a = self.try_read_prompt(sync_multiplier)
+
+ self.sendline()
+ b = self.try_read_prompt(sync_multiplier)
+
+ ld = self.levenshtein_distance(a,b)
+ len_a = len(a)
+ if len_a == 0:
+ return False
+ if float(ld)/len_a < 0.4:
+ return True
+ return False
+
+ ### TODO: This is getting messy and I'm pretty sure this isn't perfect.
+ ### TODO: I need to draw a flow chart for this.
+ ### TODO: Unit tests for SSH tunnels, remote SSH command exec, disabling original prompt sync
+ def login (self, server, username, password='', terminal_type='ansi',
+ original_prompt=r"[#$]", login_timeout=10, port=None,
+ auto_prompt_reset=True, ssh_key=None, quiet=True,
+ sync_multiplier=1, check_local_ip=True,
+ password_regex=r'(?i)(?:password:)|(?:passphrase for key)',
+ ssh_tunnels={}, spawn_local_ssh=True,
+ sync_original_prompt=True, ssh_config=None):
+ '''This logs the user into the given server.
+
+ It uses
+ 'original_prompt' to try to find the prompt right after login. When it
+ finds the prompt it immediately tries to reset the prompt to something
+ more easily matched. The default 'original_prompt' is very optimistic
+ and is easily fooled. It's more reliable to try to match the original
+ prompt as exactly as possible to prevent false matches by server
+ strings such as the "Message Of The Day". On many systems you can
+ disable the MOTD on the remote server by creating a zero-length file
+ called :file:`~/.hushlogin` on the remote server. If a prompt cannot be found
+ then this will not necessarily cause the login to fail. In the case of
+ a timeout when looking for the prompt we assume that the original
+ prompt was so weird that we could not match it, so we use a few tricks
+ to guess when we have reached the prompt. Then we hope for the best and
+ blindly try to reset the prompt to something more unique. If that fails
+ then login() raises an :class:`ExceptionPxssh` exception.
+
+ In some situations it is not possible or desirable to reset the
+ original prompt. In this case, pass ``auto_prompt_reset=False`` to
+ inhibit setting the prompt to the UNIQUE_PROMPT. Remember that pxssh
+ uses a unique prompt in the :meth:`prompt` method. If the original prompt is
+ not reset then this will disable the :meth:`prompt` method unless you
+ manually set the :attr:`PROMPT` attribute.
+
+ Set ``password_regex`` if there is a MOTD message with `password` in it.
+ Changing this is like playing in traffic, don't (p)expect it to match straight
+ away.
+
+ If you require to connect to another SSH server from the your original SSH
+ connection set ``spawn_local_ssh`` to `False` and this will use your current
+ session to do so. Setting this option to `False` and not having an active session
+ will trigger an error.
+
+ Set ``ssh_key`` to a file path to an SSH private key to use that SSH key
+ for the session authentication.
+ Set ``ssh_key`` to `True` to force passing the current SSH authentication socket
+ to the desired ``hostname``.
+
+ Set ``ssh_config`` to a file path string of an SSH client config file to pass that
+ file to the client to handle itself. You may set any options you wish in here, however
+ doing so will require you to post extra information that you may not want to if you
+ run into issues.
+ '''
+
+ session_regex_array = ["(?i)are you sure you want to continue connecting", original_prompt, password_regex, "(?i)permission denied", "(?i)terminal type", TIMEOUT]
+ session_init_regex_array = []
+ session_init_regex_array.extend(session_regex_array)
+ session_init_regex_array.extend(["(?i)connection closed by remote host", EOF])
+
+ ssh_options = ''.join([" -o '%s=%s'" % (o, v) for (o, v) in self.options.items()])
+ if quiet:
+ ssh_options = ssh_options + ' -q'
+ if not check_local_ip:
+ ssh_options = ssh_options + " -o'NoHostAuthenticationForLocalhost=yes'"
+ if self.force_password:
+ ssh_options = ssh_options + ' ' + self.SSH_OPTS
+ if ssh_config is not None:
+ if spawn_local_ssh and not os.path.isfile(ssh_config):
+ raise ExceptionPxssh('SSH config does not exist or is not a file.')
+ ssh_options = ssh_options + '-F ' + ssh_config
+ if port is not None:
+ ssh_options = ssh_options + ' -p %s'%(str(port))
+ if ssh_key is not None:
+ # Allow forwarding our SSH key to the current session
+ if ssh_key==True:
+ ssh_options = ssh_options + ' -A'
+ else:
+ if spawn_local_ssh and not os.path.isfile(ssh_key):
+ raise ExceptionPxssh('private ssh key does not exist or is not a file.')
+ ssh_options = ssh_options + ' -i %s' % (ssh_key)
+
+ # SSH tunnels, make sure you know what you're putting into the lists
+ # under each heading. Do not expect these to open 100% of the time,
+ # The port you're requesting might be bound.
+ #
+ # The structure should be like this:
+ # { 'local': ['2424:localhost:22'], # Local SSH tunnels
+ # 'remote': ['2525:localhost:22'], # Remote SSH tunnels
+ # 'dynamic': [8888] } # Dynamic/SOCKS tunnels
+ if ssh_tunnels!={} and isinstance({},type(ssh_tunnels)):
+ tunnel_types = {
+ 'local':'L',
+ 'remote':'R',
+ 'dynamic':'D'
+ }
+ for tunnel_type in tunnel_types:
+ cmd_type = tunnel_types[tunnel_type]
+ if tunnel_type in ssh_tunnels:
+ tunnels = ssh_tunnels[tunnel_type]
+ for tunnel in tunnels:
+ if spawn_local_ssh==False:
+ tunnel = quote(str(tunnel))
+ ssh_options = ssh_options + ' -' + cmd_type + ' ' + str(tunnel)
+ cmd = "ssh %s -l %s %s" % (ssh_options, username, server)
+ if self.debug_command_string:
+ return(cmd)
+
+ # Are we asking for a local ssh command or to spawn one in another session?
+ if spawn_local_ssh:
+ spawn._spawn(self, cmd)
+ else:
+ self.sendline(cmd)
+
+ # This does not distinguish between a remote server 'password' prompt
+ # and a local ssh 'passphrase' prompt (for unlocking a private key).
+ i = self.expect(session_init_regex_array, timeout=login_timeout)
+
+ # First phase
+ if i==0:
+ # New certificate -- always accept it.
+ # This is what you get if SSH does not have the remote host's
+ # public key stored in the 'known_hosts' cache.
+ self.sendline("yes")
+ i = self.expect(session_regex_array)
+ if i==2: # password or passphrase
+ self.sendline(password)
+ i = self.expect(session_regex_array)
+ if i==4:
+ self.sendline(terminal_type)
+ i = self.expect(session_regex_array)
+ if i==7:
+ self.close()
+ raise ExceptionPxssh('Could not establish connection to host')
+
+ # Second phase
+ if i==0:
+ # This is weird. This should not happen twice in a row.
+ self.close()
+ raise ExceptionPxssh('Weird error. Got "are you sure" prompt twice.')
+ elif i==1: # can occur if you have a public key pair set to authenticate.
+ ### TODO: May NOT be OK if expect() got tricked and matched a false prompt.
+ pass
+ elif i==2: # password prompt again
+ # For incorrect passwords, some ssh servers will
+ # ask for the password again, others return 'denied' right away.
+ # If we get the password prompt again then this means
+ # we didn't get the password right the first time.
+ self.close()
+ raise ExceptionPxssh('password refused')
+ elif i==3: # permission denied -- password was bad.
+ self.close()
+ raise ExceptionPxssh('permission denied')
+ elif i==4: # terminal type again? WTF?
+ self.close()
+ raise ExceptionPxssh('Weird error. Got "terminal type" prompt twice.')
+ elif i==5: # Timeout
+ #This is tricky... I presume that we are at the command-line prompt.
+ #It may be that the shell prompt was so weird that we couldn't match
+ #it. Or it may be that we couldn't log in for some other reason. I
+ #can't be sure, but it's safe to guess that we did login because if
+ #I presume wrong and we are not logged in then this should be caught
+ #later when I try to set the shell prompt.
+ pass
+ elif i==6: # Connection closed by remote host
+ self.close()
+ raise ExceptionPxssh('connection closed')
+ else: # Unexpected
+ self.close()
+ raise ExceptionPxssh('unexpected login response')
+ if sync_original_prompt:
+ if not self.sync_original_prompt(sync_multiplier):
+ self.close()
+ raise ExceptionPxssh('could not synchronize with original prompt')
+ # We appear to be in.
+ # set shell prompt to something unique.
+ if auto_prompt_reset:
+ if not self.set_unique_prompt():
+ self.close()
+ raise ExceptionPxssh('could not set shell prompt '
+ '(received: %r, expected: %r).' % (
+ self.before, self.PROMPT,))
+ return True
+
+ def logout (self):
+ '''Sends exit to the remote shell.
+
+ If there are stopped jobs then this automatically sends exit twice.
+ '''
+ self.sendline("exit")
+ index = self.expect([EOF, "(?i)there are stopped jobs"])
+ if index==1:
+ self.sendline("exit")
+ self.expect(EOF)
+ self.close()
+
+ def prompt(self, timeout=-1):
+ '''Match the next shell prompt.
+
+ This is little more than a short-cut to the :meth:`~pexpect.spawn.expect`
+ method. Note that if you called :meth:`login` with
+ ``auto_prompt_reset=False``, then before calling :meth:`prompt` you must
+ set the :attr:`PROMPT` attribute to a regex that it will use for
+ matching the prompt.
+
+ Calling :meth:`prompt` will erase the contents of the :attr:`before`
+ attribute even if no prompt is ever matched. If timeout is not given or
+ it is set to -1 then self.timeout is used.
+
+ :return: True if the shell prompt was matched, False if the timeout was
+ reached.
+ '''
+
+ if timeout == -1:
+ timeout = self.timeout
+ i = self.expect([self.PROMPT, TIMEOUT], timeout=timeout)
+ if i==1:
+ return False
+ return True
+
+ def set_unique_prompt(self):
+ '''This sets the remote prompt to something more unique than ``#`` or ``$``.
+ This makes it easier for the :meth:`prompt` method to match the shell prompt
+ unambiguously. This method is called automatically by the :meth:`login`
+ method, but you may want to call it manually if you somehow reset the
+ shell prompt. For example, if you 'su' to a different user then you
+ will need to manually reset the prompt. This sends shell commands to
+ the remote host to set the prompt, so this assumes the remote host is
+ ready to receive commands.
+
+ Alternatively, you may use your own prompt pattern. In this case you
+ should call :meth:`login` with ``auto_prompt_reset=False``; then set the
+ :attr:`PROMPT` attribute to a regular expression. After that, the
+ :meth:`prompt` method will try to match your prompt pattern.
+ '''
+
+ self.sendline("unset PROMPT_COMMAND")
+ self.sendline(self.PROMPT_SET_SH) # sh-style
+ i = self.expect ([TIMEOUT, self.PROMPT], timeout=10)
+ if i == 0: # csh-style
+ self.sendline(self.PROMPT_SET_CSH)
+ i = self.expect([TIMEOUT, self.PROMPT], timeout=10)
+ if i == 0:
+ return False
+ return True
+
+# vi:ts=4:sw=4:expandtab:ft=python:
Index: third_party/Python/module/pexpect-4.6/pexpect/replwrap.py
===================================================================
--- third_party/Python/module/pexpect-4.6/pexpect/replwrap.py
+++ third_party/Python/module/pexpect-4.6/pexpect/replwrap.py
@@ -0,0 +1,122 @@
+"""Generic wrapper for read-eval-print-loops, a.k.a. interactive shells
+"""
+import os.path
+import signal
+import sys
+
+import pexpect
+
+PY3 = (sys.version_info[0] >= 3)
+
+if PY3:
+ basestring = str
+
+PEXPECT_PROMPT = u'[PEXPECT_PROMPT>'
+PEXPECT_CONTINUATION_PROMPT = u'[PEXPECT_PROMPT+'
+
+class REPLWrapper(object):
+ """Wrapper for a REPL.
+
+ :param cmd_or_spawn: This can either be an instance of :class:`pexpect.spawn`
+ in which a REPL has already been started, or a str command to start a new
+ REPL process.
+ :param str orig_prompt: The prompt to expect at first.
+ :param str prompt_change: A command to change the prompt to something more
+ unique. If this is ``None``, the prompt will not be changed. This will
+ be formatted with the new and continuation prompts as positional
+ parameters, so you can use ``{}`` style formatting to insert them into
+ the command.
+ :param str new_prompt: The more unique prompt to expect after the change.
+ :param str extra_init_cmd: Commands to do extra initialisation, such as
+ disabling pagers.
+ """
+ def __init__(self, cmd_or_spawn, orig_prompt, prompt_change,
+ new_prompt=PEXPECT_PROMPT,
+ continuation_prompt=PEXPECT_CONTINUATION_PROMPT,
+ extra_init_cmd=None):
+ if isinstance(cmd_or_spawn, basestring):
+ self.child = pexpect.spawn(cmd_or_spawn, echo=False, encoding='utf-8')
+ else:
+ self.child = cmd_or_spawn
+ if self.child.echo:
+ # Existing spawn instance has echo enabled, disable it
+ # to prevent our input from being repeated to output.
+ self.child.setecho(False)
+ self.child.waitnoecho()
+
+ if prompt_change is None:
+ self.prompt = orig_prompt
+ else:
+ self.set_prompt(orig_prompt,
+ prompt_change.format(new_prompt, continuation_prompt))
+ self.prompt = new_prompt
+ self.continuation_prompt = continuation_prompt
+
+ self._expect_prompt()
+
+ if extra_init_cmd is not None:
+ self.run_command(extra_init_cmd)
+
+ def set_prompt(self, orig_prompt, prompt_change):
+ self.child.expect(orig_prompt)
+ self.child.sendline(prompt_change)
+
+ def _expect_prompt(self, timeout=-1):
+ return self.child.expect_exact([self.prompt, self.continuation_prompt],
+ timeout=timeout)
+
+ def run_command(self, command, timeout=-1):
+ """Send a command to the REPL, wait for and return output.
+
+ :param str command: The command to send. Trailing newlines are not needed.
+ This should be a complete block of input that will trigger execution;
+ if a continuation prompt is found after sending input, :exc:`ValueError`
+ will be raised.
+ :param int timeout: How long to wait for the next prompt. -1 means the
+ default from the :class:`pexpect.spawn` object (default 30 seconds).
+ None means to wait indefinitely.
+ """
+ # Split up multiline commands and feed them in bit-by-bit
+ cmdlines = command.splitlines()
+ # splitlines ignores trailing newlines - add it back in manually
+ if command.endswith('\n'):
+ cmdlines.append('')
+ if not cmdlines:
+ raise ValueError("No command was given")
+
+ res = []
+ self.child.sendline(cmdlines[0])
+ for line in cmdlines[1:]:
+ self._expect_prompt(timeout=timeout)
+ res.append(self.child.before)
+ self.child.sendline(line)
+
+ # Command was fully submitted, now wait for the next prompt
+ if self._expect_prompt(timeout=timeout) == 1:
+ # We got the continuation prompt - command was incomplete
+ self.child.kill(signal.SIGINT)
+ self._expect_prompt(timeout=1)
+ raise ValueError("Continuation prompt found - input was incomplete:\n"
+ + command)
+ return u''.join(res + [self.child.before])
+
+def python(command="python"):
+ """Start a Python shell and return a :class:`REPLWrapper` object."""
+ return REPLWrapper(command, u">>> ", u"import sys; sys.ps1={0!r}; sys.ps2={1!r}")
+
+def bash(command="bash"):
+ """Start a bash shell and return a :class:`REPLWrapper` object."""
+ bashrc = os.path.join(os.path.dirname(__file__), 'bashrc.sh')
+ child = pexpect.spawn(command, ['--rcfile', bashrc], echo=False,
+ encoding='utf-8')
+
+ # If the user runs 'env', the value of PS1 will be in the output. To avoid
+ # replwrap seeing that as the next prompt, we'll embed the marker characters
+ # for invisible characters in the prompt; these show up when inspecting the
+ # environment variable, but not when bash displays the prompt.
+ ps1 = PEXPECT_PROMPT[:5] + u'\\[\\]' + PEXPECT_PROMPT[5:]
+ ps2 = PEXPECT_CONTINUATION_PROMPT[:5] + u'\\[\\]' + PEXPECT_CONTINUATION_PROMPT[5:]
+ prompt_change = u"PS1='{0}' PS2='{1}' PROMPT_COMMAND=''".format(ps1, ps2)
+
+ return REPLWrapper(child, u'\\$', prompt_change,
+ extra_init_cmd="export PAGER=cat")
Index: third_party/Python/module/pexpect-4.6/pexpect/run.py
===================================================================
--- third_party/Python/module/pexpect-4.6/pexpect/run.py
+++ third_party/Python/module/pexpect-4.6/pexpect/run.py
@@ -0,0 +1,157 @@
+import sys
+import types
+
+from .exceptions import EOF, TIMEOUT
+from .pty_spawn import spawn
+
+def run(command, timeout=30, withexitstatus=False, events=None,
+ extra_args=None, logfile=None, cwd=None, env=None, **kwargs):
+
+ '''
+ This function runs the given command; waits for it to finish; then
+ returns all output as a string. STDERR is included in output. If the full
+ path to the command is not given then the path is searched.
+
+ Note that lines are terminated by CR/LF (\\r\\n) combination even on
+ UNIX-like systems because this is the standard for pseudottys. If you set
+ 'withexitstatus' to true, then run will return a tuple of (command_output,
+ exitstatus). If 'withexitstatus' is false then this returns just
+ command_output.
+
+ The run() function can often be used instead of creating a spawn instance.
+ For example, the following code uses spawn::
+
+ from pexpect import *
+ child = spawn('scp foo user@example.com:.')
+ child.expect('(?i)password')
+ child.sendline(mypassword)
+
+ The previous code can be replace with the following::
+
+ from pexpect import *
+ run('scp foo user@example.com:.', events={'(?i)password': mypassword})
+
+ **Examples**
+
+ Start the apache daemon on the local machine::
+
+ from pexpect import *
+ run("/usr/local/apache/bin/apachectl start")
+
+ Check in a file using SVN::
+
+ from pexpect import *
+ run("svn ci -m 'automatic commit' my_file.py")
+
+ Run a command and capture exit status::
+
+ from pexpect import *
+ (command_output, exitstatus) = run('ls -l /bin', withexitstatus=1)
+
+ The following will run SSH and execute 'ls -l' on the remote machine. The
+ password 'secret' will be sent if the '(?i)password' pattern is ever seen::
+
+ run("ssh username@machine.example.com 'ls -l'",
+ events={'(?i)password':'secret\\n'})
+
+ This will start mencoder to rip a video from DVD. This will also display
+ progress ticks every 5 seconds as it runs. For example::
+
+ from pexpect import *
+ def print_ticks(d):
+ print d['event_count'],
+ run("mencoder dvd://1 -o video.avi -oac copy -ovc copy",
+ events={TIMEOUT:print_ticks}, timeout=5)
+
+ The 'events' argument should be either a dictionary or a tuple list that
+ contains patterns and responses. Whenever one of the patterns is seen
+ in the command output, run() will send the associated response string.
+ So, run() in the above example can be also written as:
+
+ run("mencoder dvd://1 -o video.avi -oac copy -ovc copy",
+ events=[(TIMEOUT,print_ticks)], timeout=5)
+
+ Use a tuple list for events if the command output requires a delicate
+ control over what pattern should be matched, since the tuple list is passed
+ to pexpect() as its pattern list, with the order of patterns preserved.
+
+ Note that you should put newlines in your string if Enter is necessary.
+
+ Like the example above, the responses may also contain a callback, either
+ a function or method. It should accept a dictionary value as an argument.
+ The dictionary contains all the locals from the run() function, so you can
+ access the child spawn object or any other variable defined in run()
+ (event_count, child, and extra_args are the most useful). A callback may
+ return True to stop the current run process. Otherwise run() continues
+ until the next event. A callback may also return a string which will be
+ sent to the child. 'extra_args' is not used by directly run(). It provides
+ a way to pass data to a callback function through run() through the locals
+ dictionary passed to a callback.
+
+ Like :class:`spawn`, passing *encoding* will make it work with unicode
+ instead of bytes. You can pass *codec_errors* to control how errors in
+ encoding and decoding are handled.
+ '''
+ if timeout == -1:
+ child = spawn(command, maxread=2000, logfile=logfile, cwd=cwd, env=env,
+ **kwargs)
+ else:
+ child = spawn(command, timeout=timeout, maxread=2000, logfile=logfile,
+ cwd=cwd, env=env, **kwargs)
+ if isinstance(events, list):
+ patterns= [x for x,y in events]
+ responses = [y for x,y in events]
+ elif isinstance(events, dict):
+ patterns = list(events.keys())
+ responses = list(events.values())
+ else:
+ # This assumes EOF or TIMEOUT will eventually cause run to terminate.
+ patterns = None
+ responses = None
+ child_result_list = []
+ event_count = 0
+ while True:
+ try:
+ index = child.expect(patterns)
+ if isinstance(child.after, child.allowed_string_types):
+ child_result_list.append(child.before + child.after)
+ else:
+ # child.after may have been a TIMEOUT or EOF,
+ # which we don't want appended to the list.
+ child_result_list.append(child.before)
+ if isinstance(responses[index], child.allowed_string_types):
+ child.send(responses[index])
+ elif (isinstance(responses[index], types.FunctionType) or
+ isinstance(responses[index], types.MethodType)):
+ callback_result = responses[index](locals())
+ sys.stdout.flush()
+ if isinstance(callback_result, child.allowed_string_types):
+ child.send(callback_result)
+ elif callback_result:
+ break
+ else:
+ raise TypeError("parameter `event' at index {index} must be "
+ "a string, method, or function: {value!r}"
+ .format(index=index, value=responses[index]))
+ event_count = event_count + 1
+ except TIMEOUT:
+ child_result_list.append(child.before)
+ break
+ except EOF:
+ child_result_list.append(child.before)
+ break
+ child_result = child.string_type().join(child_result_list)
+ if withexitstatus:
+ child.close()
+ return (child_result, child.exitstatus)
+ else:
+ return child_result
+
+def runu(command, timeout=30, withexitstatus=False, events=None,
+ extra_args=None, logfile=None, cwd=None, env=None, **kwargs):
+ """Deprecated: pass encoding to run() instead.
+ """
+ kwargs.setdefault('encoding', 'utf-8')
+ return run(command, timeout=timeout, withexitstatus=withexitstatus,
+ events=events, extra_args=extra_args, logfile=logfile, cwd=cwd,
+ env=env, **kwargs)
Index: third_party/Python/module/pexpect-4.6/pexpect/screen.py
===================================================================
--- third_party/Python/module/pexpect-4.6/pexpect/screen.py
+++ third_party/Python/module/pexpect-4.6/pexpect/screen.py
@@ -0,0 +1,431 @@
+'''This implements a virtual screen. This is used to support ANSI terminal
+emulation. The screen representation and state is implemented in this class.
+Most of the methods are inspired by ANSI screen control codes. The
+:class:`~pexpect.ANSI.ANSI` class extends this class to add parsing of ANSI
+escape codes.
+
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+import codecs
+import copy
+import sys
+
+import warnings
+
+warnings.warn(("pexpect.screen and pexpect.ANSI are deprecated. "
+ "We recommend using pyte to emulate a terminal screen: "
+ "https://pypi.python.org/pypi/pyte"),
+ stacklevel=2)
+
+NUL = 0 # Fill character; ignored on input.
+ENQ = 5 # Transmit answerback message.
+BEL = 7 # Ring the bell.
+BS = 8 # Move cursor left.
+HT = 9 # Move cursor to next tab stop.
+LF = 10 # Line feed.
+VT = 11 # Same as LF.
+FF = 12 # Same as LF.
+CR = 13 # Move cursor to left margin or newline.
+SO = 14 # Invoke G1 character set.
+SI = 15 # Invoke G0 character set.
+XON = 17 # Resume transmission.
+XOFF = 19 # Halt transmission.
+CAN = 24 # Cancel escape sequence.
+SUB = 26 # Same as CAN.
+ESC = 27 # Introduce a control sequence.
+DEL = 127 # Fill character; ignored on input.
+SPACE = u' ' # Space or blank character.
+
+PY3 = (sys.version_info[0] >= 3)
+if PY3:
+ unicode = str
+
+def constrain (n, min, max):
+
+ '''This returns a number, n constrained to the min and max bounds. '''
+
+ if n < min:
+ return min
+ if n > max:
+ return max
+ return n
+
+class screen:
+ '''This object maintains the state of a virtual text screen as a
+ rectangular array. This maintains a virtual cursor position and handles
+ scrolling as characters are added. This supports most of the methods needed
+ by an ANSI text screen. Row and column indexes are 1-based (not zero-based,
+ like arrays).
+
+ Characters are represented internally using unicode. Methods that accept
+ input characters, when passed 'bytes' (which in Python 2 is equivalent to
+ 'str'), convert them from the encoding specified in the 'encoding'
+ parameter to the constructor. Methods that return screen contents return
+ unicode strings, with the exception of __str__() under Python 2. Passing
+ ``encoding=None`` limits the API to only accept unicode input, so passing
+ bytes in will raise :exc:`TypeError`.
+ '''
+ def __init__(self, r=24, c=80, encoding='latin-1', encoding_errors='replace'):
+ '''This initializes a blank screen of the given dimensions.'''
+
+ self.rows = r
+ self.cols = c
+ self.encoding = encoding
+ self.encoding_errors = encoding_errors
+ if encoding is not None:
+ self.decoder = codecs.getincrementaldecoder(encoding)(encoding_errors)
+ else:
+ self.decoder = None
+ self.cur_r = 1
+ self.cur_c = 1
+ self.cur_saved_r = 1
+ self.cur_saved_c = 1
+ self.scroll_row_start = 1
+ self.scroll_row_end = self.rows
+ self.w = [ [SPACE] * self.cols for _ in range(self.rows)]
+
+ def _decode(self, s):
+ '''This converts from the external coding system (as passed to
+ the constructor) to the internal one (unicode). '''
+ if self.decoder is not None:
+ return self.decoder.decode(s)
+ else:
+ raise TypeError("This screen was constructed with encoding=None, "
+ "so it does not handle bytes.")
+
+ def _unicode(self):
+ '''This returns a printable representation of the screen as a unicode
+ string (which, under Python 3.x, is the same as 'str'). The end of each
+ screen line is terminated by a newline.'''
+
+ return u'\n'.join ([ u''.join(c) for c in self.w ])
+
+ if PY3:
+ __str__ = _unicode
+ else:
+ __unicode__ = _unicode
+
+ def __str__(self):
+ '''This returns a printable representation of the screen. The end of
+ each screen line is terminated by a newline. '''
+ encoding = self.encoding or 'ascii'
+ return self._unicode().encode(encoding, 'replace')
+
+ def dump (self):
+ '''This returns a copy of the screen as a unicode string. This is similar to
+ __str__/__unicode__ except that lines are not terminated with line
+ feeds.'''
+
+ return u''.join ([ u''.join(c) for c in self.w ])
+
+ def pretty (self):
+ '''This returns a copy of the screen as a unicode string with an ASCII
+ text box around the screen border. This is similar to
+ __str__/__unicode__ except that it adds a box.'''
+
+ top_bot = u'+' + u'-'*self.cols + u'+\n'
+ return top_bot + u'\n'.join([u'|'+line+u'|' for line in unicode(self).split(u'\n')]) + u'\n' + top_bot
+
+ def fill (self, ch=SPACE):
+
+ if isinstance(ch, bytes):
+ ch = self._decode(ch)
+
+ self.fill_region (1,1,self.rows,self.cols, ch)
+
+ def fill_region (self, rs,cs, re,ce, ch=SPACE):
+
+ if isinstance(ch, bytes):
+ ch = self._decode(ch)
+
+ rs = constrain (rs, 1, self.rows)
+ re = constrain (re, 1, self.rows)
+ cs = constrain (cs, 1, self.cols)
+ ce = constrain (ce, 1, self.cols)
+ if rs > re:
+ rs, re = re, rs
+ if cs > ce:
+ cs, ce = ce, cs
+ for r in range (rs, re+1):
+ for c in range (cs, ce + 1):
+ self.put_abs (r,c,ch)
+
+ def cr (self):
+ '''This moves the cursor to the beginning (col 1) of the current row.
+ '''
+
+ self.cursor_home (self.cur_r, 1)
+
+ def lf (self):
+ '''This moves the cursor down with scrolling.
+ '''
+
+ old_r = self.cur_r
+ self.cursor_down()
+ if old_r == self.cur_r:
+ self.scroll_up ()
+ self.erase_line()
+
+ def crlf (self):
+ '''This advances the cursor with CRLF properties.
+ The cursor will line wrap and the screen may scroll.
+ '''
+
+ self.cr ()
+ self.lf ()
+
+ def newline (self):
+ '''This is an alias for crlf().
+ '''
+
+ self.crlf()
+
+ def put_abs (self, r, c, ch):
+ '''Screen array starts at 1 index.'''
+
+ r = constrain (r, 1, self.rows)
+ c = constrain (c, 1, self.cols)
+ if isinstance(ch, bytes):
+ ch = self._decode(ch)[0]
+ else:
+ ch = ch[0]
+ self.w[r-1][c-1] = ch
+
+ def put (self, ch):
+ '''This puts a characters at the current cursor position.
+ '''
+
+ if isinstance(ch, bytes):
+ ch = self._decode(ch)
+
+ self.put_abs (self.cur_r, self.cur_c, ch)
+
+ def insert_abs (self, r, c, ch):
+ '''This inserts a character at (r,c). Everything under
+ and to the right is shifted right one character.
+ The last character of the line is lost.
+ '''
+
+ if isinstance(ch, bytes):
+ ch = self._decode(ch)
+
+ r = constrain (r, 1, self.rows)
+ c = constrain (c, 1, self.cols)
+ for ci in range (self.cols, c, -1):
+ self.put_abs (r,ci, self.get_abs(r,ci-1))
+ self.put_abs (r,c,ch)
+
+ def insert (self, ch):
+
+ if isinstance(ch, bytes):
+ ch = self._decode(ch)
+
+ self.insert_abs (self.cur_r, self.cur_c, ch)
+
+ def get_abs (self, r, c):
+
+ r = constrain (r, 1, self.rows)
+ c = constrain (c, 1, self.cols)
+ return self.w[r-1][c-1]
+
+ def get (self):
+
+ self.get_abs (self.cur_r, self.cur_c)
+
+ def get_region (self, rs,cs, re,ce):
+ '''This returns a list of lines representing the region.
+ '''
+
+ rs = constrain (rs, 1, self.rows)
+ re = constrain (re, 1, self.rows)
+ cs = constrain (cs, 1, self.cols)
+ ce = constrain (ce, 1, self.cols)
+ if rs > re:
+ rs, re = re, rs
+ if cs > ce:
+ cs, ce = ce, cs
+ sc = []
+ for r in range (rs, re+1):
+ line = u''
+ for c in range (cs, ce + 1):
+ ch = self.get_abs (r,c)
+ line = line + ch
+ sc.append (line)
+ return sc
+
+ def cursor_constrain (self):
+ '''This keeps the cursor within the screen area.
+ '''
+
+ self.cur_r = constrain (self.cur_r, 1, self.rows)
+ self.cur_c = constrain (self.cur_c, 1, self.cols)
+
+ def cursor_home (self, r=1, c=1): # [{ROW};{COLUMN}H
+
+ self.cur_r = r
+ self.cur_c = c
+ self.cursor_constrain ()
+
+ def cursor_back (self,count=1): # [{COUNT}D (not confused with down)
+
+ self.cur_c = self.cur_c - count
+ self.cursor_constrain ()
+
+ def cursor_down (self,count=1): # [{COUNT}B (not confused with back)
+
+ self.cur_r = self.cur_r + count
+ self.cursor_constrain ()
+
+ def cursor_forward (self,count=1): # [{COUNT}C
+
+ self.cur_c = self.cur_c + count
+ self.cursor_constrain ()
+
+ def cursor_up (self,count=1): # [{COUNT}A
+
+ self.cur_r = self.cur_r - count
+ self.cursor_constrain ()
+
+ def cursor_up_reverse (self): # M (called RI -- Reverse Index)
+
+ old_r = self.cur_r
+ self.cursor_up()
+ if old_r == self.cur_r:
+ self.scroll_up()
+
+ def cursor_force_position (self, r, c): # [{ROW};{COLUMN}f
+ '''Identical to Cursor Home.'''
+
+ self.cursor_home (r, c)
+
+ def cursor_save (self): # [s
+ '''Save current cursor position.'''
+
+ self.cursor_save_attrs()
+
+ def cursor_unsave (self): # [u
+ '''Restores cursor position after a Save Cursor.'''
+
+ self.cursor_restore_attrs()
+
+ def cursor_save_attrs (self): # 7
+ '''Save current cursor position.'''
+
+ self.cur_saved_r = self.cur_r
+ self.cur_saved_c = self.cur_c
+
+ def cursor_restore_attrs (self): # 8
+ '''Restores cursor position after a Save Cursor.'''
+
+ self.cursor_home (self.cur_saved_r, self.cur_saved_c)
+
+ def scroll_constrain (self):
+ '''This keeps the scroll region within the screen region.'''
+
+ if self.scroll_row_start <= 0:
+ self.scroll_row_start = 1
+ if self.scroll_row_end > self.rows:
+ self.scroll_row_end = self.rows
+
+ def scroll_screen (self): # [r
+ '''Enable scrolling for entire display.'''
+
+ self.scroll_row_start = 1
+ self.scroll_row_end = self.rows
+
+ def scroll_screen_rows (self, rs, re): # [{start};{end}r
+ '''Enable scrolling from row {start} to row {end}.'''
+
+ self.scroll_row_start = rs
+ self.scroll_row_end = re
+ self.scroll_constrain()
+
+ def scroll_down (self): # D
+ '''Scroll display down one line.'''
+
+ # Screen is indexed from 1, but arrays are indexed from 0.
+ s = self.scroll_row_start - 1
+ e = self.scroll_row_end - 1
+ self.w[s+1:e+1] = copy.deepcopy(self.w[s:e])
+
+ def scroll_up (self): # M
+ '''Scroll display up one line.'''
+
+ # Screen is indexed from 1, but arrays are indexed from 0.
+ s = self.scroll_row_start - 1
+ e = self.scroll_row_end - 1
+ self.w[s:e] = copy.deepcopy(self.w[s+1:e+1])
+
+ def erase_end_of_line (self): # [0K -or- [K
+ '''Erases from the current cursor position to the end of the current
+ line.'''
+
+ self.fill_region (self.cur_r, self.cur_c, self.cur_r, self.cols)
+
+ def erase_start_of_line (self): # [1K
+ '''Erases from the current cursor position to the start of the current
+ line.'''
+
+ self.fill_region (self.cur_r, 1, self.cur_r, self.cur_c)
+
+ def erase_line (self): # [2K
+ '''Erases the entire current line.'''
+
+ self.fill_region (self.cur_r, 1, self.cur_r, self.cols)
+
+ def erase_down (self): # [0J -or- [J
+ '''Erases the screen from the current line down to the bottom of the
+ screen.'''
+
+ self.erase_end_of_line ()
+ self.fill_region (self.cur_r + 1, 1, self.rows, self.cols)
+
+ def erase_up (self): # [1J
+ '''Erases the screen from the current line up to the top of the
+ screen.'''
+
+ self.erase_start_of_line ()
+ self.fill_region (self.cur_r-1, 1, 1, self.cols)
+
+ def erase_screen (self): # [2J
+ '''Erases the screen with the background color.'''
+
+ self.fill ()
+
+ def set_tab (self): # H
+ '''Sets a tab at the current position.'''
+
+ pass
+
+ def clear_tab (self): # [g
+ '''Clears tab at the current position.'''
+
+ pass
+
+ def clear_all_tabs (self): # [3g
+ '''Clears all tabs.'''
+
+ pass
+
+# Insert line Esc [ Pn L
+# Delete line Esc [ Pn M
+# Delete character Esc [ Pn P
+# Scrolling region Esc [ Pn(top);Pn(bot) r
+
Index: third_party/Python/module/pexpect-4.6/pexpect/spawnbase.py
===================================================================
--- third_party/Python/module/pexpect-4.6/pexpect/spawnbase.py
+++ third_party/Python/module/pexpect-4.6/pexpect/spawnbase.py
@@ -0,0 +1,522 @@
+from io import StringIO, BytesIO
+import codecs
+import os
+import sys
+import re
+import errno
+from .exceptions import ExceptionPexpect, EOF, TIMEOUT
+from .expect import Expecter, searcher_string, searcher_re
+
+PY3 = (sys.version_info[0] >= 3)
+text_type = str if PY3 else unicode
+
+class _NullCoder(object):
+ """Pass bytes through unchanged."""
+ @staticmethod
+ def encode(b, final=False):
+ return b
+
+ @staticmethod
+ def decode(b, final=False):
+ return b
+
+class SpawnBase(object):
+ """A base class providing the backwards-compatible spawn API for Pexpect.
+
+ This should not be instantiated directly: use :class:`pexpect.spawn` or
+ :class:`pexpect.fdpexpect.fdspawn`.
+ """
+ encoding = None
+ pid = None
+ flag_eof = False
+
+ def __init__(self, timeout=30, maxread=2000, searchwindowsize=None,
+ logfile=None, encoding=None, codec_errors='strict'):
+ self.stdin = sys.stdin
+ self.stdout = sys.stdout
+ self.stderr = sys.stderr
+
+ self.searcher = None
+ self.ignorecase = False
+ self.before = None
+ self.after = None
+ self.match = None
+ self.match_index = None
+ self.terminated = True
+ self.exitstatus = None
+ self.signalstatus = None
+ # status returned by os.waitpid
+ self.status = None
+ # the child file descriptor is initially closed
+ self.child_fd = -1
+ self.timeout = timeout
+ self.delimiter = EOF
+ self.logfile = logfile
+ # input from child (read_nonblocking)
+ self.logfile_read = None
+ # output to send (send, sendline)
+ self.logfile_send = None
+ # max bytes to read at one time into buffer
+ self.maxread = maxread
+ # Data before searchwindowsize point is preserved, but not searched.
+ self.searchwindowsize = searchwindowsize
+ # Delay used before sending data to child. Time in seconds.
+ # Set this to None to skip the time.sleep() call completely.
+ self.delaybeforesend = 0.05
+ # Used by close() to give kernel time to update process status.
+ # Time in seconds.
+ self.delayafterclose = 0.1
+ # Used by terminate() to give kernel time to update process status.
+ # Time in seconds.
+ self.delayafterterminate = 0.1
+ # Delay in seconds to sleep after each call to read_nonblocking().
+ # Set this to None to skip the time.sleep() call completely: that
+ # would restore the behavior from pexpect-2.0 (for performance
+ # reasons or because you don't want to release Python's global
+ # interpreter lock).
+ self.delayafterread = 0.0001
+ self.softspace = False
+ self.name = '<' + repr(self) + '>'
+ self.closed = True
+
+ # Unicode interface
+ self.encoding = encoding
+ self.codec_errors = codec_errors
+ if encoding is None:
+ # bytes mode (accepts some unicode for backwards compatibility)
+ self._encoder = self._decoder = _NullCoder()
+ self.string_type = bytes
+ self.buffer_type = BytesIO
+ self.crlf = b'\r\n'
+ if PY3:
+ self.allowed_string_types = (bytes, str)
+ self.linesep = os.linesep.encode('ascii')
+ def write_to_stdout(b):
+ try:
+ return sys.stdout.buffer.write(b)
+ except AttributeError:
+ # If stdout has been replaced, it may not have .buffer
+ return sys.stdout.write(b.decode('ascii', 'replace'))
+ self.write_to_stdout = write_to_stdout
+ else:
+ self.allowed_string_types = (basestring,) # analysis:ignore
+ self.linesep = os.linesep
+ self.write_to_stdout = sys.stdout.write
+ else:
+ # unicode mode
+ self._encoder = codecs.getincrementalencoder(encoding)(codec_errors)
+ self._decoder = codecs.getincrementaldecoder(encoding)(codec_errors)
+ self.string_type = text_type
+ self.buffer_type = StringIO
+ self.crlf = u'\r\n'
+ self.allowed_string_types = (text_type, )
+ if PY3:
+ self.linesep = os.linesep
+ else:
+ self.linesep = os.linesep.decode('ascii')
+ # This can handle unicode in both Python 2 and 3
+ self.write_to_stdout = sys.stdout.write
+ # storage for async transport
+ self.async_pw_transport = None
+ # This is the read buffer. See maxread.
+ self._buffer = self.buffer_type()
+
+ def _log(self, s, direction):
+ if self.logfile is not None:
+ self.logfile.write(s)
+ self.logfile.flush()
+ second_log = self.logfile_send if (direction=='send') else self.logfile_read
+ if second_log is not None:
+ second_log.write(s)
+ second_log.flush()
+
+ # For backwards compatibility, in bytes mode (when encoding is None)
+ # unicode is accepted for send and expect. Unicode mode is strictly unicode
+ # only.
+ def _coerce_expect_string(self, s):
+ if self.encoding is None and not isinstance(s, bytes):
+ return s.encode('ascii')
+ return s
+
+ def _coerce_send_string(self, s):
+ if self.encoding is None and not isinstance(s, bytes):
+ return s.encode('utf-8')
+ return s
+
+ def _get_buffer(self):
+ return self._buffer.getvalue()
+
+ def _set_buffer(self, value):
+ self._buffer = self.buffer_type()
+ self._buffer.write(value)
+
+ # This property is provided for backwards compatability (self.buffer used
+ # to be a string/bytes object)
+ buffer = property(_get_buffer, _set_buffer)
+
+ def read_nonblocking(self, size=1, timeout=None):
+ """This reads data from the file descriptor.
+
+ This is a simple implementation suitable for a regular file. Subclasses using ptys or pipes should override it.
+
+ The timeout parameter is ignored.
+ """
+
+ try:
+ s = os.read(self.child_fd, size)
+ except OSError as err:
+ if err.args[0] == errno.EIO:
+ # Linux-style EOF
+ self.flag_eof = True
+ raise EOF('End Of File (EOF). Exception style platform.')
+ raise
+ if s == b'':
+ # BSD-style EOF
+ self.flag_eof = True
+ raise EOF('End Of File (EOF). Empty string style platform.')
+
+ s = self._decoder.decode(s, final=False)
+ self._log(s, 'read')
+ return s
+
+ def _pattern_type_err(self, pattern):
+ raise TypeError('got {badtype} ({badobj!r}) as pattern, must be one'
+ ' of: {goodtypes}, pexpect.EOF, pexpect.TIMEOUT'\
+ .format(badtype=type(pattern),
+ badobj=pattern,
+ goodtypes=', '.join([str(ast)\
+ for ast in self.allowed_string_types])
+ )
+ )
+
+ def compile_pattern_list(self, patterns):
+ '''This compiles a pattern-string or a list of pattern-strings.
+ Patterns must be a StringType, EOF, TIMEOUT, SRE_Pattern, or a list of
+ those. Patterns may also be None which results in an empty list (you
+ might do this if waiting for an EOF or TIMEOUT condition without
+ expecting any pattern).
+
+ This is used by expect() when calling expect_list(). Thus expect() is
+ nothing more than::
+
+ cpl = self.compile_pattern_list(pl)
+ return self.expect_list(cpl, timeout)
+
+ If you are using expect() within a loop it may be more
+ efficient to compile the patterns first and then call expect_list().
+ This avoid calls in a loop to compile_pattern_list()::
+
+ cpl = self.compile_pattern_list(my_pattern)
+ while some_condition:
+ ...
+ i = self.expect_list(cpl, timeout)
+ ...
+ '''
+
+ if patterns is None:
+ return []
+ if not isinstance(patterns, list):
+ patterns = [patterns]
+
+ # Allow dot to match \n
+ compile_flags = re.DOTALL
+ if self.ignorecase:
+ compile_flags = compile_flags | re.IGNORECASE
+ compiled_pattern_list = []
+ for idx, p in enumerate(patterns):
+ if isinstance(p, self.allowed_string_types):
+ p = self._coerce_expect_string(p)
+ compiled_pattern_list.append(re.compile(p, compile_flags))
+ elif p is EOF:
+ compiled_pattern_list.append(EOF)
+ elif p is TIMEOUT:
+ compiled_pattern_list.append(TIMEOUT)
+ elif isinstance(p, type(re.compile(''))):
+ compiled_pattern_list.append(p)
+ else:
+ self._pattern_type_err(p)
+ return compiled_pattern_list
+
+ def expect(self, pattern, timeout=-1, searchwindowsize=-1, async_=False, **kw):
+ '''This seeks through the stream until a pattern is matched. The
+ pattern is overloaded and may take several types. The pattern can be a
+ StringType, EOF, a compiled re, or a list of any of those types.
+ Strings will be compiled to re types. This returns the index into the
+ pattern list. If the pattern was not a list this returns index 0 on a
+ successful match. This may raise exceptions for EOF or TIMEOUT. To
+ avoid the EOF or TIMEOUT exceptions add EOF or TIMEOUT to the pattern
+ list. That will cause expect to match an EOF or TIMEOUT condition
+ instead of raising an exception.
+
+ If you pass a list of patterns and more than one matches, the first
+ match in the stream is chosen. If more than one pattern matches at that
+ point, the leftmost in the pattern list is chosen. For example::
+
+ # the input is 'foobar'
+ index = p.expect(['bar', 'foo', 'foobar'])
+ # returns 1('foo') even though 'foobar' is a "better" match
+
+ Please note, however, that buffering can affect this behavior, since
+ input arrives in unpredictable chunks. For example::
+
+ # the input is 'foobar'
+ index = p.expect(['foobar', 'foo'])
+ # returns 0('foobar') if all input is available at once,
+ # but returns 1('foo') if parts of the final 'bar' arrive late
+
+ When a match is found for the given pattern, the class instance
+ attribute *match* becomes an re.MatchObject result. Should an EOF
+ or TIMEOUT pattern match, then the match attribute will be an instance
+ of that exception class. The pairing before and after class
+ instance attributes are views of the data preceding and following
+ the matching pattern. On general exception, class attribute
+ *before* is all data received up to the exception, while *match* and
+ *after* attributes are value None.
+
+ When the keyword argument timeout is -1 (default), then TIMEOUT will
+ raise after the default value specified by the class timeout
+ attribute. When None, TIMEOUT will not be raised and may block
+ indefinitely until match.
+
+ When the keyword argument searchwindowsize is -1 (default), then the
+ value specified by the class maxread attribute is used.
+
+ A list entry may be EOF or TIMEOUT instead of a string. This will
+ catch these exceptions and return the index of the list entry instead
+ of raising the exception. The attribute 'after' will be set to the
+ exception type. The attribute 'match' will be None. This allows you to
+ write code like this::
+
+ index = p.expect(['good', 'bad', pexpect.EOF, pexpect.TIMEOUT])
+ if index == 0:
+ do_something()
+ elif index == 1:
+ do_something_else()
+ elif index == 2:
+ do_some_other_thing()
+ elif index == 3:
+ do_something_completely_different()
+
+ instead of code like this::
+
+ try:
+ index = p.expect(['good', 'bad'])
+ if index == 0:
+ do_something()
+ elif index == 1:
+ do_something_else()
+ except EOF:
+ do_some_other_thing()
+ except TIMEOUT:
+ do_something_completely_different()
+
+ These two forms are equivalent. It all depends on what you want. You
+ can also just expect the EOF if you are waiting for all output of a
+ child to finish. For example::
+
+ p = pexpect.spawn('/bin/ls')
+ p.expect(pexpect.EOF)
+ print p.before
+
+ If you are trying to optimize for speed then see expect_list().
+
+ On Python 3.4, or Python 3.3 with asyncio installed, passing
+ ``async_=True`` will make this return an :mod:`asyncio` coroutine,
+ which you can yield from to get the same result that this method would
+ normally give directly. So, inside a coroutine, you can replace this code::
+
+ index = p.expect(patterns)
+
+ With this non-blocking form::
+
+ index = yield from p.expect(patterns, async_=True)
+ '''
+ if 'async' in kw:
+ async_ = kw.pop('async')
+ if kw:
+ raise TypeError("Unknown keyword arguments: {}".format(kw))
+
+ compiled_pattern_list = self.compile_pattern_list(pattern)
+ return self.expect_list(compiled_pattern_list,
+ timeout, searchwindowsize, async_)
+
+ def expect_list(self, pattern_list, timeout=-1, searchwindowsize=-1,
+ async_=False, **kw):
+ '''This takes a list of compiled regular expressions and returns the
+ index into the pattern_list that matched the child output. The list may
+ also contain EOF or TIMEOUT(which are not compiled regular
+ expressions). This method is similar to the expect() method except that
+ expect_list() does not recompile the pattern list on every call. This
+ may help if you are trying to optimize for speed, otherwise just use
+ the expect() method. This is called by expect().
+
+
+ Like :meth:`expect`, passing ``async_=True`` will make this return an
+ asyncio coroutine.
+ '''
+ if timeout == -1:
+ timeout = self.timeout
+ if 'async' in kw:
+ async_ = kw.pop('async')
+ if kw:
+ raise TypeError("Unknown keyword arguments: {}".format(kw))
+
+ exp = Expecter(self, searcher_re(pattern_list), searchwindowsize)
+ if async_:
+ from ._async import expect_async
+ return expect_async(exp, timeout)
+ else:
+ return exp.expect_loop(timeout)
+
+ def expect_exact(self, pattern_list, timeout=-1, searchwindowsize=-1,
+ async_=False, **kw):
+
+ '''This is similar to expect(), but uses plain string matching instead
+ of compiled regular expressions in 'pattern_list'. The 'pattern_list'
+ may be a string; a list or other sequence of strings; or TIMEOUT and
+ EOF.
+
+ This call might be faster than expect() for two reasons: string
+ searching is faster than RE matching and it is possible to limit the
+ search to just the end of the input buffer.
+
+ This method is also useful when you don't want to have to worry about
+ escaping regular expression characters that you want to match.
+
+ Like :meth:`expect`, passing ``async_=True`` will make this return an
+ asyncio coroutine.
+ '''
+ if timeout == -1:
+ timeout = self.timeout
+ if 'async' in kw:
+ async_ = kw.pop('async')
+ if kw:
+ raise TypeError("Unknown keyword arguments: {}".format(kw))
+
+ if (isinstance(pattern_list, self.allowed_string_types) or
+ pattern_list in (TIMEOUT, EOF)):
+ pattern_list = [pattern_list]
+
+ def prepare_pattern(pattern):
+ if pattern in (TIMEOUT, EOF):
+ return pattern
+ if isinstance(pattern, self.allowed_string_types):
+ return self._coerce_expect_string(pattern)
+ self._pattern_type_err(pattern)
+
+ try:
+ pattern_list = iter(pattern_list)
+ except TypeError:
+ self._pattern_type_err(pattern_list)
+ pattern_list = [prepare_pattern(p) for p in pattern_list]
+
+ exp = Expecter(self, searcher_string(pattern_list), searchwindowsize)
+ if async_:
+ from ._async import expect_async
+ return expect_async(exp, timeout)
+ else:
+ return exp.expect_loop(timeout)
+
+ def expect_loop(self, searcher, timeout=-1, searchwindowsize=-1):
+ '''This is the common loop used inside expect. The 'searcher' should be
+ an instance of searcher_re or searcher_string, which describes how and
+ what to search for in the input.
+
+ See expect() for other arguments, return value and exceptions. '''
+
+ exp = Expecter(self, searcher, searchwindowsize)
+ return exp.expect_loop(timeout)
+
+ def read(self, size=-1):
+ '''This reads at most "size" bytes from the file (less if the read hits
+ EOF before obtaining size bytes). If the size argument is negative or
+ omitted, read all data until EOF is reached. The bytes are returned as
+ a string object. An empty string is returned when EOF is encountered
+ immediately. '''
+
+ if size == 0:
+ return self.string_type()
+ if size < 0:
+ # delimiter default is EOF
+ self.expect(self.delimiter)
+ return self.before
+
+ # I could have done this more directly by not using expect(), but
+ # I deliberately decided to couple read() to expect() so that
+ # I would catch any bugs early and ensure consistent behavior.
+ # It's a little less efficient, but there is less for me to
+ # worry about if I have to later modify read() or expect().
+ # Note, it's OK if size==-1 in the regex. That just means it
+ # will never match anything in which case we stop only on EOF.
+ cre = re.compile(self._coerce_expect_string('.{%d}' % size), re.DOTALL)
+ # delimiter default is EOF
+ index = self.expect([cre, self.delimiter])
+ if index == 0:
+ ### FIXME self.before should be ''. Should I assert this?
+ return self.after
+ return self.before
+
+ def readline(self, size=-1):
+ '''This reads and returns one entire line. The newline at the end of
+ line is returned as part of the string, unless the file ends without a
+ newline. An empty string is returned if EOF is encountered immediately.
+ This looks for a newline as a CR/LF pair (\\r\\n) even on UNIX because
+ this is what the pseudotty device returns. So contrary to what you may
+ expect you will receive newlines as \\r\\n.
+
+ If the size argument is 0 then an empty string is returned. In all
+ other cases the size argument is ignored, which is not standard
+ behavior for a file-like object. '''
+
+ if size == 0:
+ return self.string_type()
+ # delimiter default is EOF
+ index = self.expect([self.crlf, self.delimiter])
+ if index == 0:
+ return self.before + self.crlf
+ else:
+ return self.before
+
+ def __iter__(self):
+ '''This is to support iterators over a file-like object.
+ '''
+ return iter(self.readline, self.string_type())
+
+ def readlines(self, sizehint=-1):
+ '''This reads until EOF using readline() and returns a list containing
+ the lines thus read. The optional 'sizehint' argument is ignored.
+ Remember, because this reads until EOF that means the child
+ process should have closed its stdout. If you run this method on
+ a child that is still running with its stdout open then this
+ method will block until it timesout.'''
+
+ lines = []
+ while True:
+ line = self.readline()
+ if not line:
+ break
+ lines.append(line)
+ return lines
+
+ def fileno(self):
+ '''Expose file descriptor for a file-like interface
+ '''
+ return self.child_fd
+
+ def flush(self):
+ '''This does nothing. It is here to support the interface for a
+ File-like object. '''
+ pass
+
+ def isatty(self):
+ """Overridden in subclass using tty"""
+ return False
+
+ # For 'with spawn(...) as child:'
+ def __enter__(self):
+ return self
+
+ def __exit__(self, etype, evalue, tb):
+ # We rely on subclasses to implement close(). If they don't, it's not
+ # clear what a context manager should do.
+ self.close()
Index: third_party/Python/module/pexpect-4.6/pexpect/utils.py
===================================================================
--- third_party/Python/module/pexpect-4.6/pexpect/utils.py
+++ third_party/Python/module/pexpect-4.6/pexpect/utils.py
@@ -0,0 +1,187 @@
+import os
+import sys
+import stat
+import select
+import time
+import errno
+
+try:
+ InterruptedError
+except NameError:
+ # Alias Python2 exception to Python3
+ InterruptedError = select.error
+
+if sys.version_info[0] >= 3:
+ string_types = (str,)
+else:
+ string_types = (unicode, str)
+
+
+def is_executable_file(path):
+ """Checks that path is an executable regular file, or a symlink towards one.
+
+ This is roughly ``os.path isfile(path) and os.access(path, os.X_OK)``.
+ """
+ # follow symlinks,
+ fpath = os.path.realpath(path)
+
+ if not os.path.isfile(fpath):
+ # non-files (directories, fifo, etc.)
+ return False
+
+ mode = os.stat(fpath).st_mode
+
+ if (sys.platform.startswith('sunos')
+ and os.getuid() == 0):
+ # When root on Solaris, os.X_OK is True for *all* files, irregardless
+ # of their executability -- instead, any permission bit of any user,
+ # group, or other is fine enough.
+ #
+ # (This may be true for other "Unix98" OS's such as HP-UX and AIX)
+ return bool(mode & (stat.S_IXUSR |
+ stat.S_IXGRP |
+ stat.S_IXOTH))
+
+ return os.access(fpath, os.X_OK)
+
+
+def which(filename, env=None):
+ '''This takes a given filename; tries to find it in the environment path;
+ then checks if it is executable. This returns the full path to the filename
+ if found and executable. Otherwise this returns None.'''
+
+ # Special case where filename contains an explicit path.
+ if os.path.dirname(filename) != '' and is_executable_file(filename):
+ return filename
+ if env is None:
+ env = os.environ
+ p = env.get('PATH')
+ if not p:
+ p = os.defpath
+ pathlist = p.split(os.pathsep)
+ for path in pathlist:
+ ff = os.path.join(path, filename)
+ if is_executable_file(ff):
+ return ff
+ return None
+
+
+def split_command_line(command_line):
+
+ '''This splits a command line into a list of arguments. It splits arguments
+ on spaces, but handles embedded quotes, doublequotes, and escaped
+ characters. It's impossible to do this with a regular expression, so I
+ wrote a little state machine to parse the command line. '''
+
+ arg_list = []
+ arg = ''
+
+ # Constants to name the states we can be in.
+ state_basic = 0
+ state_esc = 1
+ state_singlequote = 2
+ state_doublequote = 3
+ # The state when consuming whitespace between commands.
+ state_whitespace = 4
+ state = state_basic
+
+ for c in command_line:
+ if state == state_basic or state == state_whitespace:
+ if c == '\\':
+ # Escape the next character
+ state = state_esc
+ elif c == r"'":
+ # Handle single quote
+ state = state_singlequote
+ elif c == r'"':
+ # Handle double quote
+ state = state_doublequote
+ elif c.isspace():
+ # Add arg to arg_list if we aren't in the middle of whitespace.
+ if state == state_whitespace:
+ # Do nothing.
+ None
+ else:
+ arg_list.append(arg)
+ arg = ''
+ state = state_whitespace
+ else:
+ arg = arg + c
+ state = state_basic
+ elif state == state_esc:
+ arg = arg + c
+ state = state_basic
+ elif state == state_singlequote:
+ if c == r"'":
+ state = state_basic
+ else:
+ arg = arg + c
+ elif state == state_doublequote:
+ if c == r'"':
+ state = state_basic
+ else:
+ arg = arg + c
+
+ if arg != '':
+ arg_list.append(arg)
+ return arg_list
+
+
+def select_ignore_interrupts(iwtd, owtd, ewtd, timeout=None):
+
+ '''This is a wrapper around select.select() that ignores signals. If
+ select.select raises a select.error exception and errno is an EINTR
+ error then it is ignored. Mainly this is used to ignore sigwinch
+ (terminal resize). '''
+
+ # if select() is interrupted by a signal (errno==EINTR) then
+ # we loop back and enter the select() again.
+ if timeout is not None:
+ end_time = time.time() + timeout
+ while True:
+ try:
+ return select.select(iwtd, owtd, ewtd, timeout)
+ except InterruptedError:
+ err = sys.exc_info()[1]
+ if err.args[0] == errno.EINTR:
+ # if we loop back we have to subtract the
+ # amount of time we already waited.
+ if timeout is not None:
+ timeout = end_time - time.time()
+ if timeout < 0:
+ return([], [], [])
+ else:
+ # something else caused the select.error, so
+ # this actually is an exception.
+ raise
+
+
+def poll_ignore_interrupts(fds, timeout=None):
+ '''Simple wrapper around poll to register file descriptors and
+ ignore signals.'''
+
+ if timeout is not None:
+ end_time = time.time() + timeout
+
+ poller = select.poll()
+ for fd in fds:
+ poller.register(fd, select.POLLIN | select.POLLPRI | select.POLLHUP | select.POLLERR)
+
+ while True:
+ try:
+ timeout_ms = None if timeout is None else timeout * 1000
+ results = poller.poll(timeout_ms)
+ return [afd for afd, _ in results]
+ except InterruptedError:
+ err = sys.exc_info()[1]
+ if err.args[0] == errno.EINTR:
+ # if we loop back we have to subtract the
+ # amount of time we already waited.
+ if timeout is not None:
+ timeout = end_time - time.time()
+ if timeout < 0:
+ return []
+ else:
+ # something else caused the select.error, so
+ # this actually is an exception.
+ raise
Index: third_party/Python/module/pexpect-4.6/requirements-testing.txt
===================================================================
--- third_party/Python/module/pexpect-4.6/requirements-testing.txt
+++ third_party/Python/module/pexpect-4.6/requirements-testing.txt
@@ -0,0 +1,5 @@
+pytest
+pytest-cov
+coverage
+coveralls
+pytest-capturelog
Index: third_party/Python/module/pexpect-4.6/setup.cfg
===================================================================
--- third_party/Python/module/pexpect-4.6/setup.cfg
+++ third_party/Python/module/pexpect-4.6/setup.cfg
@@ -0,0 +1,5 @@
+[tool:pytest]
+norecursedirs = .git
+
+[bdist_wheel]
+universal=1
Index: third_party/Python/module/pexpect-4.6/setup.py
===================================================================
--- third_party/Python/module/pexpect-4.6/setup.py
+++ third_party/Python/module/pexpect-4.6/setup.py
@@ -0,0 +1,71 @@
+# encoding: utf-8
+from distutils.core import setup
+import os
+import re
+import sys
+
+if any(a == 'bdist_wheel' for a in sys.argv):
+ from setuptools import setup
+
+with open(os.path.join(os.path.dirname(__file__), 'pexpect', '__init__.py'), 'r') as f:
+ for line in f:
+ version_match = re.search(r"__version__ = ['\"]([^'\"]*)['\"]", line)
+ if version_match:
+ version = version_match.group(1)
+ break
+ else:
+ raise Exception("couldn't find version number")
+
+long_description = """
+Pexpect is a pure Python module for spawning child applications; controlling
+them; and responding to expected patterns in their output. Pexpect works like
+Don Libes' Expect. Pexpect allows your script to spawn a child application and
+control it as if a human were typing commands.
+
+Pexpect can be used for automating interactive applications such as ssh, ftp,
+passwd, telnet, etc. It can be used to a automate setup scripts for duplicating
+software package installations on different servers. It can be used for
+automated software testing. Pexpect is in the spirit of Don Libes' Expect, but
+Pexpect is pure Python.
+
+The main features of Pexpect require the pty module in the Python standard
+library, which is only available on Unix-like systems. Some features—waiting
+for patterns from file descriptors or subprocesses—are also available on
+Windows.
+"""
+
+setup(name='pexpect',
+ version=version,
+ packages=['pexpect'],
+ package_data={'pexpect': ['bashrc.sh']},
+ description='Pexpect allows easy control of interactive console applications.',
+ long_description=long_description,
+ author='Noah Spurrier; Thomas Kluyver; Jeff Quast',
+ author_email='noah@noah.org, thomas@kluyver.me.uk, contact@jeffquast.com',
+ url='https://pexpect.readthedocs.io/',
+ license='ISC license',
+ platforms='UNIX',
+ classifiers = [
+ 'Development Status :: 5 - Production/Stable',
+ 'Environment :: Console',
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: System Administrators',
+ 'License :: OSI Approved :: ISC License (ISCL)',
+ 'Operating System :: POSIX',
+ 'Operating System :: MacOS :: MacOS X',
+ 'Programming Language :: Python',
+ 'Programming Language :: Python :: 2.7',
+ 'Programming Language :: Python :: 3',
+ 'Topic :: Software Development',
+ 'Topic :: Software Development :: Libraries :: Python Modules',
+ 'Topic :: Software Development :: Quality Assurance',
+ 'Topic :: Software Development :: Testing',
+ 'Topic :: System',
+ 'Topic :: System :: Archiving :: Packaging',
+ 'Topic :: System :: Installation/Setup',
+ 'Topic :: System :: Shells',
+ 'Topic :: System :: Software Distribution',
+ 'Topic :: Terminals',
+ ],
+ install_requires=['ptyprocess>=0.5'],
+)
Index: third_party/Python/module/pexpect-4.6/tests/PexpectTestCase.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/PexpectTestCase.py
+++ third_party/Python/module/pexpect-4.6/tests/PexpectTestCase.py
@@ -0,0 +1,108 @@
+
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+from __future__ import print_function
+
+import contextlib
+import unittest
+import signal
+import sys
+import os
+
+
+class PexpectTestCase(unittest.TestCase):
+ def setUp(self):
+ self.PYTHONBIN = sys.executable
+ self.original_path = os.getcwd()
+ tests_dir = os.path.dirname(__file__)
+ self.project_dir = project_dir = os.path.dirname(tests_dir)
+
+ # all tests are executed in this folder; there are many auxiliary
+ # programs in this folder executed by spawn().
+ os.chdir(tests_dir)
+
+ # If the pexpect raises an exception after fork(), but before
+ # exec(), our test runner *also* forks. We prevent this by
+ # storing our pid and asserting equality on tearDown.
+ self.pid = os.getpid()
+
+ coverage_rc = os.path.join(project_dir, '.coveragerc')
+ os.environ['COVERAGE_PROCESS_START'] = coverage_rc
+ os.environ['COVERAGE_FILE'] = os.path.join(project_dir, '.coverage')
+ print('\n', self.id(), end=' ')
+ sys.stdout.flush()
+
+ # some build agents will ignore SIGHUP and SIGINT, which python
+ # inherits. This causes some of the tests related to terminate()
+ # to fail. We set them to the default handlers that they should
+ # be, and restore them back to their SIG_IGN value on tearDown.
+ #
+ # I'm not entirely convinced they need to be restored, only our
+ # test runner is affected.
+ self.restore_ignored_signals = [
+ value for value in (signal.SIGHUP, signal.SIGINT,)
+ if signal.getsignal(value) == signal.SIG_IGN]
+ if signal.SIGHUP in self.restore_ignored_signals:
+ # sighup should be set to default handler
+ signal.signal(signal.SIGHUP, signal.SIG_DFL)
+ if signal.SIGINT in self.restore_ignored_signals:
+ # SIGINT should be set to signal.default_int_handler
+ signal.signal(signal.SIGINT, signal.default_int_handler)
+ unittest.TestCase.setUp(self)
+
+ def tearDown(self):
+ # restore original working folder
+ os.chdir(self.original_path)
+
+ if self.pid != os.getpid():
+ # The build server pattern-matches phrase 'Test runner has forked!'
+ print("Test runner has forked! This means a child process raised "
+ "an exception before exec() in a test case, the error is "
+ "more than likely found above this line in stderr.",
+ file=sys.stderr)
+ exit(1)
+
+ # restore signal handlers
+ for signal_value in self.restore_ignored_signals:
+ signal.signal(signal_value, signal.SIG_IGN)
+
+ if sys.version_info < (2, 7):
+ # We want to use these methods, which are new/improved in 2.7, but
+ # we are still supporting 2.6 for the moment. This section can be
+ # removed when we drop Python 2.6 support.
+ @contextlib.contextmanager
+ def assertRaises(self, excClass):
+ try:
+ yield
+ except Exception as e:
+ assert isinstance(e, excClass)
+ else:
+ raise AssertionError("%s was not raised" % excClass)
+
+ @contextlib.contextmanager
+ def assertRaisesRegexp(self, excClass, pattern):
+ import re
+ try:
+ yield
+ except Exception as e:
+ assert isinstance(e, excClass)
+ assert re.match(pattern, str(e))
+ else:
+ raise AssertionError("%s was not raised" % excClass)
Index: third_party/Python/module/pexpect-4.6/tests/README
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/README
+++ third_party/Python/module/pexpect-4.6/tests/README
@@ -0,0 +1,8 @@
+
+The best way to run these tests is from the directory above this one. Run:
+
+ py.test
+
+To run a specific test file:
+
+ py.test tests/test_constructor.py
Index: third_party/Python/module/pexpect-4.6/tests/TESTDATA.txt
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/TESTDATA.txt
+++ third_party/Python/module/pexpect-4.6/tests/TESTDATA.txt
@@ -0,0 +1,8 @@
+This is test data.
+ One
+ 2
+ THREE
+ IV
+ .....
+ 110
+This is the end of test data: END
Index: third_party/Python/module/pexpect-4.6/tests/__init__.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/__init__.py
+++ third_party/Python/module/pexpect-4.6/tests/__init__.py
@@ -0,0 +1,25 @@
+
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+# __init__.py
+# The mere presence of this file makes the dir a package.
+pass
+
Index: third_party/Python/module/pexpect-4.6/tests/adhoc.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/adhoc.py
+++ third_party/Python/module/pexpect-4.6/tests/adhoc.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+from __future__ import print_function
+
+import pexpect
+import time
+
+p = pexpect.spawn ('./a.out')
+print(p.exitstatus)
+p.expect (pexpect.EOF)
+print(p.before)
+time.sleep(1)
+print('exitstatus:', p.exitstatus)
+print('isalive',p.isalive())
+print('exitstatus',p.exitstatus)
+print('isalive',p.isalive())
+print('exitstatus',p.exitstatus)
+
Index: third_party/Python/module/pexpect-4.6/tests/alarm_die.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/alarm_die.py
+++ third_party/Python/module/pexpect-4.6/tests/alarm_die.py
@@ -0,0 +1,5 @@
+import signal, time
+
+signal.alarm(1) # Schedule SIGALRM in 1s
+
+time.sleep(6)
\ No newline at end of file
Index: third_party/Python/module/pexpect-4.6/tests/bambi.vt
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/bambi.vt
+++ third_party/Python/module/pexpect-4.6/tests/bambi.vt
@@ -0,0 +1,417 @@
+[?25l
+[1;24r
+[2J
+[10;1H The
+[10;1H The Adventures
+[10;1H The Adventures of
+[10;1H The Adventures of BAMBI
+[16;1H
+[15;1H Number
+[15;1H Number One :
+[15;1H Number One : BAMBI
+[15;1H Number One : BAMBI versus
+[15;1H Number One : BAMBI versus GODZILLA
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[16;1H
+[2J
+[23;5H ,| *./[24;5H\|(/|/[1;1H
+[22;38H /|[23;38H |/`|',[24;38H/| \|/[1;1H
+[23;65H \/_,| /| /,[24;65H /<|\\/\|/|\[1;1H
+[15;1H _^_
+[16;1H o / .\
+[17;1H \,--------; __o
+[18;1H / .:::. . /
+[19;1H \___________/
+[20;1H |\ |\
+[21;1H | > | \
+[22;1H / / | \
+[15;2H _^_
+[16;2H o / .\
+[17;2H \,--------; __o
+[18;2H / .:::. . /
+[19;2H \___________/
+[20;2H \| |\
+[21;2H \ | \
+[22;2H / \ / |
+[15;3H _^_
+[16;3H o / .\
+[17;3H \,--------; __o
+[18;3H / .:::. . /
+[19;3H \___________/
+[20;3H \\ \|
+[21;3H \\ \
+[22;3H | \ |\
+[15;4H _^_
+[16;4H o / .\
+[17;4H \,--------; __o
+[18;4H / .:::. . /
+[19;4H \___________/
+[20;4H \\ \|
+[21;4H >\ \
+[22;4H / | /|
+[15;5H _^_
+[16;5H o / .\
+[17;5H \,--------; __o
+[18;5H / .:::.. . /
+[19;5H \___________/
+[20;5H |\ |\
+[21;5H | > | \
+[22;5H / / | \
+[15;6H _^_
+[16;6H o / .\
+[17;6H \,--------; __o
+[18;6H / .:::.. . /
+[19;6H \___________/
+[20;6H \| |\
+[21;6H \ | \
+[22;6H / \ / |
+[15;18H
+[16;18H
+[17;18H--,_^_
+[18;18H. .\
+[19;18H__--___o
+[17;18H--_
+[18;18H. \
+[19;18H__ \/|
+[20;18H|\( .|
+[21;18H| \\ /
+[22;18H | "
+[17;18H--_
+[18;18H. \
+[19;18H__ \/|
+[20;18H|\( .|
+[21;18H| \\ /
+[22;18H | "
+[17;18H--_
+[18;18H. \
+[19;18H__ \/|
+[20;18H|\( .|
+[21;18H| \\ /
+[22;18H | "
+[17;18H--_
+[18;18H. \
+[19;18H__ \/|
+[20;18H|\( .|
+[21;18H| \\ /
+[22;18H | "
+[17;18H--,_^_
+[18;18H. .\
+[19;18H__--___o
+[20;18H|\
+[21;18H| \
+[22;18H |
+[15;7H _^_
+[16;7H o / .\
+[17;7H \,--------; __o
+[18;7H / .:::.. . /
+[19;7H \___________/
+[20;7H \\ \|
+[21;7H \\ \
+[22;7H | \ |\
+[15;8H _^_
+[16;8H o / .\
+[17;8H \,--------; __o
+[18;8H / .:::.. . /
+[19;8H \___________/
+[20;8H \\ \|
+[21;8H >\ \
+[22;8H / | /|
+[15;9H _^_
+[16;9H o / .\
+[17;9H \,--------; __o
+[18;9H / .:::.. . /
+[19;9H \___________/
+[20;9H |\ |\
+[21;9H | > | \
+[22;9H / / | \
+[15;10H _^_
+[16;10H o / .\
+[17;10H \,--------; __o
+[18;10H / .:::.. . /
+[19;10H \___________/
+[20;10H \| |\
+[21;10H \ | \
+[22;10H / \ / |
+[15;11H _^_
+[16;11H o / .\
+[17;11H \,--------; __o
+[18;11H / .:::.. . /
+[19;11H \___________/
+[20;11H \\ \|
+[21;11H \\ \
+[22;11H | \ |\
+[15;12H _^_
+[16;12H o / .\
+[17;12H \,--------; __o
+[18;12H / .:::.. . /
+[19;12H \___________/
+[20;12H \\ \|
+[21;12H >\ \
+[22;12H / | /|
+[15;13H _^_
+[16;13H o / .\
+[17;13H \,--------; __o
+[18;13H / .:::.. . /
+[19;13H \___________/
+[20;13H |\ |\
+[21;13H | > | \
+[22;13H / / | \
+[15;14H _^_
+[16;14H o / .\
+[17;14H \,--------; __o
+[18;14H / .:::.. . /
+[19;14H \___________/
+[20;14H \| |\
+[21;14H \ | \
+[22;14H / \ / |
+[15;15H _^_
+[16;15H o / .\
+[17;15H \,--------; __o
+[18;15H / .:::.. . /
+[19;15H \___________/
+[20;15H \\ \|
+[21;15H \\ \
+[22;15H | \ |\
+[15;16H _^_
+[16;16H o / .\
+[17;16H \,--------; __o
+[18;16H / .:::.. . /
+[19;16H \___________/
+[20;16H \\ \|
+[21;16H >\ \
+[22;16H / | /|
+[15;17H _^_
+[16;17H o / .\
+[17;17H \,--------; __o
+[18;17H / .:::.. . /
+[19;17H \___________/
+[20;17H |\ |\
+[21;17H | > | \
+[22;17H / / | \
+[15;29H
+[16;29H
+[17;29H--,_^_
+[18;29H. .\
+[19;29H__--___o
+[17;29H--_
+[18;29H. \
+[19;29H__ \/|
+[20;29H|\( .|
+[21;29H| \\ /
+[22;29H| \"
+[17;29H--_
+[18;29H. \
+[19;29H__ \/|
+[20;29H|\( .|
+[21;29H| \\ /
+[22;29H| \"
+[17;29H--,_^_
+[18;29H. .\
+[19;29H__--___o
+[20;29H|\
+[21;29H| \
+[22;29H| \
+[17;29H--,_^_
+[18;29H. .\
+[19;29H__--___o
+[20;29H|\
+[21;29H| \
+[22;29H| \
+[17;29H--_
+[18;29H. \
+[19;29H__ \/|
+[20;29H|\( .|
+[21;29H| \\ /
+[22;29H| \"
+[17;29H--_
+[18;29H. \
+[19;29H__ \/|
+[20;29H|\( .|
+[21;29H| \\ /
+[22;29H| \"
+[17;29H--_
+[18;29H. \
+[19;29H__ \/|
+[20;29H|\( .|
+[21;29H| \\ /
+[22;29H| \"
+[17;29H--,_^_
+[18;29H. .\
+[19;29H__--___o
+[20;29H|\
+[21;29H| \
+[22;29H| \
+[15;18H _^_
+[16;18H o / .\
+[17;18H \,--------; __o
+[18;18H / .:::.. . /
+[19;18H \___________/
+[20;18H \| |\
+[21;18H \ | \
+[22;18H / \ / |
+[15;19H _^_
+[16;19H o / .\
+[17;19H \,--------; __o
+[18;19H / .:::.. . /
+[19;19H \___________/
+[20;19H \\ \|
+[21;19H \\ \
+[22;19H | \ |\
+[15;20H _^_
+[16;20H o / .\
+[17;20H \,--------; __o
+[18;20H / .:::.. . /
+[19;20H \___________/
+[20;20H \\ \|
+[21;20H >\ \
+[22;20H / | /|
+[15;21H _^_
+[16;21H o / .\
+[17;21H \,--------; __o
+[18;21H / .:::.. . /
+[19;21H \___________/
+[20;21H |\ |\
+[21;21H | > | \
+[22;21H / / | \
+[15;22H _^_
+[16;22H o / .\
+[17;22H \,--------; __o
+[18;22H / .:::.. . /
+[19;22H \___________/
+[20;22H \| |\
+[21;22H \ | \
+[22;22H / \ / |
+[15;23H _^_
+[16;23H o / .\
+[17;23H \,--------; __o
+[18;23H / .:::.. . /
+[19;23H \___________/
+[20;23H \\ \|
+[21;23H \\ \
+[22;23H | \ |\
+[15;24H _^_
+[16;24H o / .\
+[17;24H \,--------; __o
+[18;24H / .:::.. . /
+[19;24H \___________/
+[20;24H \\ \|
+[21;24H >\ \
+[22;24H / | /|
+[15;24H
+[16;24H o
+[17;24H \,----------,_^_
+[18;24H / .:::.. . .\
+[19;24H \___________--___o
+[20;24H \\ \|
+[21;24H >\ \
+[22;24H / | /|
+[15;24H
+[16;24H o
+[17;24H \,----------_
+[18;24H / .:::.. . \
+[19;24H \___________ \/|
+[20;24H \\ \|( .|
+[21;24H >\ \ \ /
+[22;24H / | /| "
+[1;15r
+[1;10H`' `.__________________________________/M
+[1;10H( / ([1;54H/M
+[1;10H(-.___[1;55H)M
+[1;11H/ \/[1;55H)M
+[1;12H_______.--'[1;54H\M
+[1;23H,____________/[1;53H\M
+[1;37H( / )M
+[1;37H( ) /M
+[1;37H\ \ )M
+[1;36H( )M
+[1;36H( ( /M
+[1;36H\ ( )M
+[1;35H( \ )M
+[1;35H( ( /M
+[1;16r
+[1;35H\ ( ) )M
+[1;17r
+[1;34H( ( / )M
+[1;18r
+[1;34H( \ ) /M
+[1;19r
+[1;34H\ ( ) )M
+[1;20r
+[1;33H( ) )M
+[1;21r
+[1;33H( ) /M
+[1;22r
+[1;33H\ / )M
+[1;24r
+[1;32H( ) )
+[23;25H / > | \
+[1;1H
+[1;1H
+[10;1H T[10;1H T[10;1H T
+[10;1H T H[10;1H T H[10;1H T H
+[10;1H T H E[10;1H T H E[10;1H T H E [10;1H T H E
+[10;1H T H E E[10;1H T H E E[10;1H T H E E
+[10;1H T H E E N[10;1H T H E E N[10;1H T H E E N
+[10;1H T H E E N D[10;1H T H E E N D
+[11;1H ===============
+[22;1H
+[?25h
Index: third_party/Python/module/pexpect-4.6/tests/depricated_test_filedescriptor.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/depricated_test_filedescriptor.py
+++ third_party/Python/module/pexpect-4.6/tests/depricated_test_filedescriptor.py
@@ -0,0 +1,82 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+import unittest
+import PexpectTestCase
+import os
+
+class ExpectTestCase(PexpectTestCase.PexpectTestCase):
+ def setUp(self):
+ print(self.id())
+ PexpectTestCase.PexpectTestCase.setUp(self)
+
+ def test_fd (self):
+ fd = os.open ('TESTDATA.txt', os.O_RDONLY)
+ s = pexpect.spawn (fd)
+ s.expect ('This is the end of test data:')
+ s.expect (pexpect.EOF)
+ assert s.before == ' END\n'
+
+ def test_maxread (self):
+ fd = os.open ('TESTDATA.txt', os.O_RDONLY)
+ s = pexpect.spawn (fd)
+ s.maxread = 100
+ s.expect('2')
+ s.expect ('This is the end of test data:')
+ s.expect (pexpect.EOF)
+ assert s.before == ' END\n'
+
+ def test_fd_isalive (self):
+ fd = os.open ('TESTDATA.txt', os.O_RDONLY)
+ s = pexpect.spawn (fd)
+ assert s.isalive()
+ os.close (fd)
+ assert not s.isalive()
+
+ def test_fd_isatty (self):
+ fd = os.open ('TESTDATA.txt', os.O_RDONLY)
+ s = pexpect.spawn (fd)
+ assert not s.isatty()
+ os.close(fd)
+
+### def test_close_does_not_close_fd (self):
+### '''Calling close() on a pexpect.spawn object should not
+### close the underlying file descriptor.
+### '''
+### fd = os.open ('TESTDATA.txt', os.O_RDONLY)
+### s = pexpect.spawn (fd)
+### try:
+### s.close()
+### self.fail('Expected an Exception.')
+### except pexpect.ExceptionPexpect, e:
+### pass
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(ExpectTestCase, 'test')
+
+#fout = open('delete_me_1','wb')
+#fout.write(the_old_way)
+#fout.close
+#fout = open('delete_me_2', 'wb')
+#fout.write(the_new_way)
+#fout.close
Index: third_party/Python/module/pexpect-4.6/tests/echo_w_prompt.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/echo_w_prompt.py
+++ third_party/Python/module/pexpect-4.6/tests/echo_w_prompt.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+from __future__ import print_function
+
+try:
+ raw_input
+except NameError:
+ raw_input = input
+
+while True:
+ try:
+ a = raw_input('')
+ except EOFError:
+ print('')
+ break
+ print('', a, sep='')
Index: third_party/Python/module/pexpect-4.6/tests/echo_wait.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/echo_wait.py
+++ third_party/Python/module/pexpect-4.6/tests/echo_wait.py
@@ -0,0 +1,41 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import time
+import termios
+import sys
+
+# a dumb PAM will print the password prompt first then set ECHO
+# False. What it should do it set ECHO False first then print the
+# prompt. Otherwise, if we see the password prompt and type out
+# password real fast before it turns off ECHO then some or all of
+# our password might be visibly echod back to us. Sounds unlikely?
+# It happens.
+
+print("fake password:")
+sys.stdout.flush()
+time.sleep(3)
+attr = termios.tcgetattr(sys.stdout)
+attr[3] = attr[3] & ~termios.ECHO
+termios.tcsetattr(sys.stdout, termios.TCSANOW, attr)
+time.sleep(12)
+attr[3] = attr[3] | termios.ECHO
+termios.tcsetattr(sys.stdout, termios.TCSANOW, attr)
+time.sleep(2)
Index: third_party/Python/module/pexpect-4.6/tests/exit1.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/exit1.py
+++ third_party/Python/module/pexpect-4.6/tests/exit1.py
@@ -0,0 +1,24 @@
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import os, sys
+
+print("Hello")
+sys.stdout.flush()
+os._exit(1)
Index: third_party/Python/module/pexpect-4.6/tests/exit667.c
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/exit667.c
+++ third_party/Python/module/pexpect-4.6/tests/exit667.c
@@ -0,0 +1,26 @@
+/*
+ PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+*/
+
+#include
+int main ()
+{
+ printf ("Hello world!\n");
+ exit(7);
+}
Index: third_party/Python/module/pexpect-4.6/tests/fakessh/ssh
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/fakessh/ssh
+++ third_party/Python/module/pexpect-4.6/tests/fakessh/ssh
@@ -0,0 +1,34 @@
+#!/usr/bin/env python
+from __future__ import print_function
+
+import getpass
+import sys
+PY3 = (sys.version_info[0] >= 3)
+if not PY3:
+ input = raw_input
+
+server = sys.argv[-1]
+if server == 'noserver':
+ print('No route to host')
+ sys.exit(1)
+
+print("Mock SSH client for tests. Do not enter real security info.")
+
+pw = getpass.getpass('password:')
+if pw != 's3cret':
+ print('Permission denied!')
+ sys.exit(1)
+
+prompt = "$"
+while True:
+ cmd = input(prompt)
+ if cmd.startswith('PS1='):
+ prompt = eval(cmd[4:]).replace('\$', '$')
+ elif cmd == 'ping':
+ print('pong')
+ elif cmd.startswith('ls'):
+ print('file1.py', 'file2.html', sep='\t')
+ elif cmd == 'echo $?':
+ print(0)
+ elif cmd in ('exit', 'logout'):
+ break
Index: third_party/Python/module/pexpect-4.6/tests/getch.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/getch.py
+++ third_party/Python/module/pexpect-4.6/tests/getch.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+from __future__ import print_function
+import sys, tty, termios
+
+if hasattr(sys.stdin, 'buffer'):
+ # Python 3: we want to read raw bytes
+ stdin = sys.stdin.buffer
+else:
+ stdin = sys.stdin
+
+def main():
+ print('READY', end='\r\n')
+ while True:
+ try:
+ val = ord(stdin.read(1))
+ except KeyboardInterrupt:
+ val = 3
+ print('%d' % (val,), end='\r\n')
+ if val == 0:
+ # StopIteration equivalent is ctrl+' ' (\x00, NUL)
+ break
+
+if __name__ == '__main__':
+ fd = sys.stdin.fileno()
+ old_settings = termios.tcgetattr(fd)
+ try:
+ tty.setraw(sys.stdin.fileno())
+ main()
+ finally:
+ termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
+ sys.stdout.flush()
Index: third_party/Python/module/pexpect-4.6/tests/globe.vt
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/globe.vt
+++ third_party/Python/module/pexpect-4.6/tests/globe.vt
@@ -0,0 +1,690 @@
+[H[J _-o#&&*''''?d:>b\_
+ _o/"`'' '',, dMF9MMMMMHo_
+ .o' `"MbHMMMMMMMMMMMHo.
+ .o"" ' vodM*$&&HMMMMMMMMMM?.
+ ,' $M&ood,~'`(#MMMMMMH\
+ / ,MMMMMMM#b?#bobMMMMHMMML
+ & ?MMMMMMMMMMMMMMMMM7MMM$R*Hk
+ ?$. :MMMMMMMMMMMMMMMMMMM/HMMM|`*L
+| |MMMMMMMMMMMMMMMMMMMMbMH' T,
+$H#: `*MMMMMMMMMMMMMMMMMMMMb#}' `?
+]MMH# ""*""""*#MMMMMMMMMMMMM' -
+MMMMMb_ |MMMMMMMMMMMP' :
+HMMMMMMMHo `MMMMMMMMMT .
+?MMMMMMMMP 9MMMMMMMM} -
+-?MMMMMMM |MMMMMMMMM?,d- '
+ :|MMMMMM- `MMMMMMMT .M|. :
+ .9MMM[ &MMMMM*' `' .
+ :9MMk `MMM#" -
+ &M} ` .-
+ `&. .
+ `~, . ./
+ . _ .-
+ '`--._,dd###pp=""'
+[H _v->#H#P? "':o<>\_
+ .,dP` `'' "'-o.+H6&MMMHo_
+ oHMH9' `?&bHMHMMMMMMHo.
+ oMP"' ' ooMP*#&HMMMMMMM?.
+ ,M* - `*MSdob//`^#MMMH\
+ d*' .,MMMMMMH#o>#ooMMMMMb
+ HM- :HMMMMMMMMMMMMMMM&HM[R\
+ d"Z\. 9MMMMMMMMMMMMMMMMM[HMM|:
+-H - MMMMMMMMMMMMMMMMMMMbMP' :
+:??Mb# `9MMMMMMMMMMMMMMMMMMH#! .
+: MMMMH#, "*""""`#HMMMMMMMMMMH -
+||MMMMMM6\. {MMMMMMMMMH' :
+:|MMMMMMMMMMHo `9MMMMMMMM' .
+. HMMMMMMMMMMP' !MMMMMMMM `
+- `#MMMMMMMMM HMMMMMMM*,/ :
+ : ?MMMMMMMF HMMMMMM',P' :
+ . HMMMMR' {MMMMP' ^' -
+ : `HMMMT iMMH' .'
+ -.`HMH .
+ -:*H . '
+ -`\,, . .-
+ ' . _ .-`
+ '`~\.__,obb#q==~'''
+[H .ovr:HMM#?:`' >b\_
+ .,:&Hi' `' "' \\|&bSMHo_
+ oHMMM#*} `?&dMMMMMMHo.
+ .dMMMH"'''' ,oHH*&&9MMMM?.
+ ,MMM*' `*M\bd<|"*MH\
+ dHH?' :MMMMMM#bd#odMML
+ H' |\ `dMMMMMMMMMMMMMM9Mk
+ JL/"7+,. `MMMMMMMMMMMMMMMH9ML
+-`Hp ' |MMMMMMMMMMMMMMMMHH|:
+: \\#M#d? `HMMMMMMMMMMMMMMMMH.
+. JMMMMM##, ``*""'"*#MMMMMMMMH
+-. ,MMMMMMMM6o_ |MMMMMMMM':
+: |MMMMMMMMMMMMMb\ TMMMMMMT :
+. ?MMMMMMMMMMMMM' :MMMMMM|.`
+- ?HMMMMMMMMMM: HMMMMMM\|:
+ : 9MMMMMMMMH' `MMMMMP.P.
+ . `MMMMMMT'' HMMM*''-
+ - TMMMMM' MM*' -
+ '. HMM# -
+ -. `9M: .'
+ -. `b,, . . '
+ '-\ ., .-`
+ '-:b~\\_,oddq==--"
+[H _oo##'9MMHb':'-,o_
+ .oH":HH$' ""' "' -\7*R&o_
+ .oHMMMHMH#9: "\bMMMMHo.
+ dMMMMMM*""'`' .oHM"H9MM?.
+ ,MMMMMM' "HLbd<|?&H\
+ JMMH#H' |MMMMM#b>bHb
+ :MH ."\ `|MMMMMMMMMMMM&
+ .:M:d-"|:b.. 9MMMMMMMMMMMMM+
+: "*H| - &MMMMMMMMMMMMMH:
+. `LvdHH#d? `?MMMMMMMMMMMMMb
+: iMMMMMMH#b `"*"'"#HMMMMMM
+. . ,MMMMMMMMMMb\. {MMMMMH
+- |MMMMMMMMMMMMMMHb, `MMMMM|
+: |MMMMMMMMMMMMMMH' &MMMM,
+- `#MMMMMMMMMMMM |MMMM6-
+ : `MMMMMMMMMM+ ]MMMT/
+ . `MMMMMMMP" HMM*`
+ - |MMMMMH' ,M#'-
+ '. :MMMH| .-
+ . |MM -
+ ` . `#?.. . ..'
+ -. _. .-
+ '-|.#qo__,,ob=~~-''
+[H _ooppH[`MMMD::--\_
+ _oHMR":&M&. ""' "' /&\\_
+ oHMMMMMHMMH#9, `"#&H6?*MMH:-.._
+ .oHMMMR:"&MZ\ `"' " |$-_
+ ..dMMMMMMMMdMMM#9\ `'HHo.
+ . ,dMMMMMMMMMMM"`' ` ?MP?.
+ . |MMMMMMMMMMM' `"$b&\
+ - |MMMMHH##M' HMMH?
+ - TTMM| >.. \MMMMMH
+ : |MM\,#-""$~b\. `MMMMMM+
+. ``"H - &MMMMMM|
+: *\v,#MHddc. `9MMMMMb
+. MMMMMMMM##\ `"":HM
+- . .HMMMMMMMMMMRo_. |M
+: |MMMMMMMMMMMMMMMM#\ :M
+- `HMMMMMMMMMMMMMMM' |T
+: `*HMMMMMMMMMMMM' H'
+ : MMMMMMMMMMM| |T
+ . MMMMMMMM?' ./
+ `. MMMMMMH' ./
+ -. |MMMH#' .
+ . `MM* . '
+ -. #M: . . .-
+ ` . ., .-
+ '-.-~ooHH__,,v~--`
+[H _ood>H&H&Z?#M#b-\.
+ .\HMMMMMR?`\M6b."`' ''``v.
+ .. .MMMMMMMMMMHMMM#&. ``~o.
+ . ,HMMMMMMMMMMMM*"'-` &b.
+ . .MMMMMMMMMMMMH' `"&\
+ - RMMMMM#H##R' 4Mb
+ - |7MMM' ?:: `|MMb
+ / HMM__#|`"\>?v.. `MMML
+. `"'#Hd| ` 9MMM:
+- |\,\?HH#bbL `9MMb
+: !MMMMMMMH#b, `""T
+. . ,MMMMMMMMMMMbo. |
+: 4MMMMMMMMMMMMMMMHo |
+: ?MMMMMMMMMMMMMMM? :
+-. `#MMMMMMMMMMMM: .-
+ : |MMMMMMMMMM? .
+ - JMMMMMMMT' :
+ `. MMMMMMH' -
+ -. |MMM#*` -
+ . HMH' . '
+ -. #H:. .-
+ ` . .\ .-
+ '-..-+oodHL_,--/-`
+[H _,\?dZkMHF&$*q#b..
+ .//9MMMMMMM?:'HM\\"`-''`..
+ ..` :MMMMMMMMMMHMMMMH?_ `-\
+ . .dMMMMMMMMMMMMMM'"'" `\.
+ . |MMMMMMMMMMMMMR \\
+ - T9MMMMMHH##M" `?
+ : (9MMM' !':. &k
+ .: HMM\_?p "":-b\. `ML
+- "'"H, : |M|
+: ?\,\dMH#b#. 9b
+: |MMMMMMM##, `*
+: . +MMMMMMMMMMMo_ -
+: HMMMMMMMMMMMMMM#, :
+: 9MMMMMMMMMMMMMH' .
+: . *HMMMMMMMMMMP .'
+ : MMMMMMMMMH' .
+ - :MMMMMMM'` .
+ `. 9MMMMM*' -
+ -. {MMM#' :
+ - |MM" .'
+ `. &M'.. . ..'
+ ' . ._ .-
+ '-. -voboo#&:,-.-`
+[H _oo:\bk99M[<$$+b\.
+ .$*"MMMMMMMM[:"\Mb\?^" .
+ . '` HMMMMMMMMMMHMMMM+?. `.
+ . .HMMMMMMMMMMMMMMP"'' .
+ . `MMMMMMMMMMMMMM| -`.
+ - `&MMMMMMHH##H: :
+ : `(*MMM} `|\ |
+ : `- ?MMb__#|""`|+v.. \
+. `''*H#b - :|
+: `*\v,#M#b#, \
+. 9MMMMMMHb. :
+: . #MMMMMMMMMb\ -
+- .HMMMMMMMMMMMMb :
+: `MMMMMMMMMMMMH .
+-: . `#MMMMMMMMMP '
+ : ]MMMMMMMH' :
+ - ,MMMMMM?' .
+ `: HMMMMH" -
+ -. .HMM#* .-
+ `. .HH*' .
+ `-. &R". .-
+ -. ._ .-
+ '-. .voodoodc?..-`
+[H _\oo\?ddk9MRbS>v\_
+ ..:>*""MMMMMMMMM:?|H?$?-.
+ ..- - "HMMMMMMMMMMHMMMH\_-.
+ . dMMMMMMMMMMMMMMT" .
+ . TMMMMMMMMMMMMMM `.
+ - `&HMMMMMM#H#H: .
+ - `\7HMMH |\. .
+ : ` HMM\_?c`""+?\.. :
+- "``#| . -
+: `?,\#MHdb. .
+: |MMMMMH#. :
+: . ,HMMMMMMMb, -
+: ' 4MMMMMMMMMMH`
+: . 9MMMMMMMMMT-
+:.` `#MMMMMMMH '
+ : ' HMMMMMH':
+ - |MMMMH" -
+ `: |MMMH*' .'
+ '? dMM#' .
+ \. .dH" .'
+ -. ,M'- ..'
+ ` . .. ..-`
+ '-. .\ooooboo<^.-`
+[H _o,:o?\?dM&MHcc~,.
+ ..^':""HMMMMMMMM$:?&&?.
+ .` -` 'HMMMMMMMMMHMMMp\.
+ . ' |MMMMMMMMMMMMMM"' .
+ . `9MMMMMMMMMMMMM -.
+ - `*9MMMMMHH##[ .
+ - `\Z9MMM `~\ .
+ : '| ?MMb_?p""-?v.. :
+- `"'*, - .
+: `?,oHH#? .
+-- |MMMMH,:
+: . |MMMMMM6,
+: - |MMMMMMMM
+? HMMMMMMP
+-- . ' |HMMMMM'
+ :.` . ' JMMMM+
+ \ ,MMMP:
+ : |MMH?:
+ -:\. dM#" .
+ \ ,H*' .'
+ -. d':..'
+ ` . .,.-
+ '-.. .\oooodov~^-`
+[H _o\:,??\??MR9#cb\_
+ .v/''':""#HMMMMMMM$?*d\.
+ ..~' - -` `"#MMMMMMMMMMMHv.
+ .-' HMMMMMMMMMMMR!.
+ : `9MMMMMMMMMMM| -.
+ . `*9MMMMMH##| .
+ - `(#MMH `:, .
+ : '| `HMb_>/"|\,.:
+.' `"'#&b - .
+: ?\oHH?.
+: !MMM&
+: . . HMMMM
+/. - -MMMMM
+\`. 9MMMP
+:. . . - |MMM'
+ \... ' .MMT
+ &. .dMP
+ \, .HM*
+ \. `\. ,H&'
+ `- `| - ,&':
+ `. ,/\ '
+ '-.. _.-
+ "---.._\o,oov+--'"
+[H _,d?,:?o?:?HM>#b\_
+ ..H*"''`'H#*"**MMMMMM6$$v_
+ v//" - `` `'#MMMMMMMMHo.
+ /"` |MMMMMMMMMM:.
+ ,> `HMMMMMMMMH:.
+ : `#HMMMMHH\ -
+ ' `Z#MM, `,:
+ : '\ ?HH_>:`\,
+: "'*&| `:
+. <\Hb
+: MM
+: . iMM
+Mb\. {MM
+::.`- - !MP
+`&. . . - :M'
+ 9H, \ ' |T
+ HM? ,P
+ *ML ??
+ :&. `o .d'
+ ': |T /"
+ -. .<''
+ `... ..-
+ "`-=.,_,,,oov-~.-`
+[H _,oc>?_:b?o?HH#b\_
+ .v/99*""" '*H#""*HMMMMMZ,_
+ oH* /" - ' "`#MMMMM#o.
+ ./*>- `MMMMMMMb
+ ,b/' `#MMMMMMM\
+ :' ``HMMMMb:
+ /- `|&MH `\
+ / `-. |Hb??\
+,- ' "`&,.
+1 \}
+!. T
+$,. . 1
+?`M??. M
+?.::| '\ - ?
+ M?&. . . - ,'
+ 9MMH\ .. ' ` .
+ HMMM#. :'
+ 9#MMb ..
+ -:"# `b. .-
+ . ` {! /
+ - ,-'
+ ' . .-
+ ```^==\_.,,,ov--\-`
+[H _\o##??,:io??$#b\_
+ .oH#"H9*""" "`#H*"*#MMMHo_
+ oHMM- -' - '' ``*HMMHo.
+ dM#S>-` ?MMMM?.
+ ,&&,/' "#MMMH\
+ d?-" `*HMMb
+ H? "ZHb:
+ /: \ H?L
+|:| . `*:
+:?: \
+>" :
+M|\,_ |
+!|":HH?-'. :
+:^'_:?"\ `-- - .
+- |ML?b . .. - -
+ :HMMMMH\ \ ` :
+ >MMMMMM#. .
+ ^M*HMMM| -
+ `. `"#+ `?v .`
+ . `- +?' -
+ ` . ..'
+ - . .-
+ "`\b=p?.._\\vv---`
+[H _,o#bH\??::?o?cbo_
+ .o#MH#**SH""' "`*H#"*#MHo_
+ oHMMMH^ ^" - ` '*HHo.
+ .dMMM#">>- `HM?.
+ ,MH:R_o/ `*MH\
+ dMM' ' "ML
+ HMR! ' `#k
+ d&'. -. `L
+:M :: ` `-
+/| !| -
+k.$-" :
+}9R:!,,_. .
+\::\':`*M#\-'. -
+: "''..:"!`\ '- - `
+- ,HMb.H| . _ - .'
+ : ,MMMMMMMb. .. .
+ .`HMMMMMMMM? .
+ `.`9M#*HMMMM :
+ -.' "##* `b, .
+ . ` ,/' .'
+ ` . ..'
+ - . ..-
+ "`*#d##c.._\v----`
+[H _,o#&oHb?\o::d?>\_
+ .oHHMMM#**$M""` "`*HH"#&o_
+ oHMMMMMMD' .'' - ' ``bo.
+ .dMMMMMH*'/|- `\b.
+ ,MMMM?T|_o/ `\\
+ dMMMMP '' `|
+ HMMMH& - `\
+ /MH7' : -- :
+-:MM {. . .
+:i?' .!& .
+:{, o| ' :
+-T?9M\:-'o,_ .
+: \?::``"`?9MHo./.. -
+. '"`'^ _.`"!"^. `- - `
+- ,bMM?.M\ . . - . .'
+ : .oMMMMMMMMb. .. ` .
+ . `HMMMMMMMMMMb -
+ - 9MH*#HMMMMH .'
+ '. ' `"*##' `b. :
+ . ` .d'' .'
+ -. . '
+ -. .-`
+ "`*##H###:._\--.-`
+[H _oo#H&d#b?\b:_>>\_
+ .oHMMMMMMH*"*9R"'-``*#P\-_
+ oHMMMMMMMMM$ ." ' `^-
+ .dMMMMMMMMH*",?- '\.
+ ,MMMMMMM:?}.,d' `.
+ dMMMMMMMH /'' :
+ HMMMMMMM&' - -
+ dPTMMP>' : -. :
+|? -MM} .\ .
+J' ::*' -$L .
+: ?b .,H- ' :
+- |6.&MP:: !.,_. -
+: `\:: "' "`:"MM#,-^, - :
+- ````:' _.:"?``\ `- .
+: .?bMML.]# - _ ` . .'
+ - .o#MMMMMMMMH\ \. . .
+ - `HMMMMMMMMMMMH :
+ `. `HMM#*#MMMMMH' -
+ -. ' ``##*' i+ :
+ - `' v/' .'
+ `- ..'
+ ' . .-
+ "`*##HMH##:__,-.-`
+[H _oo##Mbb&bo??o_>\_
+ .oHMMMMMMMMM**#?M*' "?*&..
+ oHMMMMMMMMMMMM4 `" - `.
+ .dMMMMMMMMMMMM#"\?.- .
+ ,MMMMMMMMMM}"9:_,d' -.
+ dMMMMMMMMMMM| ^'' .
+ &MMMMMMMMMMH\ - .
+ :{M*"MMMPT"' : `-. :
+.'M' 'MMM. -T, . .
+- k i:?'' -|& .
+: ` -o& .,H- " :
+- `M:`HMP|:'!.o._. .
+: "<:::'<^ '"``9MH#,-^ . -
+- '''``''._.`"?`^| ^ - :
+: ?#dMM_.M? . . - ..'
+ : ,ddMMMMMMMMMb. .. ' .
+ . TMMMMMMMMMMMMM, :
+ - ?MMH**#MMMMMH' :
+ '. ' "`##*' &. :
+ -. `' ,~" .'
+ -. ..'
+ ` . .-
+ ```*##HMMMH#<:,..-`
+[H _,dd#HMb&dHo?\?:\_
+ .oHMMMMMMMMMMMH***9P'`"\v.
+ oHMMMMMMMMMMMMMMM> `' -.
+ .dMMMMMMMMMMMMMMMH*'|~-' .
+ ,MMMMMMMMMMMMM6>`H._,& -.
+ dMMMMMMMMMMMMMMM| `" .
+ H*MMMMMMMMMMMMMH&. - .
+ d' HMM""&MMMPT'' :. `.-
+,' MP `TMMM, |: . -
+| #: ? *" : &L :
+! `' /?H ,#r `' :
+. ?M: HMM^<~->,o._ :
+: `9:::'`*-``':`9MHb,|-, ' :
+. `"''':' :_ ""!"^. `| :
+`. _dbHM6_|H. . . ' .'
+ \ _odHMMMMMMMMH, .. ` :
+ `- |MMMMMMMMMMMMM| :
+ `. 9MMH**#MMMMMH' :
+ -. ' "?##" d :
+ . ' ,/" .'
+ `.. ..'
+ ` . .-
+ '`"#HHMMMMM#<>..-`
+[H _oo##bHMb&d#bd,>\_
+ .oHMMMMMMMMMMMMMM***9R"-..
+ oHMMMMMMMMMMMMMMMMMH\ ? `-.
+ .dMMMMMMMMMMMMMMMMMMM#".}-' .
+ ,MMMMMMMMMMMMMMMMM6/`H _o} -.
+ dMMMMMMMMMMMMMMMMMMML `'' .
+ HbP*HMMMMMMMMMMMMMMM*: - ,
+ dMH' `MMMP'"HMMMR'T" : :
+|H' -MR' `?MMMb P, . .
+1& *| |.`*" .-`&| .
+M' " |\&| .,#~ "' :
+T :HL.|HMH\c~`|v,\_ :
+| `"|:::':`-`` '"MM#\-'. -:
+% ``'``'`' :_ '?'`| ``. :
+||, ,#dMM?.M? . .` -
+ ?\ .,odMMMMMMMMM? \ ` :
+ / |MMMMMMMMMMMMM: .'
+ `. TMMH#*9MMMMM* :
+ -. ` "*#*' ,: .
+ . ` .v'' .'
+ `. ..'
+ '- . .-
+ "`\+HHMMMMMMHr~.-`
+[H _,,>#b&HMHd&&bb>\_
+ _oHMMMMMMMMMMMMMMMMH**H:.
+ oHMMMMMMMMMMMMMMMMMMMM#v`? `.
+ .dMMMMMMMMMMMMMMMMMMMMMMH*`+| .
+ ,MMMMMMMMMMMMMMMMMMMMMb|?+.,H -.
+ ddHMMMMMMMMMMMMMMMMMMMMMb `' .
+ HMMkZ**HMMMMMMMMMMMMMMMMH\ - . :
+ dTMMM* `9MMMP'"*MMMMPT"` .. :
+|M6H'' 4MP' `"HMMM| !|. . .
+1MHp' #L $ *"' .-:&. .
+MMM' " q:H. .o#-``' :
+MM' ?H?.|MMH::::-o,_. -
+M[ `*?:::'|` `"`:9MH\~-. `
+&M. ""'`'^'.:.`?'`. '| -:
+`M|d, .dbHM[.1? .. :
+ 9||| . _obMMMMMMMMH, . :
+ H.^ MMMMMMMMMMMM} -
+ \ |MMH#*HMMMMH' .'
+ . ` `#*' ,:-
+ ` '' .-'.
+ `. .-
+ '- . .-`
+ '`\bqHMMMMMMHHb--`
+[H .,:,#&6dHHHb#o\_
+ .oHHMMMMMMMMMMMMMMMMMH*\,.
+ oHMMMMMMMMMMMMMMMMMMMMMMHb:'-.
+ .dMMMMMMMMMMMMMMMMMMMMMMMMMH|\/' .
+ ,&HMMMMMMMMMMMMMMMMMMMMMMM/"&.,d. -.
+ dboMMHMMMMMMMMMMMMMMMMMMMMMML `' .
+ HMHMMM$Z***MMMMMMMMMMMMMMMMMM|.- .
+ dMM}MMMM#' `9MMMH?"`MMMMR'T' _ :
+|MMMbM#'' |MM" ``MMMH. <_ .
+dMMMM#& *&. .?`*" .'&: .
+MMMMMH- `' -v/H .dD "' ' :
+MMMM* `*M: 4MM*::-!v,_ :
+MMMM `*?::" "'``"?9Mb::. :
+&MMM, `"'"'|"._ "?`| - :
+`MMM}.H ,#dM[_H ..:
+ 9MMi`M: . .ooHMMMMMMM, ..
+ 9Mb `- 1MMMMMMMMMM| :
+ ?M |MM#*#MMMM* .
+ -. ` |#"' ,'
+ . -" v`
+ -. .-
+ - . . `
+ '-*#d#HHMMMMHH#"-'
+[H _,<_:&S6dHHHb&bb\_
+ .odHMMMMMMMMMMMMMMMMMMM}-_
+ .oHMMMMMMMMMMMMMMMMMMMMMMMM#d:.
+ ?9MMMMMMMMMMMMMMMMMMMMMMMMMMMH-$ .
+ ,::dHMMMMMMMMMMMMMMMMMMMMMMMMH:\.?? -.
+ dMdboHMMHMMMMMMMMMMMMMMMMMMMMMMH, ' .
+ HMMMM7MMMb$R***MMMMMMMMMMMMMMMMMH\ - .
+ dMMMMM/MMMMM* `$MMMM*'"*MMMM?&' . :
+|MMMMMMb1H*' HMP' '9MMM| &. . .
+dMMMMMMM##~` `#\ |.`*" .-9. :
+9MMMMMMMM* ` |v7? .,H `' ` :
+SMMMMMMH' '9M_-MMH::-\v_ :
+:HMMMMM `\_:"'|'`':9Mv\.
+-|MMMMM, ""`'`':.`?\ \
+`:MMMMM}.d} .?bM6,| |
+ :?MMM6 M| . .,oHMMMMM| /
+ .?MMM- `' &MMMMMMMM|.
+ -`HM- HMH#*MMM?:
+ '. ' `#*:`
+ - -'/
+ ` . . '
+ ` . . `
+ '--##HH#HMMMHH#""`
+[H _o,d_?dZdoHHHb#b\_
+ .vdMMMMMMMMMMMMMMMMMMMMH\.
+ .,HHMMMMMMMMMMMMMMMMMMMMMMMMH&,.
+ /?RMMMMMMMMMMMMMMMMMMMMMMMMMMMMH|..
+ ,\?>`T#RMMMMMMMMMMMMMMMMMMMMMMMM6`\|/
+ dMMbd#ooHMMMHMMMMMMMMMMMMMMMMMMMMMH,`' '
+ HMMMMMMMTMMMMb$ZP**HMMMMMMMMMMMMMMMM|. :
+ dMMMMMMMM}$MMMMMH' `HMMMH?"`MMMM?T' . :
+|MMMMMMMMMMoMH*'' `MM? ``MMM| +\ .
+1MMMMMMMMMMMb#/ ?#? |`#" -T: :
+*'HMMMMMMMMMM*' " ~?& .?} ' ' .
+- 4MMMMMMMMP" `M? HMTc:\\.:
+: `MMMMMMM[ "#:::`>`"?M{
+. |MMMMMMH. ``'``'_`:-
+- |MMMMMMM|.dD ,#Mb\'
+ : *MMMMM: iM| . _oHMMMM:
+ . ?MMMM' "' ,MMMMMMP
+ : `HMH JM#*MMT
+ -. ' ` #'
+ . /
+ -. - .'
+ -. . `
+ '--=&&MH##HMHH#"""
+[H .-:?,Z?:&$dHH##b\_
+ ,:bqRMMMMMMMMMMMMMMMMMHo.
+ .?HHHMMMMMMMMMMMMMMMMMMMMMMMHo.
+ -o/*M9MMMMMMMMMMMMMMMMMMMMMMMMMMMv
+ .:H\b\'|?#HHMMMMMMMMMMMMMMMMMMMMMM6?Z\
+ .?MMMHbdbbodMMMMHMMMMMMMMMMMMMMMMMMMM\':
+ :MMMMMMMMMMM7MMMMb?6P**#MMMMMMMMMMMMMMM_ :
+ \MMMMMMMMMMMMb^MMMMMM? `*MMMM*"`MMMR<' . -
+.1MMMMMMMMMMMMMb]M#"" 9MR' `?MMb \. :
+-MMMMMMMMMMMMMMMH##|` *&. |`*' .\ .
+-?""*MMMMMMMMMMMMM' ' |?b ,}" :
+: MMMMMMMMMMH' `M_|M}r\?
+. `MMMMMMMMM' `$_:`'"H
+- TMMMMMMMM, '"``::
+: {MMMMMMMM| oH| .#M-
+ : `9MMMMMM' .MP . ,oMMT
+ . HMMMMP' `' ,MMMP
+ - `MMH' HH9*
+ '. ` ` .'
+ - . '
+ ` . - .-
+ ` . .-
+ ' -==pHMMH##HH#"""
+[H _..-:b&::&?&#bo_
+ ...?-#&9MMMMMMMMMMMMMMMHo_
+ .. .1MMHMMMMMMMMMMMMMMMMMMMHo.
+ . .o/##R9MMMMMMMMMMMMMMMMMMMMMMMM?.
+ .- |MSd?|'`$?#HMMMMMMMMMMMMMMMMMMMMMH\
+ - dMMMMHbd##oodMMMM#MMMMMMMMMMMMMMMMMH:
+ - JMMMMMMMMMMMMM7HMMMH$SR***MMMMMMMMMMMMb>
+ : {MMMMMMMMMMMMMMM`9MMMMMH' ``HMMM?"*MM[| :
+- |MMMMMMMMMMMMMMMMM
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+try:
+ # This allows coverage to measure code run in this process
+ import coverage
+ coverage.process_startup()
+except ImportError:
+ pass
+
+from utils import no_coverage_env
+import pexpect
+import sys
+
+
+def main():
+ p = pexpect.spawn('{sys.executable} getch.py'.format(sys=sys),
+ env=no_coverage_env())
+
+ # defaults matches api
+ escape_character = chr(29)
+ encoding = None
+
+ if len(sys.argv) > 1 and '--no-escape' in sys.argv:
+ escape_character = None
+
+ if len(sys.argv) > 1 and '--utf8' in sys.argv:
+ encoding = 'utf8'
+
+ p.interact(escape_character=escape_character)
+
+ print("Escaped interact")
+
+if __name__ == '__main__':
+ main()
Index: third_party/Python/module/pexpect-4.6/tests/list100.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/list100.py
+++ third_party/Python/module/pexpect-4.6/tests/list100.py
@@ -0,0 +1,2 @@
+# -*- coding: utf-8 -*-
+print(list(range(100)))
Index: third_party/Python/module/pexpect-4.6/tests/needs_kill.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/needs_kill.py
+++ third_party/Python/module/pexpect-4.6/tests/needs_kill.py
@@ -0,0 +1,13 @@
+#!/usr/bin/env python
+"""This script can only be killed by SIGKILL."""
+import signal, time
+
+# Ignore interrupt, hangup and continue signals - only SIGKILL will work
+signal.signal(signal.SIGINT, signal.SIG_IGN)
+signal.signal(signal.SIGHUP, signal.SIG_IGN)
+signal.signal(signal.SIGCONT, signal.SIG_IGN)
+
+print('READY')
+while True:
+ time.sleep(10)
+
\ No newline at end of file
Index: third_party/Python/module/pexpect-4.6/tests/pexpectTest.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/pexpectTest.py
+++ third_party/Python/module/pexpect-4.6/tests/pexpectTest.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+import time
+import pexpect
+import sys
+
+def getProcessResults(cmd, timeLimit=20):
+ '''
+ executes 'cmd' as a child process and returns the child's output,
+ the duration of execution, and the process exit status. Aborts if
+ child process does not generate output for 'timeLimit' seconds.
+ '''
+ output = ""
+ startTime = time.time()
+ child = pexpect.spawn(cmd, timeout=10)
+ child.logfile = sys.stdout
+
+ while 1:
+ try:
+ # read_nonblocking will add to 'outout' one byte at a time
+ # newlines can show up as '\r\n' so we kill any '\r's which
+ # will mess up the formatting for the viewer
+ output += child.read_nonblocking(timeout=timeLimit).replace("\r","")
+ except pexpect.EOF as e:
+ print(str(e))
+ # process terminated normally
+ break
+ except pexpect.TIMEOUT as e:
+ print(str(e))
+ output += "\nProcess aborted by FlashTest after %s seconds.\n" % timeLimit
+ print(child.isalive())
+ child.kill(9)
+ break
+
+ endTime = time.time()
+ child.close(force=True)
+
+ duration = endTime - startTime
+ exitStatus = child.exitstatus
+
+ return (output, duration, exitStatus)
+
+cmd = "./ticker.py"
+
+result, duration, exitStatus = getProcessResults(cmd)
+
+print("result: %s" % result)
+print("duration: %s" % duration)
+print("exit-status: %s" % exitStatus)
+
Index: third_party/Python/module/pexpect-4.6/tests/platform_checks/CSIGNALTEST/test.c
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/platform_checks/CSIGNALTEST/test.c
+++ third_party/Python/module/pexpect-4.6/tests/platform_checks/CSIGNALTEST/test.c
@@ -0,0 +1,90 @@
+/* I built this with "gcc -lutil test.c -otest" */
+#include /* include this before any other sys headers */
+#include /* header for waitpid() and various macros */
+#include /* header for signal functions */
+#include /* header for fprintf() */
+#include /* header for fork() */
+#ifdef LINUX
+#include
+#else
+#include /* header for forkpty, compile with -lutil */
+#endif
+
+void sig_chld(int); /* prototype for our SIGCHLD handler */
+
+int main()
+{
+ struct sigaction act;
+ int pid;
+ int fdm;
+ char slave_name [20];
+
+
+ /* Assign sig_chld as our SIGCHLD handler.
+ We don't want to block any other signals in this example
+ We're only interested in children that have terminated, not ones
+ which have been stopped (eg user pressing control-Z at terminal).
+ Finally, make these values effective. If we were writing a real
+ application, we would save the old value instead of passing NULL.
+ */
+ act.sa_handler = sig_chld;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_NOCLDSTOP;
+ if (sigaction(SIGCHLD, &act, NULL) < 0)
+ {
+ fprintf(stderr, "sigaction failed\n");
+ return 1;
+ }
+
+ /* Do the Fork thing.
+ */
+ pid = forkpty (&fdm, slave_name, NULL, NULL);
+ /* pid = fork(); */
+
+ switch (pid)
+ {
+ case -1:
+ fprintf(stderr, "fork failed\n");
+ return 1;
+ break;
+
+ case 0: /* Child process. */
+ printf ("This child output will cause trouble.\n");
+ _exit(7);
+ break;
+
+ default: /* Parent process. */
+ sleep(1);
+ printf ("Child pid: %d\n", pid);
+ sleep(10); /* let child finish -- crappy way to avoid race. */
+ break;
+ }
+
+ return 0;
+}
+
+void sig_chld(int signo)
+{
+ int status, wpid, child_val;
+
+ printf ("In sig_chld signal handler.\n");
+
+ /* Wait for any child without blocking */
+ wpid = waitpid (-1, & status, WNOHANG);
+ printf ("\tWaitpid found status for pid: %d\n", wpid);
+ if (wpid < 0)
+ {
+ fprintf(stderr, "\twaitpid failed\n");
+ return;
+ }
+ printf("\tWaitpid status: %d\n", status);
+
+ if (WIFEXITED(status)) /* did child exit normally? */
+ {
+ child_val = WEXITSTATUS(status);
+ printf("\tchild exited normally with status %d\n", child_val);
+ }
+ printf ("End of sig_chld.\n");
+}
+
+
Index: third_party/Python/module/pexpect-4.6/tests/platform_checks/README
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/platform_checks/README
+++ third_party/Python/module/pexpect-4.6/tests/platform_checks/README
@@ -0,0 +1,2 @@
+These scripts are for checking how the underlying system behaves, not for
+testing Pexpect itself.
\ No newline at end of file
Index: third_party/Python/module/pexpect-4.6/tests/platform_checks/check.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/platform_checks/check.py
+++ third_party/Python/module/pexpect-4.6/tests/platform_checks/check.py
@@ -0,0 +1,77 @@
+#!/usr/bin/env python
+import signal
+import os
+import time
+import pty
+
+def signal_handler (signum, frame):
+ print 'Signal handler called with signal:', signum
+ print 'signal.SIGCHLD=', signal.SIGKILL
+
+# First thing we do is set up a handler for SIGCHLD.
+signal.signal (signal.SIGCHLD, signal.SIG_IGN)
+
+print 'PART 1 -- Test signal handling with empty pipe.'
+# Create a child process for us to kill.
+try:
+ pid, fd = pty.fork()
+except Exception as e:
+ print str(e)
+
+if pid == 0:
+# os.write (sys.stdout.fileno(), 'This is a test.\n This is a test.')
+ time.sleep(10000)
+
+print 'Sending SIGKILL to child pid:', pid
+os.kill (pid, signal.SIGKILL)
+
+# SIGCHLD should interrupt sleep.
+# Note that this is a race.
+# It is possible that the signal handler will get called
+# before we try to sleep, but this has not happened yet.
+# But in that case we can only tell by order of printed output.
+print 'Entering sleep...'
+try:
+ time.sleep(10)
+except:
+ print 'sleep was interrupted by signal.'
+
+# Just for fun let's see if the process is alive.
+try:
+ os.kill(pid, 0)
+ print 'Child is alive. This is ambiguous because it may be a Zombie.'
+except OSError as e:
+ print 'Child appears to be dead.'
+
+print 'PART 2 -- Test signal handling with full pipe.'
+# Create a child process for us to kill.
+try:
+ pid, fd = pty.fork()
+except Exception as e:
+ print str(e)
+
+if pid == 0:
+ os.write (sys.stdout.fileno(), 'This is a test.\n This is a test.')
+ time.sleep(10000)
+
+print 'Sending SIGKILL to child pid:', pid
+os.kill (pid, signal.SIGKILL)
+
+# SIGCHLD should interrupt sleep.
+# Note that this is a race.
+# It is possible that the signal handler will get called
+# before we try to sleep, but this has not happened yet.
+# But in that case we can only tell by order of printed output.
+print 'Entering sleep...'
+try:
+ time.sleep(10)
+except:
+ print 'sleep was interrupted by signal.'
+
+# Just for fun let's see if the process is alive.
+try:
+ os.kill(pid, 0)
+ print 'Child is alive. This is ambiguous because it may be a Zombie.'
+except OSError as e:
+ print 'Child appears to be dead.'
+
Index: third_party/Python/module/pexpect-4.6/tests/platform_checks/check2.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/platform_checks/check2.py
+++ third_party/Python/module/pexpect-4.6/tests/platform_checks/check2.py
@@ -0,0 +1,44 @@
+#!/usr/bin/env python
+import signal
+import os
+import time
+
+def signal_handler (signum, frame):
+ print 'Signal handler called with signal:', signum
+ print 'signal.SIGCHLD=', signal.SIGKILL
+
+# Create a child process for us to kill.
+pid = os.fork()
+if pid == 0:
+ time.sleep(10000)
+
+#signal.signal (signal.SIGCHLD, signal.SIG_IGN)
+signal.signal (signal.SIGCHLD, signal_handler)
+
+print 'Sending SIGKILL to child pid:', pid
+os.kill (pid, signal.SIGKILL)
+
+# SIGCHLD should interrupt sleep.
+# Note that this is a race.
+# It is possible that the signal handler will get called
+# before we try to sleep, but this has not happened yet.
+# But in that case we can only tell by order of printed output.
+interrupted = 0
+try:
+ time.sleep(10)
+except:
+ print 'sleep was interrupted by signal.'
+ interrupted = 1
+
+if not interrupted:
+ print 'ERROR. Signal did not interrupt sleep.'
+else:
+ print 'Signal interrupted sleep. This is good.'
+
+# Let's see if the process is alive.
+try:
+ os.kill(pid, 0)
+ print 'Child is alive. This is ambiguous because it may be a Zombie.'
+except OSError as e:
+ print 'Child appears to be dead.'
+
Index: third_party/Python/module/pexpect-4.6/tests/platform_checks/check_control_terminal.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/platform_checks/check_control_terminal.py
+++ third_party/Python/module/pexpect-4.6/tests/platform_checks/check_control_terminal.py
@@ -0,0 +1,19 @@
+#!/usr/bin/env python
+
+import termios, fcntl, struct, os, sys
+
+def getwinsize():
+ s = struct.pack("HHHH", 0, 0, 0, 0)
+ x = fcntl.ioctl(sys.stdout.fileno(), termios.TIOCGWINSZ, s)
+ rows, cols = struct.unpack("HHHH", x)[:2]
+ return rows, cols
+
+def setwinsize(r,c):
+ # Assume ws_xpixel and ws_ypixel are zero.
+ s = struct.pack("HHHH", r,c,0,0)
+ x = fcntl.ioctl(sys.stdout.fileno(), termios.TIOCSWINSZ, s)
+print 'stdin tty:', os.ttyname(0)
+print 'stdout tty:', os.ttyname(1)
+print 'controlling terminal:', os.ctermid()
+print 'winsize %d,%d' % getwinsize()
+print 'ENDTEST'
Index: third_party/Python/module/pexpect-4.6/tests/platform_checks/check_handler.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/platform_checks/check_handler.py
+++ third_party/Python/module/pexpect-4.6/tests/platform_checks/check_handler.py
@@ -0,0 +1,60 @@
+#!/usr/bin/env python
+import signal
+import os
+import time
+import pty
+import sys
+import fcntl
+import tty
+GLOBAL_SIGCHLD_RECEIVED = 0
+
+def nonblock (fd):
+ # if O_NDELAY is set read() returns 0 (ambiguous with EOF).
+ # if O_NONBLOCK is set read() returns -1 and sets errno to EAGAIN
+ original_flags = fcntl.fcntl (fd, fcntl.F_GETFL, 0)
+ flags = original_flags | os.O_NONBLOCK
+ fcntl.fcntl(fd, fcntl.F_SETFL, flags)
+ return original_flags
+
+def signal_handler (signum, frame):
+ print ''
+ global GLOBAL_SIGCHLD_RECEIVED
+ status = os.waitpid (-1, os.WNOHANG)
+ if status[0] == 0:
+ print 'No process for waitpid:', status
+ else:
+ print 'Status:', status
+ print 'WIFEXITED(status):', os.WIFEXITED(status[1])
+ print 'WEXITSTATUS(status):', os.WEXITSTATUS(status[1])
+ GLOBAL_SIGCHLD_RECEIVED = 1
+
+def main ():
+ signal.signal (signal.SIGCHLD, signal_handler)
+ pid, fd = pty.fork()
+ if pid == 0:
+ os.write (sys.stdout.fileno(), 'This is a test.\nThis is a test.')
+ time.sleep(10000)
+ nonblock (fd)
+ tty.setraw(fd) #STDIN_FILENO)
+ print 'Sending SIGKILL to child pid:', pid
+ time.sleep(2)
+ os.kill (pid, signal.SIGKILL)
+
+ print 'Entering to sleep...'
+ try:
+ time.sleep(2)
+ except:
+ print 'Sleep interrupted'
+ try:
+ os.kill(pid, 0)
+ print '\tChild is alive. This is ambiguous because it may be a Zombie.'
+ except OSError as e:
+ print '\tChild appears to be dead.'
+# print str(e)
+ print
+ print 'Reading from master fd:', os.read (fd, 1000)
+
+
+
+if __name__ == '__main__':
+ main ()
Index: third_party/Python/module/pexpect-4.6/tests/platform_checks/check_read.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/platform_checks/check_read.py
+++ third_party/Python/module/pexpect-4.6/tests/platform_checks/check_read.py
@@ -0,0 +1,35 @@
+import os
+
+filename = os.tmpnam()
+print 'filename:', filename
+
+fd_out = os.open(filename, os.O_CREAT | os.O_WRONLY)
+print 'fd_out:', fd_out
+os.write (fd_out, 'This is a test.\n')
+os.close(fd_out)
+print
+print 'testing read on good fd...'
+fd_in = os.open (filename, os.O_RDONLY)
+print 'fd_in:', fd_in
+while 1:
+ data_in = os.read(fd_in, 1)
+ print 'data_in:', data_in
+ if data_in == '':
+ print 'data_in was empty'
+ break #sys.exit(1)
+os.close(fd_in)
+print
+print
+print 'testing read on closed fd...'
+fd_in = os.open ('test_read.py', os.O_RDONLY)
+print 'fd_in:', fd_in
+while 1:
+ data_in = os.read(fd_in, 1)
+ print 'data_in:', data_in
+ if data_in == '':
+ print 'data_in was empty'
+ break
+os.close(fd_in)
+d = os.read(fd_in, 1) # fd_in should be closed now...
+if s == '':
+ print 'd is empty. good.'
Index: third_party/Python/module/pexpect-4.6/tests/platform_checks/check_signals.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/platform_checks/check_signals.py
+++ third_party/Python/module/pexpect-4.6/tests/platform_checks/check_signals.py
@@ -0,0 +1,67 @@
+#!/usr/bin/env python
+import signal
+import os
+import time
+import pty
+import sys
+GLOBAL_SIGCHLD_RECEIVED = 0
+
+def signal_handler (signum, frame):
+ print ''
+ global GLOBAL_SIGCHLD_RECEIVED
+ status = os.waitpid (-1, os.WNOHANG)
+ print 'WIFEXITED(status):', os.WIFEXITED(status)
+ print 'WEXITSTATUS(status):', os.WEXITSTATUS(status)
+ GLOBAL_SIGCHLD_RECEIVED = 1
+
+def main ():
+# sig_test ('SIG_IGN', 'ptyfork', 'yes')
+ sig_test ('handler', 'ptyfork', 'yes')
+# sig_test ('SIG_IGN', 'ptyfork', 'no')
+# sig_test ('handler', 'ptyfork', 'no')
+# sig_test ('SIG_IGN', 'osfork', 'yes')
+# sig_test ('handler', 'osfork', 'yes')
+# sig_test ('SIG_IGN', 'osfork', 'no')
+# sig_test ('handler', 'osfork', 'no')
+
+def sig_test (sig_handler_type, fork_type, child_output):
+ print 'Testing with:'
+ print '\tsig_handler_type:', sig_handler_type
+ print '\tfork_type:', fork_type
+ print '\tchild_output:', child_output
+
+ if sig_handler_type == 'SIG_IGN':
+ signal.signal (signal.SIGCHLD, signal.SIG_IGN)
+ else:
+ signal.signal (signal.SIGCHLD, signal_handler)
+ pid = -1
+ fd = -1
+ if fork_type == 'ptyfork':
+ pid, fd = pty.fork()
+ else:
+ pid = os.fork()
+
+ if pid == 0:
+ if child_output == 'yes':
+ os.write (sys.stdout.fileno(), 'This is a test.\nThis is a test.')
+ time.sleep(10000)
+
+ #print 'Sending SIGKILL to child pid:', pid
+ time.sleep(2)
+ os.kill (pid, signal.SIGKILL)
+
+ #print 'Entering to sleep...'
+ try:
+ time.sleep(2)
+ except:
+ pass
+ try:
+ os.kill(pid, 0)
+ print '\tChild is alive. This is ambiguous because it may be a Zombie.'
+ except OSError as e:
+ print '\tChild appears to be dead.'
+# print str(e)
+ print
+
+if __name__ == '__main__':
+ main ()
Index: third_party/Python/module/pexpect-4.6/tests/qa.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/qa.py
+++ third_party/Python/module/pexpect-4.6/tests/qa.py
@@ -0,0 +1,26 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import commands
+import signal
+
+signal.signal(signal.SIGCHLD, signal.SIG_IGN)
+print(commands.getoutput('/bin/ls -l'))
+
Index: third_party/Python/module/pexpect-4.6/tests/sigwinch_report.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/sigwinch_report.py
+++ third_party/Python/module/pexpect-4.6/tests/sigwinch_report.py
@@ -0,0 +1,50 @@
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+from __future__ import print_function
+
+import signal, time, struct, fcntl, termios, sys
+
+def getwinsize():
+ '''This returns the window size of the child tty.
+ The return value is a tuple of (rows, cols).
+ '''
+ if 'TIOCGWINSZ' in dir(termios):
+ TIOCGWINSZ = termios.TIOCGWINSZ
+ else:
+ TIOCGWINSZ = 1074295912 # Assume
+ s = struct.pack('HHHH', 0, 0, 0, 0)
+ x = fcntl.ioctl(sys.stdout.fileno(), TIOCGWINSZ, s)
+ return struct.unpack('HHHH', x)[0:2]
+
+def handler(signum, frame):
+ print('signal')
+ sys.stdout.flush()
+ print('SIGWINCH:', getwinsize ())
+ sys.stdout.flush()
+
+print("Initial Size:", getwinsize())
+print("setting handler for SIGWINCH")
+signal.signal(signal.SIGWINCH, handler)
+print("READY")
+
+while 1:
+ sys.stdout.flush()
+ time.sleep(1)
+
Index: third_party/Python/module/pexpect-4.6/tests/sleep_for.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/sleep_for.py
+++ third_party/Python/module/pexpect-4.6/tests/sleep_for.py
@@ -0,0 +1,41 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+from __future__ import print_function
+
+import time
+import sys
+
+def main():
+ """
+ This script sleeps for the number of seconds (float) specified by the
+ command line argument.
+ """
+ if len(sys.argv) < 2:
+ print("Usage: %s seconds_to_sleep" % (sys.argv[0],))
+ sys.exit(1)
+ timeout = float(sys.argv[1])
+ print("READY")
+ time.sleep(timeout)
+ print("END")
+
+if __name__ == '__main__':
+ main()
Index: third_party/Python/module/pexpect-4.6/tests/swapcase_echo.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/swapcase_echo.py
+++ third_party/Python/module/pexpect-4.6/tests/swapcase_echo.py
@@ -0,0 +1,26 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import sys, time
+while True:
+ x = raw_input ()
+ time.sleep(1) # without this delay the test would fail about 75% of the time. Why?
+ print(x.swapcase())
+ sys.stdout.flush()
Index: third_party/Python/module/pexpect-4.6/tests/test_FSM.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/test_FSM.py
+++ third_party/Python/module/pexpect-4.6/tests/test_FSM.py
@@ -0,0 +1,34 @@
+import io
+import sys
+import unittest
+try:
+ import builtins
+except ImportError:
+ import __builtin__ as builtins
+
+PY3 = (sys.version_info[0] >= 3)
+input_name = 'input' if PY3 else 'raw_input'
+
+from pexpect import FSM
+
+class FSMTestCase(unittest.TestCase):
+ def test_run_fsm(self):
+ def _input(prompt):
+ return "167 3 2 2 * * * 1 - ="
+ orig_input = getattr(builtins, input_name)
+ orig_stdout = sys.stdout
+ setattr(builtins, input_name, _input)
+ sys.stdout = sio = (io.StringIO if PY3 else io.BytesIO)()
+
+ try:
+ FSM.main()
+ finally:
+ setattr(builtins, input_name, orig_input)
+ sys.stdout = orig_stdout
+
+ printed = sio.getvalue()
+ assert '2003' in printed, printed
+
+
+if __name__ == '__main__':
+ unittest.main()
\ No newline at end of file
Index: third_party/Python/module/pexpect-4.6/tests/test_ansi.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/test_ansi.py
+++ third_party/Python/module/pexpect-4.6/tests/test_ansi.py
@@ -0,0 +1,228 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+from pexpect import ANSI
+import unittest
+from . import PexpectTestCase
+import sys
+
+PY3 = (sys.version_info[0] >= 3)
+
+write_target = 'I\'ve got a ferret sticking up my nose. \n' +\
+'(He\'s got a ferret sticking up his nose.) \n' +\
+'How it got there I can\'t tell \n' +\
+'But now it\'s there it hurts like hell \n' +\
+'And what is more it radically affects my sense of smell. \n' +\
+'(His sense of smell.) '
+
+write_text = 'I\'ve got a ferret sticking up my nose.\n' + \
+'(He\'s got a ferret sticking up his nose.)\n' + \
+'How it got there I can\'t tell\n' + \
+'But now it\'s there it hurts like hell\n' + \
+'And what is more it radically affects my sense of smell.\n' + \
+'(His sense of smell.)\n' + \
+'I can see a bare-bottomed mandril.\n' + \
+'(Slyly eyeing his other nostril.)\n' + \
+'If it jumps inside there too I really don\'t know what to do\n' + \
+'I\'ll be the proud posessor of a kind of nasal zoo.\n' + \
+'(A nasal zoo.)\n' + \
+'I\'ve got a ferret sticking up my nose.\n' + \
+'(And what is worst of all it constantly explodes.)\n' + \
+'"Ferrets don\'t explode," you say\n' + \
+'But it happened nine times yesterday\n' + \
+'And I should know for each time I was standing in the way.\n' + \
+'I\'ve got a ferret sticking up my nose.\n' + \
+'(He\'s got a ferret sticking up his nose.)\n' + \
+'How it got there I can\'t tell\n' + \
+'But now it\'s there it hurts like hell\n' + \
+'And what is more it radically affects my sense of smell.\n' + \
+'(His sense of smell.)'
+
+tetris_target=' XX XXXX XX \n' +\
+' XXXXXX XXXXXXXX XX \n' +\
+' XXXXXX XXXXXXXX XX \n' +\
+' XX XX XX XXXX XX \n' +\
+' XXXXXX XXXX XXXX XX \n' +\
+' XXXXXXXXXX XXXX XX \n' +\
+' XX XXXXXX XX XX \n' +\
+' XXXXXX XX XX \n' +\
+' XXXX XXXXXX XX XX \n' +\
+' XXXXXX XXXX XX XX \n' +\
+' XX XX XXXX XX XX \n' +\
+' XX XX XX XX XX \n' +\
+' XX XX XXXX XXXX XX \n' +\
+' XXXXXXXX XXXX XXXX XX \n' +\
+' XXXXXXXXXXXXXX XXXXXXXX \n' +\
+' XX XXXXXXXX XX XX \n' +\
+' XXXXXXXXXXXXXX XX XX \n' +\
+' XX XXXX XXXXXX XX \n' +\
+' XXXXXX XXXXXXXX \n' +\
+' XXXXXXXXXX XX XX \n' +\
+' XXXXXXXXXXXXXXXXXXXXXXXX \n' +\
+' \n' +\
+' J->LEFT K->ROTATE L->RIGHT SPACE->DROP P->PAUSE Q->QUIT \n' +\
+' '
+
+torture_target='+--------------------------------------------------------------------------------+\n' +\
+'|a`opqrs` This is the `srqpo`a |\n' +\
+'|VT100 series Torture Test Demonstration. |\n' +\
+'|VT100 series Torture Test Demonstration. |\n' +\
+'|This is a normal line __________________________________________________y_ |\n' +\
+'|This is a bold line (normal unless the Advanced Video Option is installed) |\n' +\
+'|This line is underlined _ " " " " " " _y_ |\n' +\
+'|This is a blinking line _ " " " " " " _y_ |\n' +\
+'|This is inverse video _ (underlined if no AVO and cursor is underline) _y_ |\n' +\
+'|Normal gjpqy Underline Blink Underline+Blink gjpqy |\n' +\
+'|Bold gjpqy Underline Blink Underline+Blink gjpqy |\n' +\
+'|Inverse Underline Blink Underline+Blink |\n' +\
+'|Bold+Inverse Underline Blink Underline+Blink |\n' +\
+'|This is double width |\n' +\
+'|This is double height |\n' +\
+'|This is double height |\n' +\
+'|_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ioy |\n' +\
+'|_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ioy |\n' +\
+'|_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ioy |\n' +\
+'|`abcdefghijklmnopqrstuvwxyz{|}~ lqwqk |\n' +\
+'|`abcdefghijklmnopqrstuvwxyz{|}~ tqnqu |\n' +\
+'|`abcdefghijklmnopqrstuvwxyz{|}~ tqnqu |\n' +\
+'|`abcdefghijklmnopqrstuvwxyz{|}~ mqvqj |\n' +\
+'| This test created by Joe Smith, 8-May-85 |\n' +\
+'| |\n' +\
+'+--------------------------------------------------------------------------------+\n'
+
+class ansiTestCase (PexpectTestCase.PexpectTestCase):
+ def test_write (self):
+ s = ANSI.ANSI (6,65)
+ s.fill('.')
+ s.cursor_home()
+ for c in write_text:
+ s.write (c)
+ assert str(s) == write_target
+
+ def test_torturet (self):
+ s = ANSI.ANSI (24,80)
+ with open('torturet.vt') as f:
+ sample_text = f.read()
+ for c in sample_text:
+ s.process (c)
+ assert s.pretty() == torture_target, 'processed: \n' + s.pretty() + '\nexpected:\n' + torture_target
+
+ def test_tetris (self):
+ s = ANSI.ANSI (24,80)
+ with open('tetris.data') as f:
+ tetris_text = f.read()
+ for c in tetris_text:
+ s.process (c)
+ assert str(s) == tetris_target
+
+ def test_lines(self):
+ s = ANSI.ANSI(5, 5)
+ s.write('a'*6 + '\n')
+ s.write('ab\bcd\n')
+ s.write('ab\rcd\n')
+ assert str(s) == ('aaaaa\n'
+ 'a \n'
+ 'acd \n'
+ 'cd \n'
+ ' ')
+
+ def test_number_x(self):
+ """Test the FSM state used to handle more than 2 numeric parameters."""
+ class TestANSI(ANSI.ANSI):
+ captured_memory = None
+ def do_sgr(self, fsm):
+ assert self.captured_memory is None
+ self.captured_memory = fsm.memory
+
+ s = TestANSI(1, 20)
+ s.write('\x1b[0;1;32;45mtest')
+ assert str(s) == ('test ')
+ assert s.captured_memory is not None
+ assert s.captured_memory == [s, '0', '1', '32', '45']
+
+ def test_fsm_memory(self):
+ """Test the FSM stack/memory does not have numbers left on it
+ after some sequences with numbers are passed in."""
+ s = ANSI.ANSI(1, 20)
+ s.write('\x1b[0;1;2;3m\x1b[4;5;6;7q\x1b[?8h\x1b[?9ltest')
+ assert str(s) == ('test ')
+ assert s.state.memory == [s]
+
+ def test_utf8_bytes(self):
+ """Test that when bytes are passed in containing UTF-8 encoded
+ characters, where the encoding of each character consists of
+ multiple bytes, the characters are correctly decoded.
+ Incremental decoding is also tested."""
+ s = ANSI.ANSI(2, 10, encoding='utf-8')
+ # This is the UTF-8 encoding of the UCS character "HOURGLASS"
+ # followed by the UTF-8 encoding of the UCS character
+ # "KEYBOARD". These characters can't be encoded in cp437 or
+ # latin-1. The "KEYBOARD" character is split into two
+ # separate writes.
+ s.write(b'\xe2\x8c\x9b')
+ s.write(b'\xe2\x8c')
+ s.write(b'\xa8')
+ if PY3:
+ assert str(s) == u'\u231b\u2328 \n '
+ else:
+ assert unicode(s) == u'\u231b\u2328 \n '
+ assert str(s) == b'\xe2\x8c\x9b\xe2\x8c\xa8 \n '
+ assert s.dump() == u'\u231b\u2328 '
+ assert s.pretty() == u'+----------+\n|\u231b\u2328 |\n| |\n+----------+\n'
+ assert s.get_abs(1, 1) == u'\u231b'
+ assert s.get_region(1, 1, 1, 5) == [u'\u231b\u2328 ']
+
+ def test_unicode(self):
+ """Test passing in of a unicode string."""
+ s = ANSI.ANSI(2, 10, encoding="utf-8")
+ s.write(u'\u231b\u2328')
+ if PY3:
+ assert str(s) == u'\u231b\u2328 \n '
+ else:
+ assert unicode(s) == u'\u231b\u2328 \n '
+ assert str(s) == b'\xe2\x8c\x9b\xe2\x8c\xa8 \n '
+ assert s.dump() == u'\u231b\u2328 '
+ assert s.pretty() == u'+----------+\n|\u231b\u2328 |\n| |\n+----------+\n'
+ assert s.get_abs(1, 1) == u'\u231b'
+ assert s.get_region(1, 1, 1, 5) == [u'\u231b\u2328 ']
+
+ def test_decode_error(self):
+ """Test that default handling of decode errors replaces the
+ invalid characters."""
+ s = ANSI.ANSI(2, 10, encoding="ascii")
+ s.write(b'\xff') # a non-ASCII character
+ # In unicode, the non-ASCII character is replaced with
+ # REPLACEMENT CHARACTER.
+ if PY3:
+ assert str(s) == u'\ufffd \n '
+ else:
+ assert unicode(s) == u'\ufffd \n '
+ assert str(s) == b'? \n '
+ assert s.dump() == u'\ufffd '
+ assert s.pretty() == u'+----------+\n|\ufffd |\n| |\n+----------+\n'
+ assert s.get_abs(1, 1) == u'\ufffd'
+ assert s.get_region(1, 1, 1, 5) == [u'\ufffd ']
+
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(ansiTestCase,'test')
+
Index: third_party/Python/module/pexpect-4.6/tests/test_async.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/test_async.py
+++ third_party/Python/module/pexpect-4.6/tests/test_async.py
@@ -0,0 +1,70 @@
+try:
+ import asyncio
+except ImportError:
+ asyncio = None
+
+import gc
+import sys
+import unittest
+
+import pexpect
+from .PexpectTestCase import PexpectTestCase
+
+def run(coro):
+ return asyncio.get_event_loop().run_until_complete(coro)
+
+@unittest.skipIf(asyncio is None, "Requires asyncio")
+class AsyncTests(PexpectTestCase):
+ def test_simple_expect(self):
+ p = pexpect.spawn('cat')
+ p.sendline('Hello asyncio')
+ coro = p.expect(['Hello', pexpect.EOF] , async_=True)
+ assert run(coro) == 0
+ print('Done')
+
+ def test_timeout(self):
+ p = pexpect.spawn('cat')
+ coro = p.expect('foo', timeout=1, async_=True)
+ with self.assertRaises(pexpect.TIMEOUT):
+ run(coro)
+
+ p = pexpect.spawn('cat')
+ coro = p.expect(['foo', pexpect.TIMEOUT], timeout=1, async_=True)
+ assert run(coro) == 1
+
+ def test_eof(self):
+ p = pexpect.spawn('cat')
+ p.sendline('Hi')
+ coro = p.expect(pexpect.EOF, async_=True)
+ p.sendeof()
+ assert run(coro) == 0
+
+ p = pexpect.spawn('cat')
+ p.sendeof()
+ coro = p.expect('Blah', async_=True)
+ with self.assertRaises(pexpect.EOF):
+ run(coro)
+
+ def test_expect_exact(self):
+ p = pexpect.spawn('%s list100.py' % sys.executable)
+ assert run(p.expect_exact(b'5', async_=True)) == 0
+ assert run(p.expect_exact(['wpeok', b'11'], async_=True)) == 1
+ assert run(p.expect_exact([b'foo', pexpect.EOF], async_=True)) == 1
+
+ def test_async_utf8(self):
+ p = pexpect.spawn('%s list100.py' % sys.executable, encoding='utf8')
+ assert run(p.expect_exact(u'5', async_=True)) == 0
+ assert run(p.expect_exact([u'wpeok', u'11'], async_=True)) == 1
+ assert run(p.expect_exact([u'foo', pexpect.EOF], async_=True)) == 1
+
+ def test_async_and_gc(self):
+ p = pexpect.spawn('%s sleep_for.py 1' % sys.executable, encoding='utf8')
+ assert run(p.expect_exact(u'READY', async_=True)) == 0
+ gc.collect()
+ assert run(p.expect_exact(u'END', async_=True)) == 0
+
+ def test_async_and_sync(self):
+ p = pexpect.spawn('echo 1234', encoding='utf8', maxread=1)
+ assert run(p.expect_exact(u'1', async_=True)) == 0
+ assert p.expect_exact(u'2') == 0
+ assert run(p.expect_exact(u'3', async_=True)) == 0
Index: third_party/Python/module/pexpect-4.6/tests/test_command_list_split.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/test_command_list_split.py
+++ third_party/Python/module/pexpect-4.6/tests/test_command_list_split.py
@@ -0,0 +1,40 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+import unittest
+from . import PexpectTestCase
+
+class SplitCommandLineTestCase(PexpectTestCase.PexpectTestCase):
+ def testSplitSizes(self):
+ assert len(pexpect.split_command_line(r'')) == 0
+ assert len(pexpect.split_command_line(r'one')) == 1
+ assert len(pexpect.split_command_line(r'one two')) == 2
+ assert len(pexpect.split_command_line(r'one two')) == 2
+ assert len(pexpect.split_command_line(r'one two')) == 2
+ assert len(pexpect.split_command_line(r'one\ one')) == 1
+ assert len(pexpect.split_command_line('\'one one\'')) == 1
+ assert len(pexpect.split_command_line(r'one\"one')) == 1
+ assert len(pexpect.split_command_line(r'This\' is a\'\ test')) == 3
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(SplitCommandLineTestCase,'test')
Index: third_party/Python/module/pexpect-4.6/tests/test_constructor.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/test_constructor.py
+++ third_party/Python/module/pexpect-4.6/tests/test_constructor.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+import unittest
+from . import PexpectTestCase
+
+class TestCaseConstructor(PexpectTestCase.PexpectTestCase):
+ def test_constructor (self):
+ '''This tests that the constructor will work and give
+ the same results for different styles of invoking __init__().
+ This assumes that the root directory / is static during the test.
+ '''
+ p1 = pexpect.spawn('uname -m -n -p -r -s -v')
+ p2 = pexpect.spawn('uname', ['-m', '-n', '-p', '-r', '-s', '-v'])
+ p1.expect(pexpect.EOF)
+ p2.expect(pexpect.EOF)
+ assert p1.before == p2.before
+
+ def test_named_parameters (self):
+ '''This tests that named parameters work.
+ '''
+ p = pexpect.spawn ('/bin/ls',timeout=10)
+ p = pexpect.spawn (timeout=10, command='/bin/ls')
+ p = pexpect.spawn (args=[], command='/bin/ls')
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(TestCaseConstructor,'test')
+
Index: third_party/Python/module/pexpect-4.6/tests/test_ctrl_chars.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/test_ctrl_chars.py
+++ third_party/Python/module/pexpect-4.6/tests/test_ctrl_chars.py
@@ -0,0 +1,125 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+from __future__ import print_function
+
+import pexpect
+import unittest
+from . import PexpectTestCase
+import time
+import sys
+
+from ptyprocess import ptyprocess
+ptyprocess._make_eof_intr()
+
+if sys.version_info[0] >= 3:
+ def byte(i):
+ return bytes([i])
+else:
+ byte = chr
+
+class TestCtrlChars(PexpectTestCase.PexpectTestCase):
+
+ def test_control_chars(self):
+ '''This tests that we can send all 256 8-bit characters to a child
+ process.'''
+ child = pexpect.spawn('python getch.py', echo=False, timeout=5)
+ child.expect('READY')
+ for i in range(1, 256):
+ child.send(byte(i))
+ child.expect ('%d' % (i,))
+
+ # This needs to be last, as getch.py exits on \x00
+ child.send(byte(0))
+ child.expect('0')
+ child.expect(pexpect.EOF)
+ assert not child.isalive()
+ assert child.exitstatus == 0
+
+ def test_sendintr (self):
+ child = pexpect.spawn('python getch.py', echo=False, timeout=5)
+ child.expect('READY')
+ child.sendintr()
+ child.expect(str(ord(ptyprocess._INTR)) + '')
+
+ child.send(byte(0))
+ child.expect('0')
+ child.expect(pexpect.EOF)
+ assert not child.isalive()
+ assert child.exitstatus == 0
+
+ def test_sendeof(self):
+ child = pexpect.spawn('python getch.py', echo=False, timeout=5)
+ child.expect('READY')
+ child.sendeof()
+ child.expect(str(ord(ptyprocess._EOF)) + '')
+
+ child.send(byte(0))
+ child.expect('0')
+ child.expect(pexpect.EOF)
+ assert not child.isalive()
+ assert child.exitstatus == 0
+
+ def test_bad_sendcontrol_chars (self):
+ '''This tests that sendcontrol will return 0 for an unknown char. '''
+
+ child = pexpect.spawn('python getch.py', echo=False, timeout=5)
+ child.expect('READY')
+ assert 0 == child.sendcontrol('1')
+
+ def test_sendcontrol(self):
+ '''This tests that we can send all special control codes by name.
+ '''
+ child = pexpect.spawn('python getch.py', echo=False, timeout=5)
+ child.expect('READY')
+ for ctrl in 'abcdefghijklmnopqrstuvwxyz':
+ assert child.sendcontrol(ctrl) == 1
+ val = ord(ctrl) - ord('a') + 1
+ child.expect_exact(str(val)+'')
+
+ # escape character
+ assert child.sendcontrol('[') == 1
+ child.expect('27')
+ assert child.sendcontrol('\\') == 1
+ child.expect('28')
+ # telnet escape character
+ assert child.sendcontrol(']') == 1
+ child.expect('29')
+ assert child.sendcontrol('^') == 1
+ child.expect('30')
+ # irc protocol uses this to underline ...
+ assert child.sendcontrol('_') == 1
+ child.expect('31')
+ # the real "backspace is delete"
+ assert child.sendcontrol('?') == 1
+ child.expect('127')
+
+ # NUL, same as ctrl + ' '
+ assert child.sendcontrol('@') == 1
+ child.expect('0')
+ child.expect(pexpect.EOF)
+ assert not child.isalive()
+ assert child.exitstatus == 0
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(TestCtrlChars,'test')
+
Index: third_party/Python/module/pexpect-4.6/tests/test_delay.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/test_delay.py
+++ third_party/Python/module/pexpect-4.6/tests/test_delay.py
@@ -0,0 +1,45 @@
+# -*- coding: utf-8 -*-
+
+from . import PexpectTestCase
+import pexpect
+
+
+class TestCaseDelay(PexpectTestCase.PexpectTestCase):
+ """
+ Tests for various delay attributes.
+ """
+ def test_delaybeforesend(self):
+ """
+ Test various values for delaybeforesend.
+ """
+ p = pexpect.spawn("cat")
+
+ p.delaybeforesend = 1
+ p.sendline("line 1")
+ p.expect("line 1")
+
+ p.delaybeforesend = 0.0
+ p.sendline("line 2")
+ p.expect("line 2")
+
+ p.delaybeforesend = None
+ p.sendline("line 3")
+ p.expect("line 3")
+
+ def test_delayafterread(self):
+ """
+ Test various values for delayafterread.
+ """
+ p = pexpect.spawn("cat")
+
+ p.delayafterread = 1
+ p.sendline("line 1")
+ p.expect("line 1")
+
+ p.delayafterread = 0.0
+ p.sendline("line 2")
+ p.expect("line 2")
+
+ p.delayafterread = None
+ p.sendline("line 3")
+ p.expect("line 3")
Index: third_party/Python/module/pexpect-4.6/tests/test_destructor.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/test_destructor.py
+++ third_party/Python/module/pexpect-4.6/tests/test_destructor.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+import unittest
+from . import PexpectTestCase
+import gc
+import platform
+import time
+
+class TestCaseDestructor(PexpectTestCase.PexpectTestCase):
+ def test_destructor (self):
+ if platform.python_implementation() != 'CPython':
+ # Details of garbage collection are different on other implementations
+ return 'SKIP'
+ gc.collect()
+ time.sleep(3)
+ p1 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN)
+ p2 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN)
+ p3 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN)
+ p4 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN)
+ fd_t1 = (p1.child_fd,p2.child_fd,p3.child_fd,p4.child_fd)
+ p1.expect(pexpect.EOF)
+ p2.expect(pexpect.EOF)
+ p3.expect(pexpect.EOF)
+ p4.expect(pexpect.EOF)
+ p1.kill(9)
+ p2.kill(9)
+ p3.kill(9)
+ p4.kill(9)
+ p1 = None
+ p2 = None
+ p3 = None
+ p4 = None
+ gc.collect()
+ time.sleep(3) # Some platforms are slow at gc... Solaris!
+
+ p1 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN)
+ p2 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN)
+ p3 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN)
+ p4 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN)
+ fd_t2 = (p1.child_fd,p2.child_fd,p3.child_fd,p4.child_fd)
+ p1.kill(9)
+ p2.kill(9)
+ p3.kill(9)
+ p4.kill(9)
+ del (p1)
+ del (p2)
+ del (p3)
+ del (p4)
+ gc.collect()
+ time.sleep(3)
+
+ p1 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN)
+ p2 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN)
+ p3 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN)
+ p4 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN)
+ fd_t3 = (p1.child_fd,p2.child_fd,p3.child_fd,p4.child_fd)
+
+ assert (fd_t1 == fd_t2 == fd_t3), "pty file descriptors not properly garbage collected (fd_t1,fd_t2,fd_t3)=(%s,%s,%s)" % (str(fd_t1),str(fd_t2),str(fd_t3))
+
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(TestCaseDestructor,'test')
+
Index: third_party/Python/module/pexpect-4.6/tests/test_dotall.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/test_dotall.py
+++ third_party/Python/module/pexpect-4.6/tests/test_dotall.py
@@ -0,0 +1,43 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+import unittest
+import re
+from . import PexpectTestCase
+
+testdata = 'BEGIN\nHello world\nEND'
+class TestCaseDotall(PexpectTestCase.PexpectTestCase):
+ def test_dotall (self):
+ p = pexpect.spawn('echo "%s"' % testdata)
+ i = p.expect ([b'BEGIN(.*)END', pexpect.EOF])
+ assert i==0, 'DOTALL does not seem to be working.'
+
+ def test_precompiled (self):
+ p = pexpect.spawn('echo "%s"' % testdata)
+ pat = re.compile(b'BEGIN(.*)END') # This overrides the default DOTALL.
+ i = p.expect ([pat, pexpect.EOF])
+ assert i==1, 'Precompiled pattern to override DOTALL does not seem to be working.'
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(TestCaseDotall,'test')
+
Index: third_party/Python/module/pexpect-4.6/tests/test_env.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/test_env.py
+++ third_party/Python/module/pexpect-4.6/tests/test_env.py
@@ -0,0 +1,93 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2016, Martin Packman
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import contextlib
+import os
+import tempfile
+import unittest
+
+import pexpect
+from . import PexpectTestCase
+
+
+@contextlib.contextmanager
+def example_script(name, output='success'):
+ " helper to create a temporary shell script that tests can run "
+ tempdir = tempfile.mkdtemp(prefix='tmp-pexpect-test')
+ try:
+ script_path = os.path.join(tempdir, name)
+ with open(script_path, 'w') as f:
+ f.write('#!/bin/sh\necho "%s"' % (output,))
+ try:
+ os.chmod(script_path, 0o755)
+ yield tempdir
+ finally:
+ os.remove(script_path)
+ finally:
+ os.rmdir(tempdir)
+
+
+class TestCaseEnv(PexpectTestCase.PexpectTestCase):
+ " tests for the env argument to pexpect.spawn and pexpect.run "
+
+ def test_run_uses_env(self):
+ " pexpect.run uses env argument when running child process "
+ script_name = 'run_uses_env.sh'
+ environ = {'PEXPECT_TEST_KEY': 'pexpect test value'}
+ with example_script(script_name, '$PEXPECT_TEST_KEY') as script_dir:
+ script = os.path.join(script_dir, script_name)
+ out = pexpect.run(script, env=environ)
+ self.assertEqual(out.rstrip(), b'pexpect test value')
+
+ def test_spawn_uses_env(self):
+ " pexpect.spawn uses env argument when running child process "
+ script_name = 'spawn_uses_env.sh'
+ environ = {'PEXPECT_TEST_KEY': 'pexpect test value'}
+ with example_script(script_name, '$PEXPECT_TEST_KEY') as script_dir:
+ script = os.path.join(script_dir, script_name)
+ child = pexpect.spawn(script, env=environ)
+ out = child.readline()
+ child.expect(pexpect.EOF)
+ self.assertEqual(child.exitstatus, 0)
+ self.assertEqual(out.rstrip(), b'pexpect test value')
+
+ def test_run_uses_env_path(self):
+ " pexpect.run uses binary from PATH when given in env argument "
+ script_name = 'run_uses_env_path.sh'
+ with example_script(script_name) as script_dir:
+ out = pexpect.run(script_name, env={'PATH': script_dir})
+ self.assertEqual(out.rstrip(), b'success')
+
+ def test_run_uses_env_path_over_path(self):
+ " pexpect.run uses PATH from env over os.environ "
+ script_name = 'run_uses_env_path_over_path.sh'
+ with example_script(script_name, output='failure') as wrong_dir:
+ with example_script(script_name) as right_dir:
+ orig_path = os.environ['PATH']
+ os.environ['PATH'] = wrong_dir
+ try:
+ out = pexpect.run(script_name, env={'PATH': right_dir})
+ finally:
+ os.environ['PATH'] = orig_path
+ self.assertEqual(out.rstrip(), b'success')
+
+
+if __name__ == '__main__':
+ unittest.main()
Index: third_party/Python/module/pexpect-4.6/tests/test_expect.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/test_expect.py
+++ third_party/Python/module/pexpect-4.6/tests/test_expect.py
@@ -0,0 +1,602 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import multiprocessing
+import unittest
+import subprocess
+import time
+import signal
+import sys
+import os
+
+import pexpect
+from . import PexpectTestCase
+from .utils import no_coverage_env
+
+# Many of these test cases blindly assume that sequential directory
+# listings of the /bin directory will yield the same results.
+# This may not be true, but seems adequate for testing now.
+# I should fix this at some point.
+
+FILTER=''.join([(len(repr(chr(x)))==3) and chr(x) or '.' for x in range(256)])
+def hex_dump(src, length=16):
+ result=[]
+ for i in xrange(0, len(src), length):
+ s = src[i:i+length]
+ hexa = ' '.join(["%02X"%ord(x) for x in s])
+ printable = s.translate(FILTER)
+ result.append("%04X %-*s %s\n" % (i, length*3, hexa, printable))
+ return ''.join(result)
+
+def hex_diff(left, right):
+ diff = ['< %s\n> %s' % (_left, _right,) for _left, _right in zip(
+ hex_dump(left).splitlines(), hex_dump(right).splitlines())
+ if _left != _right]
+ return '\n' + '\n'.join(diff,)
+
+
+class ExpectTestCase (PexpectTestCase.PexpectTestCase):
+
+ def test_expect_basic (self):
+ p = pexpect.spawn('cat', echo=False, timeout=5)
+ p.sendline (b'Hello')
+ p.sendline (b'there')
+ p.sendline (b'Mr. Python')
+ p.expect (b'Hello')
+ p.expect (b'there')
+ p.expect (b'Mr. Python')
+ p.sendeof ()
+ p.expect (pexpect.EOF)
+
+ def test_expect_exact_basic (self):
+ p = pexpect.spawn('cat', echo=False, timeout=5)
+ p.sendline (b'Hello')
+ p.sendline (b'there')
+ p.sendline (b'Mr. Python')
+ p.expect_exact (b'Hello')
+ p.expect_exact (b'there')
+ p.expect_exact (b'Mr. Python')
+ p.sendeof ()
+ p.expect_exact (pexpect.EOF)
+
+ def test_expect_ignore_case(self):
+ '''This test that the ignorecase flag will match patterns
+ even if case is different using the regex (?i) directive.
+ '''
+ p = pexpect.spawn('cat', echo=False, timeout=5)
+ p.sendline (b'HELLO')
+ p.sendline (b'there')
+ p.expect (b'(?i)hello')
+ p.expect (b'(?i)THERE')
+ p.sendeof ()
+ p.expect (pexpect.EOF)
+
+ def test_expect_ignore_case_flag(self):
+ '''This test that the ignorecase flag will match patterns
+ even if case is different using the ignorecase flag.
+ '''
+ p = pexpect.spawn('cat', echo=False, timeout=5)
+ p.ignorecase = True
+ p.sendline (b'HELLO')
+ p.sendline (b'there')
+ p.expect (b'hello')
+ p.expect (b'THERE')
+ p.sendeof ()
+ p.expect (pexpect.EOF)
+
+ def test_expect_order (self):
+ '''This tests that patterns are matched in the same order as given in the pattern_list.
+
+ (Or does it? Doesn't it also pass if expect() always chooses
+ (one of the) the leftmost matches in the input? -- grahn)
+ ... agreed! -jquast, the buffer ptr isn't forwarded on match, see first two test cases
+ '''
+ p = pexpect.spawn('cat', echo=False, timeout=5)
+ self._expect_order(p)
+
+ def test_expect_order_exact (self):
+ '''Like test_expect_order(), but using expect_exact().
+ '''
+ p = pexpect.spawn('cat', echo=False, timeout=5)
+ p.expect = p.expect_exact
+ self._expect_order(p)
+
+ def _expect_order (self, p):
+ p.sendline (b'1234')
+ p.sendline (b'abcd')
+ p.sendline (b'wxyz')
+ p.sendline (b'7890')
+ p.sendeof ()
+ index = p.expect ([
+ b'1234',
+ b'abcd',
+ b'wxyz',
+ pexpect.EOF,
+ b'7890' ])
+ assert index == 0, (index, p.before, p.after)
+ index = p.expect ([
+ b'54321',
+ pexpect.TIMEOUT,
+ b'1234',
+ b'abcd',
+ b'wxyz',
+ pexpect.EOF], timeout=5)
+ assert index == 3, (index, p.before, p.after)
+ index = p.expect ([
+ b'54321',
+ pexpect.TIMEOUT,
+ b'1234',
+ b'abcd',
+ b'wxyz',
+ pexpect.EOF], timeout=5)
+ assert index == 4, (index, p.before, p.after)
+ index = p.expect ([
+ pexpect.EOF,
+ b'abcd',
+ b'wxyz',
+ b'7890' ])
+ assert index == 3, (index, p.before, p.after)
+
+ index = p.expect ([
+ b'abcd',
+ b'wxyz',
+ b'7890',
+ pexpect.EOF])
+ assert index == 3, (index, p.before, p.after)
+
+ def test_expect_setecho_off(self):
+ '''This tests that echo may be toggled off.
+ '''
+ p = pexpect.spawn('cat', echo=True, timeout=5)
+ try:
+ self._expect_echo_toggle(p)
+ except IOError:
+ if sys.platform.lower().startswith('sunos'):
+ if hasattr(unittest, 'SkipTest'):
+ raise unittest.SkipTest("Not supported on this platform.")
+ return 'skip'
+ raise
+
+ def test_expect_setecho_off_exact(self):
+ p = pexpect.spawn('cat', echo=True, timeout=5)
+ p.expect = p.expect_exact
+ try:
+ self._expect_echo_toggle(p)
+ except IOError:
+ if sys.platform.lower().startswith('sunos'):
+ if hasattr(unittest, 'SkipTest'):
+ raise unittest.SkipTest("Not supported on this platform.")
+ return 'skip'
+ raise
+
+ def test_waitnoecho(self):
+ " Tests setecho(False) followed by waitnoecho() "
+ p = pexpect.spawn('cat', echo=False, timeout=5)
+ try:
+ p.setecho(False)
+ p.waitnoecho()
+ except IOError:
+ if sys.platform.lower().startswith('sunos'):
+ if hasattr(unittest, 'SkipTest'):
+ raise unittest.SkipTest("Not supported on this platform.")
+ return 'skip'
+ raise
+
+ def test_waitnoecho_order(self):
+
+ ''' This tests that we can wait on a child process to set echo mode.
+ For example, this tests that we could wait for SSH to set ECHO False
+ when asking of a password. This makes use of an external script
+ echo_wait.py. '''
+
+ p1 = pexpect.spawn('%s echo_wait.py' % self.PYTHONBIN)
+ start = time.time()
+ try:
+ p1.waitnoecho(timeout=10)
+ except IOError:
+ if sys.platform.lower().startswith('sunos'):
+ if hasattr(unittest, 'SkipTest'):
+ raise unittest.SkipTest("Not supported on this platform.")
+ return 'skip'
+ raise
+
+
+ end_time = time.time() - start
+ assert end_time < 10 and end_time > 2, "waitnoecho did not set ECHO off in the expected window of time."
+
+ # test that we actually timeout and return False if ECHO is never set off.
+ p1 = pexpect.spawn('cat')
+ start = time.time()
+ retval = p1.waitnoecho(timeout=4)
+ end_time = time.time() - start
+ assert end_time > 3, "waitnoecho should have waited longer than 2 seconds. retval should be False, retval=%d"%retval
+ assert retval==False, "retval should be False, retval=%d"%retval
+
+ # This one is mainly here to test default timeout for code coverage.
+ p1 = pexpect.spawn('%s echo_wait.py' % self.PYTHONBIN)
+ start = time.time()
+ p1.waitnoecho()
+ end_time = time.time() - start
+ assert end_time < 10, "waitnoecho did not set ECHO off in the expected window of time."
+
+ def test_expect_echo (self):
+ '''This tests that echo is on by default.
+ '''
+ p = pexpect.spawn('cat', echo=True, timeout=5)
+ self._expect_echo(p)
+
+ def test_expect_echo_exact (self):
+ '''Like test_expect_echo(), but using expect_exact().
+ '''
+ p = pexpect.spawn('cat', echo=True, timeout=5)
+ p.expect = p.expect_exact
+ self._expect_echo(p)
+
+ def _expect_echo (self, p):
+ p.sendline (b'1234') # Should see this twice (once from tty echo and again from cat).
+ index = p.expect ([
+ b'1234',
+ b'abcd',
+ b'wxyz',
+ pexpect.EOF,
+ pexpect.TIMEOUT])
+ assert index == 0, "index="+str(index)+"\n"+p.before
+ index = p.expect ([
+ b'1234',
+ b'abcd',
+ b'wxyz',
+ pexpect.EOF])
+ assert index == 0, "index="+str(index)
+
+ def _expect_echo_toggle(self, p):
+ p.sendline (b'1234') # Should see this twice (once from tty echo and again from cat).
+ index = p.expect ([
+ b'1234',
+ b'abcd',
+ b'wxyz',
+ pexpect.EOF,
+ pexpect.TIMEOUT])
+ assert index == 0, "index="+str(index)+"\n"+p.before
+ index = p.expect ([
+ b'1234',
+ b'abcd',
+ b'wxyz',
+ pexpect.EOF])
+ assert index == 0, "index="+str(index)
+ p.setecho(0) # Turn off tty echo
+ p.waitnoecho()
+ p.sendline (b'abcd') # Now, should only see this once.
+ p.sendline (b'wxyz') # Should also be only once.
+ index = p.expect ([
+ pexpect.EOF,
+ pexpect.TIMEOUT,
+ b'abcd',
+ b'wxyz',
+ b'1234'])
+ assert index == 2, "index="+str(index)
+ index = p.expect ([
+ pexpect.EOF,
+ b'abcd',
+ b'wxyz',
+ b'7890'])
+ assert index == 2, "index="+str(index)
+ p.setecho(1) # Turn on tty echo
+ p.sendline (b'7890') # Should see this twice.
+ index = p.expect ([pexpect.EOF,b'abcd',b'wxyz',b'7890'])
+ assert index == 3, "index="+str(index)
+ index = p.expect ([pexpect.EOF,b'abcd',b'wxyz',b'7890'])
+ assert index == 3, "index="+str(index)
+ p.sendeof()
+
+ def test_expect_index (self):
+ '''This tests that mixed list of regex strings, TIMEOUT, and EOF all
+ return the correct index when matched.
+ '''
+ p = pexpect.spawn('cat', echo=False, timeout=5)
+ self._expect_index(p)
+
+ def test_expect_index_exact (self):
+ '''Like test_expect_index(), but using expect_exact().
+ '''
+ p = pexpect.spawn('cat', echo=False, timeout=5)
+ p.expect = p.expect_exact
+ self._expect_index(p)
+
+ def _expect_index (self, p):
+ p.sendline (b'1234')
+ index = p.expect ([b'abcd',b'wxyz',b'1234',pexpect.EOF])
+ assert index == 2, "index="+str(index)
+ p.sendline (b'abcd')
+ index = p.expect ([pexpect.TIMEOUT,b'abcd',b'wxyz',b'1234',pexpect.EOF])
+ assert index == 1, "index="+str(index)+str(p)
+ p.sendline (b'wxyz')
+ index = p.expect ([b'54321',pexpect.TIMEOUT,b'abcd',b'wxyz',b'1234',pexpect.EOF])
+ assert index == 3, "index="+str(index) # Expect 'wxyz'
+ p.sendline (b'$*!@?')
+ index = p.expect ([b'54321',pexpect.TIMEOUT,b'abcd',b'wxyz',b'1234',pexpect.EOF],
+ timeout=1)
+ assert index == 1, "index="+str(index) # Expect TIMEOUT
+ p.sendeof ()
+ index = p.expect ([b'54321',pexpect.TIMEOUT,b'abcd',b'wxyz',b'1234',pexpect.EOF])
+ assert index == 5, "index="+str(index) # Expect EOF
+
+ def test_expect (self):
+ the_old_way = subprocess.Popen(args=['ls', '-l', '/bin'],
+ stdout=subprocess.PIPE).communicate()[0].rstrip()
+ p = pexpect.spawn('ls -l /bin')
+ the_new_way = b''
+ while 1:
+ i = p.expect ([b'\n', pexpect.EOF])
+ the_new_way = the_new_way + p.before
+ if i == 1:
+ break
+ the_new_way = the_new_way.rstrip()
+ the_new_way = the_new_way.replace(b'\r\n', b'\n'
+ ).replace(b'\r', b'\n').replace(b'\n\n', b'\n').rstrip()
+ the_old_way = the_old_way.replace(b'\r\n', b'\n'
+ ).replace(b'\r', b'\n').replace(b'\n\n', b'\n').rstrip()
+ assert the_old_way == the_new_way, hex_diff(the_old_way, the_new_way)
+
+ def test_expect_exact (self):
+ the_old_way = subprocess.Popen(args=['ls', '-l', '/bin'],
+ stdout=subprocess.PIPE).communicate()[0].rstrip()
+ p = pexpect.spawn('ls -l /bin')
+ the_new_way = b''
+ while 1:
+ i = p.expect_exact ([b'\n', pexpect.EOF])
+ the_new_way = the_new_way + p.before
+ if i == 1:
+ break
+ the_new_way = the_new_way.replace(b'\r\n', b'\n'
+ ).replace(b'\r', b'\n').replace(b'\n\n', b'\n').rstrip()
+ the_old_way = the_old_way.replace(b'\r\n', b'\n'
+ ).replace(b'\r', b'\n').replace(b'\n\n', b'\n').rstrip()
+ assert the_old_way == the_new_way, hex_diff(the_old_way, the_new_way)
+ p = pexpect.spawn('echo hello.?world')
+ i = p.expect_exact(b'.?')
+ self.assertEqual(p.before, b'hello')
+ self.assertEqual(p.after, b'.?')
+
+ def test_expect_eof (self):
+ the_old_way = subprocess.Popen(args=['/bin/ls', '-l', '/bin'],
+ stdout=subprocess.PIPE).communicate()[0].rstrip()
+ p = pexpect.spawn('/bin/ls -l /bin')
+ p.expect(pexpect.EOF) # This basically tells it to read everything. Same as pexpect.run() function.
+ the_new_way = p.before
+ the_new_way = the_new_way.replace(b'\r\n', b'\n'
+ ).replace(b'\r', b'\n').replace(b'\n\n', b'\n').rstrip()
+ the_old_way = the_old_way.replace(b'\r\n', b'\n'
+ ).replace(b'\r', b'\n').replace(b'\n\n', b'\n').rstrip()
+ assert the_old_way == the_new_way, hex_diff(the_old_way, the_new_way)
+
+ def test_expect_timeout (self):
+ p = pexpect.spawn('cat', timeout=5)
+ p.expect(pexpect.TIMEOUT) # This tells it to wait for timeout.
+ self.assertEqual(p.after, pexpect.TIMEOUT)
+
+ def test_unexpected_eof (self):
+ p = pexpect.spawn('ls -l /bin')
+ try:
+ p.expect('_Z_XY_XZ') # Probably never see this in ls output.
+ except pexpect.EOF:
+ pass
+ else:
+ self.fail ('Expected an EOF exception.')
+
+ def test_buffer_interface(self):
+ p = pexpect.spawn('cat', timeout=5)
+ p.sendline (b'Hello')
+ p.expect (b'Hello')
+ assert len(p.buffer)
+ p.buffer = b'Testing'
+ p.sendeof ()
+
+ def test_before_across_chunks(self):
+ # https://github.com/pexpect/pexpect/issues/478
+ child = pexpect.spawn(
+ '''/bin/bash -c "openssl rand -base64 {} | head -500 | nl --number-format=rz --number-width=5 2>&1 ; echo 'PATTERN!!!'"'''.format(1024 * 1024 * 2),
+ searchwindowsize=128
+ )
+ child.expect(['PATTERN'])
+ assert len(child.before.splitlines()) == 500
+ assert child.after == b'PATTERN'
+ assert child.buffer == b'!!!\r\n'
+
+ def _before_after(self, p):
+ p.timeout = 5
+
+ p.expect(b'5')
+ self.assertEqual(p.after, b'5')
+ assert p.before.startswith(b'[0, 1, 2'), p.before
+
+ p.expect(b'50')
+ self.assertEqual(p.after, b'50')
+ assert p.before.startswith(b', 6, 7, 8'), p.before[:20]
+ assert p.before.endswith(b'48, 49, '), p.before[-20:]
+
+ p.expect(pexpect.EOF)
+ self.assertEqual(p.after, pexpect.EOF)
+ assert p.before.startswith(b', 51, 52'), p.before[:20]
+ assert p.before.endswith(b', 99]\r\n'), p.before[-20:]
+
+ def test_before_after(self):
+ '''This tests expect() for some simple before/after things.
+ '''
+ p = pexpect.spawn('%s -Wi list100.py' % self.PYTHONBIN, env=no_coverage_env())
+ self._before_after(p)
+
+ def test_before_after_exact(self):
+ '''This tests some simple before/after things, for
+ expect_exact(). (Grahn broke it at one point.)
+ '''
+ p = pexpect.spawn('%s -Wi list100.py' % self.PYTHONBIN, env=no_coverage_env())
+ # mangle the spawn so we test expect_exact() instead
+ p.expect = p.expect_exact
+ self._before_after(p)
+
+ def _ordering(self, p):
+ p.timeout = 20
+ p.expect(b'>>> ')
+
+ p.sendline('list(range(4*3))')
+ self.assertEqual(p.expect([b'5,', b'5,']), 0)
+ p.expect(b'>>> ')
+
+ p.sendline(b'list(range(4*3))')
+ self.assertEqual(p.expect([b'7,', b'5,']), 1)
+ p.expect(b'>>> ')
+
+ p.sendline(b'list(range(4*3))')
+ self.assertEqual(p.expect([b'5,', b'7,']), 0)
+ p.expect(b'>>> ')
+
+ p.sendline(b'list(range(4*5))')
+ self.assertEqual(p.expect([b'2,', b'12,']), 0)
+ p.expect(b'>>> ')
+
+ p.sendline(b'list(range(4*5))')
+ self.assertEqual(p.expect([b'12,', b'2,']), 1)
+
+ def test_ordering(self):
+ '''This tests expect() for which pattern is returned
+ when many may eventually match. I (Grahn) am a bit
+ confused about what should happen, but this test passes
+ with pexpect 2.1.
+ '''
+ p = pexpect.spawn(self.PYTHONBIN)
+ self._ordering(p)
+
+ def test_ordering_exact(self):
+ '''This tests expect_exact() for which pattern is returned
+ when many may eventually match. I (Grahn) am a bit
+ confused about what should happen, but this test passes
+ for the expect() method with pexpect 2.1.
+ '''
+ p = pexpect.spawn(self.PYTHONBIN)
+ # mangle the spawn so we test expect_exact() instead
+ p.expect = p.expect_exact
+ self._ordering(p)
+
+ def _greed(self, expect):
+ # End at the same point: the one with the earliest start should win
+ self.assertEqual(expect([b'3, 4', b'2, 3, 4']), 1)
+
+ # Start at the same point: first pattern passed wins
+ self.assertEqual(expect([b'5,', b'5, 6']), 0)
+
+ # Same pattern passed twice: first instance wins
+ self.assertEqual(expect([b'7, 8', b'7, 8, 9', b'7, 8']), 0)
+
+ def _greed_read1(self, expect):
+ # Here, one has an earlier start and a later end. When processing
+ # one character at a time, the one that finishes first should win,
+ # because we don't know about the other match when it wins.
+ # If maxread > 1, this behaviour is currently undefined, although in
+ # most cases the one that starts first will win.
+ self.assertEqual(expect([b'1, 2, 3', b'2,']), 1)
+
+ def test_greed(self):
+ p = pexpect.spawn(self.PYTHONBIN + ' list100.py')
+ self._greed(p.expect)
+
+ p = pexpect.spawn(self.PYTHONBIN + ' list100.py', maxread=1)
+ self._greed_read1(p.expect)
+
+ def test_greed_exact(self):
+ p = pexpect.spawn(self.PYTHONBIN + ' list100.py')
+ self._greed(p.expect_exact)
+
+ p = pexpect.spawn(self.PYTHONBIN + ' list100.py', maxread=1)
+ self._greed_read1(p.expect_exact)
+
+ def test_bad_arg(self):
+ p = pexpect.spawn('cat')
+ with self.assertRaisesRegexp(TypeError, '.*must be one of'):
+ p.expect(1)
+ with self.assertRaisesRegexp(TypeError, '.*must be one of'):
+ p.expect([1, b'2'])
+ with self.assertRaisesRegexp(TypeError, '.*must be one of'):
+ p.expect_exact(1)
+ with self.assertRaisesRegexp(TypeError, '.*must be one of'):
+ p.expect_exact([1, b'2'])
+
+ def test_timeout_none(self):
+ p = pexpect.spawn('echo abcdef', timeout=None)
+ p.expect('abc')
+ p.expect_exact('def')
+ p.expect(pexpect.EOF)
+
+ def test_signal_handling(self):
+ '''
+ This tests the error handling of a signal interrupt (usually a
+ SIGWINCH generated when a window is resized), but in this test, we
+ are substituting an ALARM signal as this is much easier for testing
+ and is treated the same as a SIGWINCH.
+
+ To ensure that the alarm fires during the expect call, we are
+ setting the signal to alarm after 1 second while the spawned process
+ sleeps for 2 seconds prior to sending the expected output.
+ '''
+ def noop(x, y):
+ pass
+ signal.signal(signal.SIGALRM, noop)
+
+ p1 = pexpect.spawn('%s sleep_for.py 2' % self.PYTHONBIN, timeout=5)
+ p1.expect('READY')
+ signal.alarm(1)
+ p1.expect('END')
+
+ def test_stdin_closed(self):
+ '''
+ Ensure pexpect continues to operate even when stdin is closed
+ '''
+ class Closed_stdin_proc(multiprocessing.Process):
+ def run(self):
+ sys.__stdin__.close()
+ cat = pexpect.spawn('cat')
+ cat.sendeof()
+ cat.expect(pexpect.EOF)
+
+ proc = Closed_stdin_proc()
+ proc.start()
+ proc.join()
+ assert proc.exitcode == 0
+
+ def test_stdin_stdout_closed(self):
+ '''
+ Ensure pexpect continues to operate even when stdin and stdout is closed
+ '''
+ class Closed_stdin_stdout_proc(multiprocessing.Process):
+ def run(self):
+ sys.__stdin__.close()
+ sys.__stdout__.close()
+ cat = pexpect.spawn('cat')
+ cat.sendeof()
+ cat.expect(pexpect.EOF)
+
+ proc = Closed_stdin_stdout_proc()
+ proc.start()
+ proc.join()
+ assert proc.exitcode == 0
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(ExpectTestCase, 'test')
Index: third_party/Python/module/pexpect-4.6/tests/test_filedescriptor.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/test_filedescriptor.py
+++ third_party/Python/module/pexpect-4.6/tests/test_filedescriptor.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+from pexpect import fdpexpect
+import unittest
+from . import PexpectTestCase
+import os
+
+class ExpectTestCase(PexpectTestCase.PexpectTestCase):
+ def setUp(self):
+ print(self.id())
+ PexpectTestCase.PexpectTestCase.setUp(self)
+
+ def test_fd (self):
+ fd = os.open ('TESTDATA.txt', os.O_RDONLY)
+ s = fdpexpect.fdspawn (fd)
+ s.expect(b'This is the end of test data:')
+ s.expect(pexpect.EOF)
+ self.assertEqual(s.before, b' END\n')
+
+ def test_maxread (self):
+ fd = os.open ('TESTDATA.txt', os.O_RDONLY)
+ s = fdpexpect.fdspawn (fd)
+ s.maxread = 100
+ s.expect('2')
+ s.expect ('This is the end of test data:')
+ s.expect (pexpect.EOF)
+ self.assertEqual(s.before, b' END\n')
+
+ def test_fd_isalive (self):
+ fd = os.open ('TESTDATA.txt', os.O_RDONLY)
+ s = fdpexpect.fdspawn(fd)
+ assert s.isalive()
+ os.close(fd)
+ assert not s.isalive(), "Should not be alive after close()"
+
+ def test_fd_isatty (self):
+ fd = os.open ('TESTDATA.txt', os.O_RDONLY)
+ s = fdpexpect.fdspawn (fd)
+ assert not s.isatty()
+ s.close()
+
+ def test_fileobj(self):
+ f = open('TESTDATA.txt', 'r')
+ s = fdpexpect.fdspawn(f) # Should get the fileno from the file handle
+ s.expect('2')
+ s.close()
+ assert not s.isalive()
+ s.close() # Smoketest - should be able to call this again
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(ExpectTestCase, 'test')
Index: third_party/Python/module/pexpect-4.6/tests/test_interact.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/test_interact.py
+++ third_party/Python/module/pexpect-4.6/tests/test_interact.py
@@ -0,0 +1,101 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+from __future__ import print_function
+from __future__ import unicode_literals
+
+import os
+import pexpect
+import unittest
+import sys
+from . import PexpectTestCase
+
+
+class InteractTestCase (PexpectTestCase.PexpectTestCase):
+ def setUp(self):
+ super(InteractTestCase, self).setUp()
+ self.env = env = os.environ.copy()
+
+ # Ensure 'import pexpect' works in subprocess interact*.py
+ if 'PYTHONPATH' in env:
+ env['PYTHONPATH'] = os.pathsep.join((self.project_dir,
+ env['PYTHONPATH']))
+ else:
+ env['PYTHONPATH'] = self.project_dir
+
+ self.interact_py = ('{sys.executable} interact.py'.format(sys=sys))
+
+ def test_interact_escape(self):
+ " Ensure `escape_character' value exits interactive mode. "
+ p = pexpect.spawn(self.interact_py, timeout=5, env=self.env)
+ p.expect('READY')
+ p.sendcontrol(']') # chr(29), the default `escape_character'
+ # value of pexpect.interact().
+ p.expect_exact('Escaped interact')
+ p.expect(pexpect.EOF)
+ assert not p.isalive()
+ assert p.exitstatus == 0
+
+ def test_interact_escape_None(self):
+ " Return only after Termination when `escape_character=None'. "
+ p = pexpect.spawn('{self.interact_py} --no-escape'.format(self=self),
+ timeout=5, env=self.env)
+ p.expect('READY')
+ p.sendcontrol(']')
+ p.expect('29')
+ p.send('\x00')
+ if not os.environ.get('TRAVIS', None):
+ # on Travis-CI, we sometimes miss trailing stdout from the
+ # chain of child processes, not entirely sure why. So this
+ # is skipped on such systems.
+ p.expect('0')
+ p.expect_exact('Escaped interact')
+ p.expect(pexpect.EOF)
+ assert not p.isalive()
+ assert p.exitstatus == 0
+
+ def test_interact_exit_unicode(self):
+ " Ensure subprocess receives utf8. "
+ p = pexpect.spawnu('{self.interact_py} --utf8'.format(self=self),
+ timeout=5, env=self.env)
+ p.expect('READY')
+ p.send('ɑ') # >>> map(ord, u'ɑ'.encode('utf8'))
+ p.expect('201') # [201, 145]
+ p.expect('145')
+ p.send('Β') # >>> map(ord, u'Β'.encode('utf8'))
+ p.expect('206') # [206, 146]
+ p.expect('146')
+ p.send('\x00')
+ if not os.environ.get('TRAVIS', None):
+ # on Travis-CI, we sometimes miss trailing stdout from the
+ # chain of child processes, not entirely sure why. So this
+ # is skipped on such systems.
+ p.expect('0')
+ p.expect_exact('Escaped interact')
+ p.expect(pexpect.EOF)
+ assert not p.isalive()
+ assert p.exitstatus == 0
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(InteractTestCase, 'test')
+
Index: third_party/Python/module/pexpect-4.6/tests/test_isalive.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/test_isalive.py
+++ third_party/Python/module/pexpect-4.6/tests/test_isalive.py
@@ -0,0 +1,125 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+import unittest
+import signal
+import sys
+import time
+from . import PexpectTestCase
+
+
+class IsAliveTestCase(PexpectTestCase.PexpectTestCase):
+ """Various tests for the running status of processes."""
+
+ def test_expect_wait(self):
+ """Ensure consistency in wait() and isalive()."""
+ p = pexpect.spawn('sleep 1')
+ assert p.isalive()
+ assert p.wait() == 0
+ assert not p.isalive()
+ # In previous versions of ptyprocess/pexpect, calling wait() a second
+ # time would raise an exception, but not since v4.0
+ assert p.wait() == 0
+
+ def test_expect_wait_after_termination(self):
+ """Ensure wait on a process terminated by kill -9."""
+ p = pexpect.spawn('sleep 3')
+ assert p.isalive()
+ p.kill(9)
+ time.sleep(1)
+
+ # when terminated, the exitstatus is None, but p.signalstatus
+ # and p.terminated reflects that the kill -9 nature.
+ assert p.wait() is None
+ assert p.signalstatus == 9
+ assert p.terminated == True
+ assert not p.isalive()
+
+ def test_signal_wait(self):
+ '''Test calling wait with a process terminated by a signal.'''
+ if not hasattr(signal, 'SIGALRM'):
+ return 'SKIP'
+ p = pexpect.spawn(sys.executable, ['alarm_die.py'])
+ p.wait()
+ assert p.exitstatus is None
+ self.assertEqual(p.signalstatus, signal.SIGALRM)
+
+ def test_expect_isalive_dead_after_normal_termination (self):
+ p = pexpect.spawn('ls', timeout=15)
+ p.expect(pexpect.EOF)
+ assert not p.isalive()
+
+ def test_expect_isalive_dead_after_SIGHUP(self):
+ p = pexpect.spawn('cat', timeout=5, ignore_sighup=False)
+ assert p.isalive()
+ force = False
+ if sys.platform.lower().startswith('sunos'):
+ # On Solaris (SmartOs), and only when executed from cron(1), SIGKILL
+ # is required to end the sub-process. This is done using force=True
+ force = True
+ assert p.terminate(force) == True
+ p.expect(pexpect.EOF)
+ assert not p.isalive()
+
+ def test_expect_isalive_dead_after_SIGINT(self):
+ p = pexpect.spawn('cat', timeout=5)
+ assert p.isalive()
+ force = False
+ if sys.platform.lower().startswith('sunos'):
+ # On Solaris (SmartOs), and only when executed from cron(1), SIGKILL
+ # is required to end the sub-process. This is done using force=True
+ force = True
+ assert p.terminate(force) == True
+ p.expect(pexpect.EOF)
+ assert not p.isalive()
+
+ def test_expect_isalive_dead_after_SIGKILL(self):
+ p = pexpect.spawn('cat', timeout=5)
+ assert p.isalive()
+ p.kill(9)
+ p.expect(pexpect.EOF)
+ assert not p.isalive()
+
+ def test_forced_terminate(self):
+ p = pexpect.spawn(sys.executable, ['needs_kill.py'])
+ p.expect('READY')
+ assert p.terminate(force=True) == True
+ p.expect(pexpect.EOF)
+ assert not p.isalive()
+
+### Some platforms allow this. Some reset status after call to waitpid.
+### probably not necessary, isalive() returns early when terminate is False.
+ def test_expect_isalive_consistent_multiple_calls (self):
+ '''This tests that multiple calls to isalive() return same value.
+ '''
+ p = pexpect.spawn('cat')
+ assert p.isalive()
+ assert p.isalive()
+ p.sendeof()
+ p.expect(pexpect.EOF)
+ assert not p.isalive()
+ assert not p.isalive()
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(IsAliveTestCase, 'test')
+
Index: third_party/Python/module/pexpect-4.6/tests/test_log.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/test_log.py
+++ third_party/Python/module/pexpect-4.6/tests/test_log.py
@@ -0,0 +1,108 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+import unittest
+import os
+import tempfile
+from . import PexpectTestCase
+
+# the program cat(1) may display ^D\x08\x08 when \x04 (EOF, Ctrl-D) is sent
+_CAT_EOF = b'^D\x08\x08'
+
+class TestCaseLog(PexpectTestCase.PexpectTestCase):
+
+ def test_log (self):
+ log_message = 'This is a test.'
+ filename = tempfile.mktemp()
+ mylog = open(filename, 'wb')
+ p = pexpect.spawn('echo', [log_message])
+ p.logfile = mylog
+ p.expect(pexpect.EOF)
+ p.logfile = None
+ mylog.close()
+ with open(filename, 'rb') as f:
+ lf = f.read()
+ os.unlink(filename)
+ self.assertEqual(lf.rstrip(), log_message.encode('ascii'))
+
+ def test_log_logfile_read (self):
+ log_message = 'This is a test.'
+ filename = tempfile.mktemp()
+ mylog = open(filename, 'wb')
+ p = pexpect.spawn('cat')
+ p.logfile_read = mylog
+ p.sendline(log_message)
+ p.sendeof()
+ p.expect(pexpect.EOF)
+ p.logfile = None
+ mylog.close()
+ with open(filename, 'rb') as f:
+ lf = f.read()
+ os.unlink (filename)
+ lf = lf.replace(_CAT_EOF, b'')
+ self.assertEqual(lf, b'This is a test.\r\nThis is a test.\r\n')
+
+ def test_log_logfile_send (self):
+ log_message = b'This is a test.'
+ filename = tempfile.mktemp()
+ mylog = open (filename, 'wb')
+ p = pexpect.spawn('cat')
+ p.logfile_send = mylog
+ p.sendline(log_message)
+ p.sendeof()
+ p.expect (pexpect.EOF)
+ p.logfile = None
+ mylog.close()
+ with open(filename, 'rb') as f:
+ lf = f.read()
+ os.unlink(filename)
+ lf = lf.replace(b'\x04', b'')
+ self.assertEqual(lf.rstrip(), log_message)
+
+ def test_log_send_and_received (self):
+
+ '''The logfile should have the test message three time -- once for the
+ data we sent. Once for the data that cat echos back as characters are
+ typed. And once for the data that cat prints after we send a linefeed
+ (sent by sendline). '''
+
+ log_message = 'This is a test.'
+ filename = tempfile.mktemp()
+ mylog = open(filename, 'wb')
+ p = pexpect.spawn('cat')
+ p.logfile = mylog
+ p.sendline(log_message)
+ p.sendeof()
+ p.expect (pexpect.EOF)
+ p.logfile = None
+ mylog.close()
+ with open(filename, 'rb') as f:
+ lf = f.read()
+ os.unlink(filename)
+ lf = lf.replace(b'\x04', b'').replace(_CAT_EOF, b'')
+ self.assertEqual(lf,
+ b'This is a test.\nThis is a test.\r\nThis is a test.\r\n')
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(TestCaseLog,'test')
+
Index: third_party/Python/module/pexpect-4.6/tests/test_misc.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/test_misc.py
+++ third_party/Python/module/pexpect-4.6/tests/test_misc.py
@@ -0,0 +1,373 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import unittest
+import sys
+import re
+import signal
+import time
+import tempfile
+import os
+
+import pexpect
+from . import PexpectTestCase
+
+# the program cat(1) may display ^D\x08\x08 when \x04 (EOF, Ctrl-D) is sent
+_CAT_EOF = b'^D\x08\x08'
+
+
+if (sys.version_info[0] >= 3):
+ def _u(s):
+ return s.decode('utf-8')
+else:
+ def _u(s):
+ return s
+
+
+class TestCaseMisc(PexpectTestCase.PexpectTestCase):
+
+ def test_isatty(self):
+ " Test isatty() is True after spawning process on most platforms. "
+ child = pexpect.spawn('cat')
+ if not child.isatty() and sys.platform.lower().startswith('sunos'):
+ if hasattr(unittest, 'SkipTest'):
+ raise unittest.SkipTest("Not supported on this platform.")
+ return 'skip'
+ assert child.isatty()
+
+ def test_isatty_poll(self):
+ " Test isatty() is True after spawning process on most platforms. "
+ child = pexpect.spawn('cat', use_poll=True)
+ if not child.isatty() and sys.platform.lower().startswith('sunos'):
+ if hasattr(unittest, 'SkipTest'):
+ raise unittest.SkipTest("Not supported on this platform.")
+ return 'skip'
+ assert child.isatty()
+
+ def test_read(self):
+ " Test spawn.read by calls of various size. "
+ child = pexpect.spawn('cat')
+ child.sendline("abc")
+ child.sendeof()
+ self.assertEqual(child.read(0), b'')
+ self.assertEqual(child.read(1), b'a')
+ self.assertEqual(child.read(1), b'b')
+ self.assertEqual(child.read(1), b'c')
+ self.assertEqual(child.read(2), b'\r\n')
+ remaining = child.read().replace(_CAT_EOF, b'')
+ self.assertEqual(remaining, b'abc\r\n')
+
+ def test_read_poll(self):
+ " Test spawn.read by calls of various size. "
+ child = pexpect.spawn('cat', use_poll=True)
+ child.sendline("abc")
+ child.sendeof()
+ self.assertEqual(child.read(0), b'')
+ self.assertEqual(child.read(1), b'a')
+ self.assertEqual(child.read(1), b'b')
+ self.assertEqual(child.read(1), b'c')
+ self.assertEqual(child.read(2), b'\r\n')
+ remaining = child.read().replace(_CAT_EOF, b'')
+ self.assertEqual(remaining, b'abc\r\n')
+
+ def test_read_poll_timeout(self):
+ " Test use_poll properly times out "
+ child = pexpect.spawn('sleep 5', use_poll=True)
+ with self.assertRaises(pexpect.TIMEOUT):
+ child.expect(pexpect.EOF, timeout=1)
+
+ def test_readline_bin_echo(self):
+ " Test spawn('echo'). "
+ # given,
+ child = pexpect.spawn('echo', ['alpha', 'beta'])
+
+ # exercise,
+ assert child.readline() == b'alpha beta' + child.crlf
+
+ def test_readline(self):
+ " Test spawn.readline(). "
+ # when argument 0 is sent, nothing is returned.
+ # Otherwise the argument value is meaningless.
+ child = pexpect.spawn('cat', echo=False)
+ child.sendline("alpha")
+ child.sendline("beta")
+ child.sendline("gamma")
+ child.sendline("delta")
+ child.sendeof()
+ assert child.readline(0) == b''
+ assert child.readline().rstrip() == b'alpha'
+ assert child.readline(1).rstrip() == b'beta'
+ assert child.readline(2).rstrip() == b'gamma'
+ assert child.readline().rstrip() == b'delta'
+ child.expect(pexpect.EOF)
+ assert not child.isalive()
+ assert child.exitstatus == 0
+
+ def test_iter(self):
+ " iterating over lines of spawn.__iter__(). "
+ child = pexpect.spawn('cat', echo=False)
+ child.sendline("abc")
+ child.sendline("123")
+ child.sendeof()
+ # Don't use ''.join() because we want to test __iter__().
+ page = b''
+ for line in child:
+ page += line
+ page = page.replace(_CAT_EOF, b'')
+ assert page == b'abc\r\n123\r\n'
+
+ def test_readlines(self):
+ " reading all lines of spawn.readlines(). "
+ child = pexpect.spawn('cat', echo=False)
+ child.sendline("abc")
+ child.sendline("123")
+ child.sendeof()
+ page = b''.join(child.readlines()).replace(_CAT_EOF, b'')
+ assert page == b'abc\r\n123\r\n'
+ child.expect(pexpect.EOF)
+ assert not child.isalive()
+ assert child.exitstatus == 0
+
+ def test_write(self):
+ " write a character and return it in return. "
+ child = pexpect.spawn('cat', echo=False)
+ child.write('a')
+ child.write('\r')
+ self.assertEqual(child.readline(), b'a\r\n')
+
+ def test_writelines(self):
+ " spawn.writelines() "
+ child = pexpect.spawn('cat')
+ # notice that much like file.writelines, we do not delimit by newline
+ # -- it is equivalent to calling write(''.join([args,]))
+ child.writelines(['abc', '123', 'xyz', '\r'])
+ child.sendeof()
+ line = child.readline()
+ assert line == b'abc123xyz\r\n'
+
+ def test_eof(self):
+ " call to expect() after EOF is received raises pexpect.EOF "
+ child = pexpect.spawn('cat')
+ child.sendeof()
+ with self.assertRaises(pexpect.EOF):
+ child.expect('the unexpected')
+
+ def test_with(self):
+ "spawn can be used as a context manager"
+ with pexpect.spawn(sys.executable + ' echo_w_prompt.py') as p:
+ p.expect('')
+ p.sendline(b'alpha')
+ p.expect(b'alpha')
+ assert p.isalive()
+
+ assert not p.isalive()
+
+ def test_terminate(self):
+ " test force terminate always succeeds (SIGKILL). "
+ child = pexpect.spawn('cat')
+ child.terminate(force=1)
+ assert child.terminated
+
+ def test_sighup(self):
+ " validate argument `ignore_sighup=True` and `ignore_sighup=False`. "
+ getch = sys.executable + ' getch.py'
+ child = pexpect.spawn(getch, ignore_sighup=True)
+ child.expect('READY')
+ child.kill(signal.SIGHUP)
+ for _ in range(10):
+ if not child.isalive():
+ self.fail('Child process should not have exited.')
+ time.sleep(0.1)
+
+ child = pexpect.spawn(getch, ignore_sighup=False)
+ child.expect('READY')
+ child.kill(signal.SIGHUP)
+ for _ in range(10):
+ if not child.isalive():
+ break
+ time.sleep(0.1)
+ else:
+ self.fail('Child process should have exited.')
+
+ def test_bad_child_pid(self):
+ " assert bad condition error in isalive(). "
+ expect_errmsg = re.escape("isalive() encountered condition where ")
+ child = pexpect.spawn('cat')
+ child.terminate(force=1)
+ # Force an invalid state to test isalive
+ child.ptyproc.terminated = 0
+ try:
+ with self.assertRaisesRegexp(pexpect.ExceptionPexpect,
+ ".*" + expect_errmsg):
+ child.isalive()
+ finally:
+ # Force valid state for child for __del__
+ child.terminated = 1
+
+ def test_bad_arguments_suggest_fdpsawn(self):
+ " assert custom exception for spawn(int). "
+ expect_errmsg = "maybe you want to use fdpexpect.fdspawn"
+ with self.assertRaisesRegexp(pexpect.ExceptionPexpect,
+ ".*" + expect_errmsg):
+ pexpect.spawn(1)
+
+ def test_bad_arguments_second_arg_is_list(self):
+ " Second argument to spawn, if used, must be only a list."
+ with self.assertRaises(TypeError):
+ pexpect.spawn('ls', '-la')
+
+ with self.assertRaises(TypeError):
+ # not even a tuple,
+ pexpect.spawn('ls', ('-la',))
+
+ def test_read_after_close_raises_value_error(self):
+ " Calling read_nonblocking after close raises ValueError. "
+ # as read_nonblocking underlies all other calls to read,
+ # ValueError should be thrown for all forms of read.
+ with self.assertRaises(ValueError):
+ p = pexpect.spawn('cat')
+ p.close()
+ p.read_nonblocking()
+
+ with self.assertRaises(ValueError):
+ p = pexpect.spawn('cat')
+ p.close()
+ p.read()
+
+ with self.assertRaises(ValueError):
+ p = pexpect.spawn('cat')
+ p.close()
+ p.readline()
+
+ with self.assertRaises(ValueError):
+ p = pexpect.spawn('cat')
+ p.close()
+ p.readlines()
+
+ def test_isalive(self):
+ " check isalive() before and after EOF. (True, False) "
+ child = pexpect.spawn('cat')
+ assert child.isalive() is True
+ child.sendeof()
+ child.expect(pexpect.EOF)
+ assert child.isalive() is False
+
+ def test_bad_type_in_expect(self):
+ " expect() does not accept dictionary arguments. "
+ child = pexpect.spawn('cat')
+ with self.assertRaises(TypeError):
+ child.expect({})
+
+ def test_cwd(self):
+ " check keyword argument `cwd=' of pexpect.run() "
+ tmp_dir = os.path.realpath(tempfile.gettempdir())
+ default = pexpect.run('pwd')
+ pwd_tmp = pexpect.run('pwd', cwd=tmp_dir).rstrip()
+ assert default != pwd_tmp
+ assert tmp_dir == _u(pwd_tmp)
+
+ def _test_searcher_as(self, searcher, plus=None):
+ # given,
+ given_words = ['alpha', 'beta', 'gamma', 'delta', ]
+ given_search = given_words
+ if searcher == pexpect.searcher_re:
+ given_search = [re.compile(word) for word in given_words]
+ if plus is not None:
+ given_search = given_search + [plus]
+ search_string = searcher(given_search)
+ basic_fmt = '\n {0}: {1}'
+ fmt = basic_fmt
+ if searcher is pexpect.searcher_re:
+ fmt = '\n {0}: re.compile({1})'
+ expected_output = '{0}:'.format(searcher.__name__)
+ idx = 0
+ for word in given_words:
+ expected_output += fmt.format(idx, "'{0}'".format(word))
+ idx += 1
+ if plus is not None:
+ if plus == pexpect.EOF:
+ expected_output += basic_fmt.format(idx, 'EOF')
+ elif plus == pexpect.TIMEOUT:
+ expected_output += basic_fmt.format(idx, 'TIMEOUT')
+
+ # exercise,
+ assert search_string.__str__() == expected_output
+
+ def test_searcher_as_string(self):
+ " check searcher_string(..).__str__() "
+ self._test_searcher_as(pexpect.searcher_string)
+
+ def test_searcher_as_string_with_EOF(self):
+ " check searcher_string(..).__str__() that includes EOF "
+ self._test_searcher_as(pexpect.searcher_string, plus=pexpect.EOF)
+
+ def test_searcher_as_string_with_TIMEOUT(self):
+ " check searcher_string(..).__str__() that includes TIMEOUT "
+ self._test_searcher_as(pexpect.searcher_string, plus=pexpect.TIMEOUT)
+
+ def test_searcher_re_as_string(self):
+ " check searcher_re(..).__str__() "
+ self._test_searcher_as(pexpect.searcher_re)
+
+ def test_searcher_re_as_string_with_EOF(self):
+ " check searcher_re(..).__str__() that includes EOF "
+ self._test_searcher_as(pexpect.searcher_re, plus=pexpect.EOF)
+
+ def test_searcher_re_as_string_with_TIMEOUT(self):
+ " check searcher_re(..).__str__() that includes TIMEOUT "
+ self._test_searcher_as(pexpect.searcher_re, plus=pexpect.TIMEOUT)
+
+ def test_nonnative_pty_fork(self):
+ " test forced self.__fork_pty() and __pty_make_controlling_tty "
+ # given,
+ class spawn_ourptyfork(pexpect.spawn):
+ def _spawn(self, command, args=[], preexec_fn=None,
+ dimensions=None):
+ self.use_native_pty_fork = False
+ pexpect.spawn._spawn(self, command, args, preexec_fn,
+ dimensions)
+
+ # exercise,
+ p = spawn_ourptyfork('cat', echo=False)
+ # verify,
+ p.sendline('abc')
+ p.expect('abc')
+ p.sendeof()
+ p.expect(pexpect.EOF)
+ assert not p.isalive()
+
+ def test_exception_tb(self):
+ " test get_trace() filters away pexpect/__init__.py calls. "
+ p = pexpect.spawn('sleep 1')
+ try:
+ p.expect('BLAH')
+ except pexpect.ExceptionPexpect as e:
+ # get_trace should filter out frames in pexpect's own code
+ tb = e.get_trace()
+ # exercise,
+ assert 'raise ' not in tb
+ assert 'pexpect/__init__.py' not in tb
+ else:
+ assert False, "Should have raised an exception."
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(TestCaseMisc,'test')
Index: third_party/Python/module/pexpect-4.6/tests/test_missing_command.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/test_missing_command.py
+++ third_party/Python/module/pexpect-4.6/tests/test_missing_command.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+import unittest
+from . import PexpectTestCase
+
+class MissingCommandTestCase (PexpectTestCase.PexpectTestCase):
+ def testMissingCommand(self):
+ try:
+ i = pexpect.spawn ('ZXQYQZX')
+ except Exception:
+ pass
+ else:
+ self.fail('Expected an Exception.')
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(MissingCommandTestCase,'test')
+
Index: third_party/Python/module/pexpect-4.6/tests/test_performance.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/test_performance.py
+++ third_party/Python/module/pexpect-4.6/tests/test_performance.py
@@ -0,0 +1,113 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+from __future__ import print_function
+
+import unittest, time, sys
+import platform
+import pexpect
+import re
+from . import PexpectTestCase
+
+# This isn't exactly a unit test, but it fits in nicely with the rest of the tests.
+
+class PerformanceTestCase (PexpectTestCase.PexpectTestCase):
+
+ '''Testing the performance of expect, with emphasis on wading through long
+ inputs. '''
+
+ if sys.version_info[0] >= 3:
+ @staticmethod
+ def _iter_n(n):
+ s = 'for n in range(1, %d+1): print(n)' % n
+ return s.encode('ascii')
+
+ else:
+ @staticmethod
+ def _iter_n(n):
+ return 'for n in range(1, %d+1): print(n)' % n
+
+ def plain_range(self, n):
+ e = pexpect.spawn('python', timeout=100)
+ self.assertEqual(e.expect(b'>>>'), 0)
+ e.sendline(self._iter_n(n))
+ self.assertEqual(e.expect(br'\.{3}'), 0)
+ e.sendline(b'')
+ self.assertEqual(e.expect([b'inquisition', '%d' % n]), 1)
+
+ def window_range(self, n):
+ e = pexpect.spawn('python', timeout=100)
+ self.assertEqual(e.expect(b'>>>'), 0)
+ e.sendline(self._iter_n(n))
+ self.assertEqual(e.expect(r'\.{3}'), 0)
+ e.sendline(b'')
+ self.assertEqual(e.expect([b'inquisition', '%d' % n], searchwindowsize=20), 1)
+
+ def exact_range(self, n):
+ e = pexpect.spawn('python', timeout=100)
+ self.assertEqual(e.expect_exact([b'>>>']), 0)
+ e.sendline(self._iter_n(n))
+ self.assertEqual(e.expect_exact([b'...']), 0)
+ e.sendline(b'')
+ self.assertEqual(e.expect_exact([b'inquisition', '%d' % n],timeout=520), 1)
+
+ def ewin_range(self, n):
+ e = pexpect.spawn('python', timeout=100)
+ self.assertEqual(e.expect_exact([b'>>>']), 0)
+ e.sendline(self._iter_n(n))
+ self.assertEqual(e.expect_exact([b'...']), 0)
+ e.sendline(b'')
+ self.assertEqual(e.expect_exact([b'inquisition', '%d' % n], searchwindowsize=20), 1)
+
+ def faster_range(self, n):
+ e = pexpect.spawn('python', timeout=100)
+ self.assertEqual(e.expect(b'>>>'), 0)
+ e.sendline(('list(range(1, %d+1))' % n).encode('ascii'))
+ self.assertEqual(e.expect([b'inquisition', '%d' % n]), 1)
+
+ def test_100000(self):
+ if platform.python_implementation() == 'PyPy':
+ raise unittest.SkipTest("This test fails on PyPy because of REPL differences")
+ print()
+ start_time = time.time()
+ self.plain_range (100000)
+ print("100000 calls to plain_range:", (time.time() - start_time))
+ start_time = time.time()
+ self.window_range(100000)
+ print("100000 calls to window_range:", (time.time() - start_time))
+ start_time = time.time()
+ self.exact_range (100000)
+ print("100000 calls to exact_range:", (time.time() - start_time))
+ start_time = time.time()
+ self.ewin_range (100000)
+ print("100000 calls to ewin_range:", (time.time() - start_time))
+ start_time = time.time()
+ self.faster_range(100000)
+ print("100000 calls to faster_range:", (time.time() - start_time))
+
+ def test_large_stdout_stream(self):
+ e = pexpect.spawn('openssl rand -base64 {}'.format(1024*1024*25), searchwindowsize=1000)
+ resp = e.expect(['Password:', pexpect.EOF, pexpect.TIMEOUT])
+ assert resp == 1 # index 1 == EOF
+
+if __name__ == "__main__":
+ unittest.main()
+
+suite = unittest.makeSuite(PerformanceTestCase,'test')
Index: third_party/Python/module/pexpect-4.6/tests/test_pickling.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/test_pickling.py
+++ third_party/Python/module/pexpect-4.6/tests/test_pickling.py
@@ -0,0 +1,14 @@
+#!/usr/bin/env python
+import pickle
+import unittest
+
+from pexpect import ExceptionPexpect
+
+class PickleTest(unittest.TestCase):
+ def test_picking(self):
+ e = ExceptionPexpect('Oh noes!')
+ clone = pickle.loads(pickle.dumps(e))
+ self.assertEqual(e.value, clone.value)
+
+if __name__ == '__main__':
+ unittest.main()
Index: third_party/Python/module/pexpect-4.6/tests/test_popen_spawn.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/test_popen_spawn.py
+++ third_party/Python/module/pexpect-4.6/tests/test_popen_spawn.py
@@ -0,0 +1,139 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import unittest
+import subprocess
+
+
+import pexpect
+from pexpect.popen_spawn import PopenSpawn
+from . import PexpectTestCase
+
+
+class ExpectTestCase (PexpectTestCase.PexpectTestCase):
+
+ def test_expect_basic(self):
+ p = PopenSpawn('cat', timeout=5)
+ p.sendline(b'Hello')
+ p.sendline(b'there')
+ p.sendline(b'Mr. Python')
+ p.expect(b'Hello')
+ p.expect(b'there')
+ p.expect(b'Mr. Python')
+ p.sendeof()
+ p.expect(pexpect.EOF)
+
+ def test_expect_exact_basic(self):
+ p = PopenSpawn('cat', timeout=5)
+ p.sendline(b'Hello')
+ p.sendline(b'there')
+ p.sendline(b'Mr. Python')
+ p.expect_exact(b'Hello')
+ p.expect_exact(b'there')
+ p.expect_exact(b'Mr. Python')
+ p.sendeof()
+ p.expect_exact(pexpect.EOF)
+
+ def test_expect(self):
+ the_old_way = subprocess.Popen(args=['ls', '-l', '/bin'],
+ stdout=subprocess.PIPE).communicate()[0].rstrip()
+ p = PopenSpawn('ls -l /bin')
+ the_new_way = b''
+ while 1:
+ i = p.expect([b'\n', pexpect.EOF])
+ the_new_way = the_new_way + p.before
+ if i == 1:
+ break
+ the_new_way += b'\n'
+ the_new_way = the_new_way.rstrip()
+ assert the_old_way == the_new_way, len(the_old_way) - len(the_new_way)
+
+ def test_expect_exact(self):
+ the_old_way = subprocess.Popen(args=['ls', '-l', '/bin'],
+ stdout=subprocess.PIPE).communicate()[0].rstrip()
+ p = PopenSpawn('ls -l /bin')
+ the_new_way = b''
+ while 1:
+ i = p.expect_exact([b'\n', pexpect.EOF])
+ the_new_way = the_new_way + p.before
+ if i == 1:
+ break
+ the_new_way += b'\n'
+ the_new_way = the_new_way.rstrip()
+
+ assert the_old_way == the_new_way, len(the_old_way) - len(the_new_way)
+ p = PopenSpawn('echo hello.?world')
+ i = p.expect_exact(b'.?')
+ self.assertEqual(p.before, b'hello')
+ self.assertEqual(p.after, b'.?')
+
+ def test_expect_eof(self):
+ the_old_way = subprocess.Popen(args=['ls', '-l', '/bin'],
+ stdout=subprocess.PIPE).communicate()[0].rstrip()
+ p = PopenSpawn('ls -l /bin')
+ # This basically tells it to read everything. Same as pexpect.run()
+ # function.
+ p.expect(pexpect.EOF)
+ the_new_way = p.before.rstrip()
+ assert the_old_way == the_new_way, len(the_old_way) - len(the_new_way)
+
+ def test_expect_timeout(self):
+ p = PopenSpawn('cat', timeout=5)
+ p.expect(pexpect.TIMEOUT) # This tells it to wait for timeout.
+ self.assertEqual(p.after, pexpect.TIMEOUT)
+
+ def test_unexpected_eof(self):
+ p = PopenSpawn('ls -l /bin')
+ try:
+ p.expect('_Z_XY_XZ') # Probably never see this in ls output.
+ except pexpect.EOF:
+ pass
+ else:
+ self.fail('Expected an EOF exception.')
+
+ def test_bad_arg(self):
+ p = PopenSpawn('cat')
+ with self.assertRaisesRegexp(TypeError, '.*must be one of'):
+ p.expect(1)
+ with self.assertRaisesRegexp(TypeError, '.*must be one of'):
+ p.expect([1, b'2'])
+ with self.assertRaisesRegexp(TypeError, '.*must be one of'):
+ p.expect_exact(1)
+ with self.assertRaisesRegexp(TypeError, '.*must be one of'):
+ p.expect_exact([1, b'2'])
+
+ def test_timeout_none(self):
+ p = PopenSpawn('echo abcdef', timeout=None)
+ p.expect('abc')
+ p.expect_exact('def')
+ p.expect(pexpect.EOF)
+
+ def test_crlf(self):
+ p = PopenSpawn('echo alpha beta')
+ assert p.read() == b'alpha beta' + p.crlf
+
+ def test_crlf_encoding(self):
+ p = PopenSpawn('echo alpha beta', encoding='utf-8')
+ assert p.read() == 'alpha beta' + p.crlf
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(ExpectTestCase, 'test')
Index: third_party/Python/module/pexpect-4.6/tests/test_pxssh.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/test_pxssh.py
+++ third_party/Python/module/pexpect-4.6/tests/test_pxssh.py
@@ -0,0 +1,120 @@
+#!/usr/bin/env python
+import os
+import tempfile
+import unittest
+
+from pexpect import pxssh
+
+class SSHTestBase(unittest.TestCase):
+ def setUp(self):
+ self.orig_path = os.environ.get('PATH')
+ fakessh_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), 'fakessh'))
+ os.environ['PATH'] = fakessh_dir + \
+ ((os.pathsep + self.orig_path) if self.orig_path else '')
+
+ def tearDown(self):
+ if self.orig_path:
+ os.environ['PATH'] = self.orig_path
+ else:
+ del os.environ['PATH']
+
+class PxsshTestCase(SSHTestBase):
+ def test_fake_ssh(self):
+ ssh = pxssh.pxssh()
+ #ssh.logfile_read = sys.stdout # DEBUG
+ ssh.login('server', 'me', password='s3cret')
+ ssh.sendline('ping')
+ ssh.expect('pong', timeout=10)
+ assert ssh.prompt(timeout=10)
+ ssh.logout()
+
+ def test_wrong_pw(self):
+ ssh = pxssh.pxssh()
+ try:
+ ssh.login('server', 'me', password='wr0ng')
+ except pxssh.ExceptionPxssh:
+ pass
+ else:
+ assert False, 'Password should have been refused'
+
+ def test_failed_set_unique_prompt(self):
+ ssh = pxssh.pxssh()
+ ssh.set_unique_prompt = lambda: False
+ try:
+ ssh.login('server', 'me', password='s3cret',
+ auto_prompt_reset=True)
+ except pxssh.ExceptionPxssh:
+ pass
+ else:
+ assert False, 'should have raised exception, pxssh.ExceptionPxssh'
+
+ def test_connection_refused(self):
+ ssh = pxssh.pxssh()
+ try:
+ ssh.login('noserver', 'me', password='s3cret')
+ except pxssh.ExceptionPxssh:
+ pass
+ else:
+ assert False, 'should have raised exception, pxssh.ExceptionPxssh'
+
+ def test_ssh_tunnel_string(self):
+ ssh = pxssh.pxssh(debug_command_string=True)
+ tunnels = { 'local': ['2424:localhost:22'],'remote': ['2525:localhost:22'],
+ 'dynamic': [8888] }
+ confirmation_strings = 0
+ confirmation_array = ['-R 2525:localhost:22','-L 2424:localhost:22','-D 8888']
+ string = ssh.login('server', 'me', password='s3cret', ssh_tunnels=tunnels)
+ for confirmation in confirmation_array:
+ if confirmation in string:
+ confirmation_strings+=1
+
+ if confirmation_strings!=len(confirmation_array):
+ assert False, 'String generated from tunneling is incorrect.'
+
+ def test_remote_ssh_tunnel_string(self):
+ ssh = pxssh.pxssh(debug_command_string=True)
+ tunnels = { 'local': ['2424:localhost:22'],'remote': ['2525:localhost:22'],
+ 'dynamic': [8888] }
+ confirmation_strings = 0
+ confirmation_array = ['-R 2525:localhost:22','-L 2424:localhost:22','-D 8888']
+ string = ssh.login('server', 'me', password='s3cret', ssh_tunnels=tunnels, spawn_local_ssh=False)
+ for confirmation in confirmation_array:
+ if confirmation in string:
+ confirmation_strings+=1
+
+ if confirmation_strings!=len(confirmation_array):
+ assert False, 'String generated from remote tunneling is incorrect.'
+
+ def test_ssh_config_passing_string(self):
+ ssh = pxssh.pxssh(debug_command_string=True)
+ (temp_file,config_path) = tempfile.mkstemp()
+ string = ssh.login('server', 'me', password='s3cret', spawn_local_ssh=False, ssh_config=config_path)
+ if not '-F '+config_path in string:
+ assert False, 'String generated from SSH config passing is incorrect.'
+
+ def test_ssh_key_string(self):
+ ssh = pxssh.pxssh(debug_command_string=True)
+ confirmation_strings = 0
+ confirmation_array = [' -A']
+ string = ssh.login('server', 'me', password='s3cret', ssh_key=True)
+ for confirmation in confirmation_array:
+ if confirmation in string:
+ confirmation_strings+=1
+
+ if confirmation_strings!=len(confirmation_array):
+ assert False, 'String generated from forcing the SSH agent sock is incorrect.'
+
+ confirmation_strings = 0
+ (temp_file,ssh_key) = tempfile.mkstemp()
+ confirmation_array = [' -i '+ssh_key]
+ string = ssh.login('server', 'me', password='s3cret', ssh_key=ssh_key)
+ for confirmation in confirmation_array:
+ if confirmation in string:
+ confirmation_strings+=1
+
+ if confirmation_strings!=len(confirmation_array):
+ assert False, 'String generated from adding an SSH key is incorrect.'
+
+
+if __name__ == '__main__':
+ unittest.main()
Index: third_party/Python/module/pexpect-4.6/tests/test_replwrap.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/test_replwrap.py
+++ third_party/Python/module/pexpect-4.6/tests/test_replwrap.py
@@ -0,0 +1,114 @@
+import platform
+import unittest
+import re
+import os
+
+import pexpect
+from pexpect import replwrap
+
+skip_pypy = "This test fails on PyPy because of REPL differences"
+
+
+class REPLWrapTestCase(unittest.TestCase):
+ def setUp(self):
+ super(REPLWrapTestCase, self).setUp()
+ self.save_ps1 = os.getenv('PS1', r'\$')
+ self.save_ps2 = os.getenv('PS2', '>')
+ os.putenv('PS1', r'\$')
+ os.putenv('PS2', '>')
+
+ def tearDown(self):
+ super(REPLWrapTestCase, self).tearDown()
+ os.putenv('PS1', self.save_ps1)
+ os.putenv('PS2', self.save_ps2)
+
+ def test_bash(self):
+ bash = replwrap.bash()
+ res = bash.run_command("time")
+ assert 'real' in res, res
+
+ def test_pager_as_cat(self):
+ " PAGER is set to cat, to prevent timeout in ``man sleep``. "
+ bash = replwrap.bash()
+ res = bash.run_command('man sleep', timeout=5)
+ assert 'SLEEP' in res, res
+
+ def test_bash_env(self):
+ """env, which displays PS1=..., should not mess up finding the prompt.
+ """
+ bash = replwrap.bash()
+ res = bash.run_command("env")
+ self.assertIn('PS1', res)
+ res = bash.run_command("echo $HOME")
+ assert res.startswith('/'), res
+
+ def test_long_running_multiline(self):
+ " ensure the default timeout is used for multi-line commands. "
+ bash = replwrap.bash()
+ res = bash.run_command("echo begin\r\nsleep 2\r\necho done")
+ self.assertEqual(res.strip().splitlines(), ['begin', 'done'])
+
+ def test_long_running_continuation(self):
+ " also ensure timeout when used within continuation prompts. "
+ bash = replwrap.bash()
+ # The two extra '\\' in the following expression force a continuation
+ # prompt:
+ # $ echo begin\
+ # + ;
+ # $ sleep 2
+ # $ echo done
+ res = bash.run_command("echo begin\\\n;sleep 2\r\necho done")
+ self.assertEqual(res.strip().splitlines(), ['begin', 'done'])
+
+ def test_multiline(self):
+ bash = replwrap.bash()
+ res = bash.run_command("echo '1 2\n3 4'")
+ self.assertEqual(res.strip().splitlines(), ['1 2', '3 4'])
+
+ # Should raise ValueError if input is incomplete
+ try:
+ bash.run_command("echo '5 6")
+ except ValueError:
+ pass
+ else:
+ assert False, "Didn't raise ValueError for incomplete input"
+
+ # Check that the REPL was reset (SIGINT) after the incomplete input
+ res = bash.run_command("echo '1 2\n3 4'")
+ self.assertEqual(res.strip().splitlines(), ['1 2', '3 4'])
+
+ def test_existing_spawn(self):
+ child = pexpect.spawn("bash", timeout=5, echo=False, encoding='utf-8')
+ repl = replwrap.REPLWrapper(child, re.compile('[$#]'),
+ "PS1='{0}' PS2='{1}' "
+ "PROMPT_COMMAND=''")
+
+ res = repl.run_command("echo $HOME")
+ assert res.startswith('/'), res
+
+ def test_python(self):
+ if platform.python_implementation() == 'PyPy':
+ raise unittest.SkipTest(skip_pypy)
+
+ p = replwrap.python()
+ res = p.run_command('4+7')
+ assert res.strip() == '11'
+
+ res = p.run_command('for a in range(3): print(a)\n')
+ assert res.strip().splitlines() == ['0', '1', '2']
+
+ def test_no_change_prompt(self):
+ if platform.python_implementation() == 'PyPy':
+ raise unittest.SkipTest(skip_pypy)
+
+ child = pexpect.spawn('python', echo=False, timeout=5, encoding='utf-8')
+ # prompt_change=None should mean no prompt change
+ py = replwrap.REPLWrapper(child, u">>> ", prompt_change=None,
+ continuation_prompt=u"... ")
+ assert py.prompt == ">>> "
+
+ res = py.run_command("for a in range(3): print(a)\n")
+ assert res.strip().splitlines() == ['0', '1', '2']
+
+if __name__ == '__main__':
+ unittest.main()
Index: third_party/Python/module/pexpect-4.6/tests/test_repr.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/test_repr.py
+++ third_party/Python/module/pexpect-4.6/tests/test_repr.py
@@ -0,0 +1,37 @@
+""" Test __str__ methods. """
+import pexpect
+
+from . import PexpectTestCase
+
+
+class TestCaseMisc(PexpectTestCase.PexpectTestCase):
+
+ def test_str_spawnu(self):
+ """ Exercise spawnu.__str__() """
+ # given,
+ p = pexpect.spawnu('cat')
+ # exercise,
+ value = str(p)
+ # verify
+ assert isinstance(value, str)
+
+ def test_str_spawn(self):
+ """ Exercise spawn.__str__() """
+ # given,
+ p = pexpect.spawn('cat')
+ # exercise,
+ value = str(p)
+ # verify
+ assert isinstance(value, str)
+
+ def test_str_before_spawn(self):
+ """ Exercise derived spawn.__str__() """
+ # given,
+ child = pexpect.spawn(None, None)
+ child.read_nonblocking = lambda size, timeout: b''
+ try:
+ child.expect('alpha', timeout=0.1)
+ except pexpect.TIMEOUT as e:
+ str(e) # Smoketest
+ else:
+ assert False, 'TIMEOUT exception expected. No exception raised.'
Index: third_party/Python/module/pexpect-4.6/tests/test_run.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/test_run.py
+++ third_party/Python/module/pexpect-4.6/tests/test_run.py
@@ -0,0 +1,191 @@
+#!/usr/bin/env python
+# encoding: utf-8
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+import unittest
+import subprocess
+import tempfile
+import sys
+import os
+from . import PexpectTestCase
+
+unicode_type = str if pexpect.PY3 else unicode
+
+
+def timeout_callback(values):
+ if values["event_count"] > 3:
+ return 1
+ return 0
+
+
+def function_events_callback(values):
+ try:
+ previous_echoed = (values["child_result_list"][-1]
+ .decode().split("\n")[-2].strip())
+ if previous_echoed.endswith("stage-1"):
+ return "echo stage-2\n"
+ elif previous_echoed.endswith("stage-2"):
+ return "echo stage-3\n"
+ elif previous_echoed.endswith("stage-3"):
+ return "exit\n"
+ else:
+ raise Exception("Unexpected output {0}".format(previous_echoed))
+ except IndexError:
+ return "echo stage-1\n"
+
+
+class RunFuncTestCase(PexpectTestCase.PexpectTestCase):
+ runfunc = staticmethod(pexpect.run)
+ cr = b'\r'
+ empty = b''
+ prep_subprocess_out = staticmethod(lambda x: x)
+
+ def setUp(self):
+ fd, self.rcfile = tempfile.mkstemp()
+ os.write(fd, b'PS1=GO: \n')
+ os.close(fd)
+ super(RunFuncTestCase, self).setUp()
+
+ def tearDown(self):
+ os.unlink(self.rcfile)
+ super(RunFuncTestCase, self).tearDown()
+
+ def test_run_exit(self):
+ (data, exitstatus) = self.runfunc('python exit1.py', withexitstatus=1)
+ assert exitstatus == 1, "Exit status of 'python exit1.py' should be 1."
+
+ def test_run(self):
+ the_old_way = subprocess.Popen(
+ args=['uname', '-m', '-n'],
+ stdout=subprocess.PIPE
+ ).communicate()[0].rstrip()
+
+ (the_new_way, exitstatus) = self.runfunc(
+ 'uname -m -n', withexitstatus=1)
+ the_new_way = the_new_way.replace(self.cr, self.empty).rstrip()
+
+ self.assertEqual(self.prep_subprocess_out(the_old_way), the_new_way)
+ self.assertEqual(exitstatus, 0)
+
+ def test_run_callback(self):
+ # TODO it seems like this test could block forever if run fails...
+ events = {pexpect.TIMEOUT: timeout_callback}
+ self.runfunc("cat", timeout=1, events=events)
+
+ def test_run_bad_exitstatus(self):
+ (the_new_way, exitstatus) = self.runfunc(
+ 'ls -l /najoeufhdnzkxjd', withexitstatus=1)
+ assert exitstatus != 0
+
+ def test_run_event_as_string(self):
+ events = [
+ # second match on 'abc', echo 'def'
+ ('abc\r\n.*GO:', 'echo "def"\n'),
+ # final match on 'def': exit
+ ('def\r\n.*GO:', 'exit\n'),
+ # first match on 'GO:' prompt, echo 'abc'
+ ('GO:', 'echo "abc"\n')
+ ]
+
+ (data, exitstatus) = pexpect.run(
+ 'bash --rcfile {0}'.format(self.rcfile),
+ withexitstatus=True,
+ events=events,
+ timeout=10)
+ assert exitstatus == 0
+
+ def test_run_event_as_function(self):
+ events = [
+ ('GO:', function_events_callback)
+ ]
+
+ (data, exitstatus) = pexpect.run(
+ 'bash --rcfile {0}'.format(self.rcfile),
+ withexitstatus=True,
+ events=events,
+ timeout=10)
+ assert exitstatus == 0
+
+ def test_run_event_as_method(self):
+ events = [
+ ('GO:', self._method_events_callback)
+ ]
+
+ (data, exitstatus) = pexpect.run(
+ 'bash --rcfile {0}'.format(self.rcfile),
+ withexitstatus=True,
+ events=events,
+ timeout=10)
+ assert exitstatus == 0
+
+ def test_run_event_typeerror(self):
+ events = [('GO:', -1)]
+ with self.assertRaises(TypeError):
+ pexpect.run('bash --rcfile {0}'.format(self.rcfile),
+ withexitstatus=True,
+ events=events,
+ timeout=10)
+
+ def _method_events_callback(self, values):
+ try:
+ previous_echoed = (values["child_result_list"][-1].decode()
+ .split("\n")[-2].strip())
+ if previous_echoed.endswith("foo1"):
+ return "echo foo2\n"
+ elif previous_echoed.endswith("foo2"):
+ return "echo foo3\n"
+ elif previous_echoed.endswith("foo3"):
+ return "exit\n"
+ else:
+ raise Exception("Unexpected output {0!r}"
+ .format(previous_echoed))
+ except IndexError:
+ return "echo foo1\n"
+
+
+class RunUnicodeFuncTestCase(RunFuncTestCase):
+ runfunc = staticmethod(pexpect.runu)
+ cr = b'\r'.decode('ascii')
+ empty = b''.decode('ascii')
+ prep_subprocess_out = staticmethod(lambda x: x.decode('utf-8', 'replace'))
+
+ def test_run_unicode(self):
+ if pexpect.PY3:
+ char = chr(254) # þ
+ pattern = ''
+ else:
+ char = unichr(254) # analysis:ignore
+ pattern = ''.decode('ascii')
+
+ def callback(values):
+ if values['event_count'] == 0:
+ return char + '\n'
+ else:
+ return True # Stop the child process
+
+ output = pexpect.runu(sys.executable + ' echo_w_prompt.py',
+ env={'PYTHONIOENCODING': 'utf-8'},
+ events={pattern: callback})
+ assert isinstance(output, unicode_type), type(output)
+ assert ('' + char) in output, output
+
+if __name__ == '__main__':
+ unittest.main()
Index: third_party/Python/module/pexpect-4.6/tests/test_run_out_of_pty.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/test_run_out_of_pty.py
+++ third_party/Python/module/pexpect-4.6/tests/test_run_out_of_pty.py
@@ -0,0 +1,51 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+import unittest
+from . import PexpectTestCase
+
+class ExpectTestCase(PexpectTestCase.PexpectTestCase):
+ # This takes too long to run and isn't all that interesting of a test.
+ def OFF_test_run_out_of_pty (self):
+ '''This assumes that the tested platform has < 10000 pty devices.
+ This test currently does not work under Solaris.
+ Under Solaris it runs out of file descriptors first and
+ ld.so starts to barf:
+ ld.so.1: pt_chmod: fatal: /usr/lib/libc.so.1: Too many open files
+ '''
+ plist=[]
+ for count in range (0,10000):
+ try:
+ plist.append (pexpect.spawn('ls -l'))
+ except pexpect.ExceptionPexpect:
+ for c in range (0, count):
+ plist[c].close()
+ return
+ except Exception:
+ err = sys.exc_info()[1]
+ self.fail ('Expected ExceptionPexpect. ' + str(err))
+ self.fail ('Could not run out of pty devices. This may be OK.')
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(ExpectTestCase,'test')
+
Index: third_party/Python/module/pexpect-4.6/tests/test_screen.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/test_screen.py
+++ third_party/Python/module/pexpect-4.6/tests/test_screen.py
@@ -0,0 +1,287 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+import sys
+
+from pexpect import screen
+import unittest
+from . import PexpectTestCase
+
+PY3 = (sys.version_info[0] >= 3)
+
+fill1_target='XXXXXXXXXX\n' + \
+'XOOOOOOOOX\n' + \
+'XO::::::OX\n' + \
+'XO:oooo:OX\n' + \
+'XO:o..o:OX\n' + \
+'XO:o..o:OX\n' + \
+'XO:oooo:OX\n' + \
+'XO::::::OX\n' + \
+'XOOOOOOOOX\n' + \
+'XXXXXXXXXX'
+fill2_target = 'XXXXXXXXXXX\n' + \
+'XOOOOOOOOOX\n' + \
+'XO:::::::OX\n' + \
+'XO:ooooo:OX\n' + \
+'XO:o...o:OX\n' + \
+'XO:o.+.o:OX\n' + \
+'XO:o...o:OX\n' + \
+'XO:ooooo:OX\n' + \
+'XO:::::::OX\n' + \
+'XOOOOOOOOOX\n' + \
+'XXXXXXXXXXX'
+put_target = '\\.3.5.7.9/\n' + \
+'.........2\n' + \
+'3.........\n' + \
+'.........4\n' + \
+'5...\\/....\n' + \
+'..../\\...6\n' + \
+'7.........\n' + \
+'.........8\n' + \
+'9.........\n' + \
+'/2.4.6.8.\\'
+scroll_target = '\\.3.5.7.9/\n' + \
+'\\.3.5.7.9/\n' + \
+'\\.3.5.7.9/\n' + \
+'\\.3.5.7.9/\n' + \
+'5...\\/....\n' + \
+'..../\\...6\n' + \
+'/2.4.6.8.\\\n' + \
+'/2.4.6.8.\\\n' + \
+'/2.4.6.8.\\\n' + \
+'/2.4.6.8.\\'
+insert_target = 'ZXZZZZZZXZ\n' +\
+'.........2\n' +\
+'3.........\n' +\
+'.........4\n' +\
+'Z5...\\/...\n' +\
+'..../Z\\...\n' +\
+'7.........\n' +\
+'.........8\n' +\
+'9.........\n' +\
+'ZZ/2.4.6ZZ'
+get_region_target = ['......', '.\\/...', './\\...', '......']
+
+unicode_box_unicode_result = u'\u2554\u2557\n\u255A\u255D'
+unicode_box_pretty_result = u'''\
++--+
+|\u2554\u2557|
+|\u255A\u255D|
++--+
+'''
+unicode_box_ascii_bytes_result = b'??\n??'
+unicode_box_cp437_bytes_result = b'\xc9\xbb\n\xc8\xbc'
+unicode_box_utf8_bytes_result = b'\xe2\x95\x94\xe2\x95\x97\n\xe2\x95\x9a\xe2\x95\x9d'
+
+class screenTestCase (PexpectTestCase.PexpectTestCase):
+ def make_screen_with_put (self):
+ s = screen.screen(10,10)
+ s.fill ('.')
+ for r in range (1,s.rows + 1):
+ if r % 2:
+ s.put_abs (r, 1, str(r))
+ else:
+ s.put_abs (r, s.cols, str(r))
+ for c in range (1,s.cols + 1):
+ if c % 2:
+ s.put_abs (1, c, str(c))
+ else:
+ s.put_abs (s.rows, c, str(c))
+ s.put_abs(1,1, '\\')
+ s.put_abs(1,s.cols, '/')
+ s.put_abs(s.rows,1,'/')
+ s.put_abs(s.rows, s.cols, '\\')
+ s.put_abs(5,5,'\\')
+ s.put_abs(5,6,'/')
+ s.put_abs(6,5,'/')
+ s.put_abs(6,6,'\\')
+ return s
+
+ def test_fill (self):
+ s = screen.screen (10,10)
+ s.fill_region (10,1,1,10,'X')
+ s.fill_region (2,2,9,9,'O')
+ s.fill_region (8,8,3,3,':')
+ s.fill_region (4,7,7,4,'o')
+ s.fill_region (6,5,5,6,'.')
+ assert str(s) == fill1_target
+
+ s = screen.screen (11,11)
+ s.fill_region (1,1,11,11,'X')
+ s.fill_region (2,2,10,10,'O')
+ s.fill_region (9,9,3,3,':')
+ s.fill_region (4,8,8,4,'o')
+ s.fill_region (7,5,5,7,'.')
+ s.fill_region (6,6,6,6,'+')
+ assert str(s) == fill2_target
+ def test_put (self):
+ s = self.make_screen_with_put()
+ assert str(s) == put_target
+ def test_get_region (self):
+ s = self.make_screen_with_put()
+ r = s.get_region (4,4,7,9)
+ assert r == get_region_target
+
+ def test_cursor_save (self):
+ s = self.make_screen_with_put()
+ s.cursor_home (5,5)
+ c = s.get()
+ s.cursor_save()
+ s.cursor_home()
+ s.cursor_forward()
+ s.cursor_down()
+ s.cursor_unsave()
+ assert s.cur_r == 5 and s.cur_c == 5
+ assert c == s.get()
+ def test_scroll (self):
+ s = self.make_screen_with_put()
+ s.scroll_screen_rows (1,4)
+ s.scroll_down(); s.scroll_down(); s.scroll_down()
+ s.scroll_down(); s.scroll_down(); s.scroll_down()
+ s.scroll_screen_rows (7,10)
+ s.scroll_up(); s.scroll_up(); s.scroll_up()
+ s.scroll_up(); s.scroll_up(); s.scroll_up()
+ assert str(s) == scroll_target
+ def test_insert (self):
+ s = self.make_screen_with_put()
+ s.insert_abs (10,1,'Z')
+ s.insert_abs (1,1,'Z')
+ s.insert_abs (1,1,'Z')
+ s.insert_abs (1,1,'Z')
+ s.insert_abs (1,1,'Z')
+ s.insert_abs (1,1,'Z')
+ s.insert_abs (10,1,'Z')
+ s.insert_abs (1,1,'Z')
+ s.insert_abs (1,1,'Z')
+ s.insert_abs (5,1,'Z')
+ s.insert_abs (6,6,'Z')
+ s.cursor_home (1,1) # Also test relative insert.
+ s.insert ('Z')
+ s.insert ('Z')
+ s.insert ('Z')
+ s.insert ('Z')
+ s.insert_abs (1,8,'X')
+ s.insert_abs (1,2,'X')
+ s.insert_abs (10,9,'Z')
+ s.insert_abs (10,9,'Z')
+ assert str(s) == insert_target
+
+ def make_screen_with_box_unicode(self, *args, **kwargs):
+ '''Creates a screen containing a box drawn using double-line
+ line drawing characters. The characters are fed in as
+ unicode. '''
+ s = screen.screen (2,2,*args,**kwargs)
+ s.put_abs (1,1,u'\u2554')
+ s.put_abs (1,2,u'\u2557')
+ s.put_abs (2,1,u'\u255A')
+ s.put_abs (2,2,u'\u255D')
+ return s
+
+ def make_screen_with_box_cp437(self, *args, **kwargs):
+ '''Creates a screen containing a box drawn using double-line
+ line drawing characters. The characters are fed in as
+ CP437. '''
+ s = screen.screen (2,2,*args,**kwargs)
+ s.put_abs (1,1,b'\xc9')
+ s.put_abs (1,2,b'\xbb')
+ s.put_abs (2,1,b'\xc8')
+ s.put_abs (2,2,b'\xbc')
+ return s
+
+ def make_screen_with_box_utf8(self, *args, **kwargs):
+ '''Creates a screen containing a box drawn using double-line
+ line drawing characters. The characters are fed in as
+ UTF-8. '''
+ s = screen.screen (2,2,*args,**kwargs)
+ s.put_abs (1,1,b'\xe2\x95\x94')
+ s.put_abs (1,2,b'\xe2\x95\x97')
+ s.put_abs (2,1,b'\xe2\x95\x9a')
+ s.put_abs (2,2,b'\xe2\x95\x9d')
+ return s
+
+ def test_unicode_ascii (self):
+ # With the default encoding set to ASCII, we should still be
+ # able to feed in unicode strings and get them back out:
+ s = self.make_screen_with_box_unicode('ascii')
+ if PY3:
+ assert str(s) == unicode_box_unicode_result
+ else:
+ assert unicode(s) == unicode_box_unicode_result
+ # And we should still get something for Python 2 str(), though
+ # it might not be very useful
+ str(s)
+
+ assert s.pretty() == unicode_box_pretty_result
+
+ def test_decoding_errors(self):
+ # With strict error handling, it should reject bytes it can't decode
+ with self.assertRaises(UnicodeDecodeError):
+ self.make_screen_with_box_cp437('ascii', 'strict')
+
+ # replace should turn them into unicode replacement characters, U+FFFD
+ s = self.make_screen_with_box_cp437('ascii', 'replace')
+ expected = u'\ufffd\ufffd\n\ufffd\ufffd'
+ if PY3:
+ assert str(s) == expected
+ else:
+ assert unicode(s) == expected
+
+ def test_unicode_cp437 (self):
+ # Verify decoding from and re-encoding to CP437.
+ s = self.make_screen_with_box_cp437('cp437','strict')
+ if PY3:
+ assert str(s) == unicode_box_unicode_result
+ else:
+ assert unicode(s) == unicode_box_unicode_result
+ assert str(s) == unicode_box_cp437_bytes_result
+ assert s.pretty() == unicode_box_pretty_result
+
+ def test_unicode_utf8 (self):
+ # Verify decoding from and re-encoding to UTF-8.
+ s = self.make_screen_with_box_utf8('utf-8','strict')
+ if PY3:
+ assert str(s) == unicode_box_unicode_result
+ else:
+ assert unicode(s) == unicode_box_unicode_result
+ assert str(s) == unicode_box_utf8_bytes_result
+ assert s.pretty() == unicode_box_pretty_result
+
+ def test_no_bytes(self):
+ s = screen.screen(2, 2, encoding=None)
+ s.put_abs(1, 1, u'A')
+ s.put_abs(2, 2, u'D')
+
+ with self.assertRaises(TypeError):
+ s.put_abs(1, 2, b'B')
+
+ if PY3:
+ assert str(s) == u'A \n D'
+ else:
+ assert unicode(s) == u'A \n D'
+ # This will still work if it's limited to ascii
+ assert str(s) == b'A \n D'
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(screenTestCase,'test')
+
+
Index: third_party/Python/module/pexpect-4.6/tests/test_socket.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/test_socket.py
+++ third_party/Python/module/pexpect-4.6/tests/test_socket.py
@@ -0,0 +1,270 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+from pexpect import fdpexpect
+import unittest
+from . import PexpectTestCase
+import multiprocessing
+import os
+import signal
+import socket
+import time
+import errno
+
+
+class SocketServerError(Exception):
+ pass
+
+
+class ExpectTestCase(PexpectTestCase.PexpectTestCase):
+
+ def setUp(self):
+ print(self.id())
+ PexpectTestCase.PexpectTestCase.setUp(self)
+ self.host = '127.0.0.1'
+ self.port = 49152 + 10000
+ self.motd = b"""\
+------------------------------------------------------------------------------
+* Welcome to the SOCKET UNIT TEST code! *
+------------------------------------------------------------------------------
+* *
+* This unit test code is our best effort at testing the ability of the *
+* pexpect library to handle sockets. We need some text to test buffer size *
+* handling. *
+* *
+* A page is 1024 bytes or 1K. 80 x 24 = 1920. So a standard terminal window *
+* contains more than one page. We actually want more than a page for our *
+* tests. *
+* *
+* This is the twelfth line, and we need 24. So we need a few more paragraphs.*
+* We can keep them short and just put lines between them. *
+* *
+* The 80 x 24 terminal size comes from the ancient past when computers were *
+* only able to display text in cuneiform writing. *
+* *
+* The cunieform writing system used the edge of a reed to make marks on clay *
+* tablets. *
+* *
+* It was the forerunner of the style of handwriting used by doctors to write *
+* prescriptions. Thus the name: pre (before) script (writing) ion (charged *
+* particle). *
+------------------------------------------------------------------------------
+""".replace(b'\n', b'\n\r') + b"\r\n"
+ self.prompt1 = b'Press Return to continue:'
+ self.prompt2 = b'Rate this unit test>'
+ self.prompt3 = b'Press X to exit:'
+ self.enter = b'\r\n'
+ self.exit = b'X\r\n'
+ self.server_up = multiprocessing.Event()
+ self.server_process = multiprocessing.Process(target=self.socket_server, args=(self.server_up,))
+ self.server_process.daemon = True
+ self.server_process.start()
+ counter = 0
+ while not self.server_up.is_set():
+ time.sleep(0.250)
+ counter += 1
+ if counter > (10 / 0.250):
+ raise SocketServerError("Could not start socket server")
+
+ def tearDown(self):
+ os.kill(self.server_process.pid, signal.SIGINT)
+ self.server_process.join(timeout=5.0)
+ PexpectTestCase.PexpectTestCase.tearDown(self)
+
+ def socket_server(self, server_up):
+ sock = None
+ try:
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ sock.bind((self.host, self.port))
+ sock.listen(5)
+ server_up.set()
+ while True:
+ (conn, addr) = sock.accept()
+ conn.send(self.motd)
+ conn.send(self.prompt1)
+ result = conn.recv(1024)
+ if result != self.enter:
+ break
+ conn.send(self.prompt2)
+ result = conn.recv(1024)
+ if result != self.enter:
+ break
+ conn.send(self.prompt3)
+ result = conn.recv(1024)
+ if result.startswith(self.exit[0]):
+ conn.shutdown(socket.SHUT_RDWR)
+ conn.close()
+ except KeyboardInterrupt:
+ pass
+ if sock is not None:
+ try:
+ sock.shutdown(socket.SHUT_RDWR)
+ sock.close()
+ except socket.error:
+ pass
+ exit(0)
+
+ def socket_fn(self, timed_out, all_read):
+ result = 0
+ try:
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ sock.connect((self.host, self.port))
+ session = fdpexpect.fdspawn(sock, timeout=10)
+ # Get all data from server
+ session.read_nonblocking(size=4096)
+ all_read.set()
+ # This read should timeout
+ session.read_nonblocking(size=4096)
+ except pexpect.TIMEOUT:
+ timed_out.set()
+ result = errno.ETIMEDOUT
+ exit(result)
+
+ def test_socket(self):
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ sock.connect((self.host, self.port))
+ session = fdpexpect.fdspawn(sock.fileno(), timeout=10)
+ session.expect(self.prompt1)
+ self.assertEqual(session.before, self.motd)
+ session.send(self.enter)
+ session.expect(self.prompt2)
+ session.send(self.enter)
+ session.expect(self.prompt3)
+ session.send(self.exit)
+ session.expect(pexpect.EOF)
+ self.assertEqual(session.before, b'')
+
+ def test_socket_with_write(self):
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ sock.connect((self.host, self.port))
+ session = fdpexpect.fdspawn(sock.fileno(), timeout=10)
+ session.expect(self.prompt1)
+ self.assertEqual(session.before, self.motd)
+ session.write(self.enter)
+ session.expect(self.prompt2)
+ session.write(self.enter)
+ session.expect(self.prompt3)
+ session.write(self.exit)
+ session.expect(pexpect.EOF)
+ self.assertEqual(session.before, b'')
+
+ def test_not_int(self):
+ with self.assertRaises(pexpect.ExceptionPexpect):
+ session = fdpexpect.fdspawn('bogus', timeout=10)
+
+ def test_not_file_descriptor(self):
+ with self.assertRaises(pexpect.ExceptionPexpect):
+ session = fdpexpect.fdspawn(-1, timeout=10)
+
+ def test_timeout(self):
+ with self.assertRaises(pexpect.TIMEOUT):
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ sock.connect((self.host, self.port))
+ session = fdpexpect.fdspawn(sock, timeout=10)
+ session.expect(b'Bogus response')
+
+ def test_interrupt(self):
+ timed_out = multiprocessing.Event()
+ all_read = multiprocessing.Event()
+ test_proc = multiprocessing.Process(target=self.socket_fn, args=(timed_out, all_read))
+ test_proc.daemon = True
+ test_proc.start()
+ while not all_read.is_set():
+ time.sleep(1.0)
+ os.kill(test_proc.pid, signal.SIGWINCH)
+ while not timed_out.is_set():
+ time.sleep(1.0)
+ test_proc.join(timeout=5.0)
+ self.assertEqual(test_proc.exitcode, errno.ETIMEDOUT)
+
+ def test_multiple_interrupts(self):
+ timed_out = multiprocessing.Event()
+ all_read = multiprocessing.Event()
+ test_proc = multiprocessing.Process(target=self.socket_fn, args=(timed_out, all_read))
+ test_proc.daemon = True
+ test_proc.start()
+ while not all_read.is_set():
+ time.sleep(1.0)
+ while not timed_out.is_set():
+ os.kill(test_proc.pid, signal.SIGWINCH)
+ time.sleep(1.0)
+ test_proc.join(timeout=5.0)
+ self.assertEqual(test_proc.exitcode, errno.ETIMEDOUT)
+
+ def test_maxread(self):
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ sock.connect((self.host, self.port))
+ session = fdpexpect.fdspawn(sock.fileno(), timeout=10)
+ session.maxread = 1100
+ session.expect(self.prompt1)
+ self.assertEqual(session.before, self.motd)
+ session.send(self.enter)
+ session.expect(self.prompt2)
+ session.send(self.enter)
+ session.expect(self.prompt3)
+ session.send(self.exit)
+ session.expect(pexpect.EOF)
+ self.assertEqual(session.before, b'')
+
+ def test_fd_isalive(self):
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ sock.connect((self.host, self.port))
+ session = fdpexpect.fdspawn(sock.fileno(), timeout=10)
+ assert session.isalive()
+ sock.close()
+ assert not session.isalive(), "Should not be alive after close()"
+
+ def test_fd_isalive_poll(self):
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ sock.connect((self.host, self.port))
+ session = fdpexpect.fdspawn(sock.fileno(), timeout=10, use_poll=True)
+ assert session.isalive()
+ sock.close()
+ assert not session.isalive(), "Should not be alive after close()"
+
+ def test_fd_isatty(self):
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ sock.connect((self.host, self.port))
+ session = fdpexpect.fdspawn(sock.fileno(), timeout=10)
+ assert not session.isatty()
+ session.close()
+
+ def test_fd_isatty_poll(self):
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ sock.connect((self.host, self.port))
+ session = fdpexpect.fdspawn(sock.fileno(), timeout=10, use_poll=True)
+ assert not session.isatty()
+ session.close()
+
+ def test_fileobj(self):
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ sock.connect((self.host, self.port))
+ session = fdpexpect.fdspawn(sock, timeout=10) # Should get the fileno from the socket
+ session.expect(self.prompt1)
+ session.close()
+ assert not session.isalive()
+ session.close() # Smoketest - should be able to call this again
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(ExpectTestCase, 'test')
Index: third_party/Python/module/pexpect-4.6/tests/test_timeout_pattern.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/test_timeout_pattern.py
+++ third_party/Python/module/pexpect-4.6/tests/test_timeout_pattern.py
@@ -0,0 +1,92 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+from __future__ import with_statement # bring 'with' stmt to py25
+import pexpect
+import unittest
+from . import PexpectTestCase
+import sys
+
+class Exp_TimeoutTestCase(PexpectTestCase.PexpectTestCase):
+ def test_matches_exp_timeout (self):
+ '''This tests that we can raise and catch TIMEOUT.
+ '''
+ try:
+ raise pexpect.TIMEOUT("TIMEOUT match test")
+ except pexpect.TIMEOUT:
+ pass
+ #print "Correctly caught TIMEOUT when raising TIMEOUT."
+ else:
+ self.fail('TIMEOUT not caught by an except TIMEOUT clause.')
+
+ def test_pattern_printout (self):
+ '''Verify that a TIMEOUT returns the proper patterns it is trying to match against.
+ Make sure it is returning the pattern from the correct call.'''
+ try:
+ p = pexpect.spawn('cat')
+ p.sendline('Hello')
+ p.expect('Hello')
+ p.expect('Goodbye',timeout=5)
+ except pexpect.TIMEOUT:
+ assert p.match_index == None
+ else:
+ self.fail("Did not generate a TIMEOUT exception.")
+
+ def test_exp_timeout_notThrown (self):
+ '''Verify that a TIMEOUT is not thrown when we match what we expect.'''
+ try:
+ p = pexpect.spawn('cat')
+ p.sendline('Hello')
+ p.expect('Hello')
+ except pexpect.TIMEOUT:
+ self.fail("TIMEOUT caught when it shouldn't be raised because we match the proper pattern.")
+
+ def test_stacktraceMunging (self):
+ '''Verify that the stack trace returned with a TIMEOUT instance does not contain references to pexpect.'''
+ try:
+ p = pexpect.spawn('cat')
+ p.sendline('Hello')
+ p.expect('Goodbye',timeout=5)
+ except pexpect.TIMEOUT:
+ err = sys.exc_info()[1]
+ if err.get_trace().count("pexpect/__init__.py") != 0:
+ self.fail("The TIMEOUT get_trace() referenced pexpect.py. "
+ "It should only reference the caller.\n" + err.get_trace())
+
+ def test_correctStackTrace (self):
+ '''Verify that the stack trace returned with a TIMEOUT instance correctly handles function calls.'''
+ def nestedFunction (spawnInstance):
+ spawnInstance.expect("junk", timeout=3)
+
+ try:
+ p = pexpect.spawn('cat')
+ p.sendline('Hello')
+ nestedFunction(p)
+ except pexpect.TIMEOUT:
+ err = sys.exc_info()[1]
+ if err.get_trace().count("nestedFunction") == 0:
+ self.fail("The TIMEOUT get_trace() did not show the call "
+ "to the nestedFunction function.\n" + str(err) + "\n"
+ + err.get_trace())
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(Exp_TimeoutTestCase,'test')
Index: third_party/Python/module/pexpect-4.6/tests/test_unicode.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/test_unicode.py
+++ third_party/Python/module/pexpect-4.6/tests/test_unicode.py
@@ -0,0 +1,187 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+import platform
+import tempfile
+import sys
+import time
+
+import pexpect
+import unittest
+from . import PexpectTestCase
+
+# the program cat(1) may display ^D\x08\x08 when \x04 (EOF, Ctrl-D) is sent
+_CAT_EOF = '^D\x08\x08'
+
+class UnicodeTests(PexpectTestCase.PexpectTestCase):
+ def test_expect_basic (self):
+ p = pexpect.spawnu('cat')
+ p.sendline('Hello')
+ p.sendline('there')
+ p.sendline('Mr. þython') # þ is more like th than p, but never mind
+ p.expect('Hello')
+ p.expect('there')
+ p.expect('Mr. þython')
+ p.sendeof ()
+ p.expect (pexpect.EOF)
+
+ def test_expect_exact_basic (self):
+ p = pexpect.spawnu('cat')
+ p.sendline('Hello')
+ p.sendline('there')
+ p.sendline('Mr. þython')
+ p.expect_exact('Hello')
+ p.expect_exact('there')
+ p.expect_exact('Mr. þython')
+ p.sendeof()
+ p.expect_exact (pexpect.EOF)
+
+ def test_expect_setecho_toggle(self):
+ '''This tests that echo may be toggled off.
+ '''
+ p = pexpect.spawnu('cat', timeout=5)
+ try:
+ self._expect_echo_toggle_off(p)
+ except IOError:
+ if sys.platform.lower().startswith('sunos'):
+ if hasattr(unittest, 'SkipTest'):
+ raise unittest.SkipTest("Not supported on this platform.")
+ return 'skip'
+ raise
+ self._expect_echo_toggle_on(p)
+
+ def test_expect_echo_exact (self):
+ '''Like test_expect_echo(), but using expect_exact().
+ '''
+ p = pexpect.spawnu('cat', timeout=5)
+ p.expect = p.expect_exact
+ self._expect_echo(p)
+
+ def test_expect_setecho_toggle_exact(self):
+ p = pexpect.spawnu('cat', timeout=5)
+ p.expect = p.expect_exact
+ try:
+ self._expect_echo_toggle_off(p)
+ except IOError:
+ if sys.platform.lower().startswith('sunos'):
+ if hasattr(unittest, 'SkipTest'):
+ raise unittest.SkipTest("Not supported on this platform.")
+ return 'skip'
+ raise
+ self._expect_echo_toggle_on(p)
+
+ def _expect_echo (self, p):
+ p.sendline('1234') # Should see this twice (once from tty echo and again from cat).
+ index = p.expect (['1234', 'abcdé', 'wxyz', pexpect.EOF, pexpect.TIMEOUT])
+ assert index == 0, (index, p.before)
+ index = p.expect (['1234', 'abcdé', 'wxyz', pexpect.EOF])
+ assert index == 0, index
+
+ def _expect_echo_toggle_off(self, p):
+ p.setecho(0) # Turn off tty echo
+ p.waitnoecho()
+ p.sendline('abcdé') # Now, should only see this once.
+ p.sendline('wxyz') # Should also be only once.
+ index = p.expect ([pexpect.EOF,pexpect.TIMEOUT, 'abcdé', 'wxyz', '1234'])
+ assert index == 2, index
+ index = p.expect ([pexpect.EOF, 'abcdé', 'wxyz', '7890'])
+ assert index == 2, index
+
+ def _expect_echo_toggle_on(self, p):
+ p.setecho(1) # Turn on tty echo
+ time.sleep(0.2) # there is no waitecho() !
+ p.sendline('7890') # Should see this twice.
+ index = p.expect ([pexpect.EOF, 'abcdé', 'wxyz', '7890'])
+ assert index == 3, index
+ index = p.expect ([pexpect.EOF, 'abcdé', 'wxyz', '7890'])
+ assert index == 3, index
+ p.sendeof()
+
+ def test_log_unicode(self):
+ msg = "abcΩ÷"
+ filename_send = tempfile.mktemp()
+ filename_read = tempfile.mktemp()
+ p = pexpect.spawnu('cat')
+ if platform.python_version_tuple() < ('3', '0', '0'):
+ import codecs
+ def open(fname, mode, **kwargs):
+ if 'newline' in kwargs:
+ del kwargs['newline']
+ return codecs.open(fname, mode, **kwargs)
+ else:
+ import io
+ open = io.open
+
+ p.logfile_send = open(filename_send, 'w', encoding='utf-8')
+ p.logfile_read = open(filename_read, 'w', encoding='utf-8')
+ p.sendline(msg)
+ p.sendeof()
+ p.expect(pexpect.EOF)
+ p.close()
+ p.logfile_send.close()
+ p.logfile_read.close()
+
+ # ensure the 'send' log is correct,
+ with open(filename_send, 'r', encoding='utf-8') as f:
+ self.assertEqual(f.read(), msg + '\n\x04')
+
+ # ensure the 'read' log is correct,
+ with open(filename_read, 'r', encoding='utf-8', newline='') as f:
+ output = f.read().replace(_CAT_EOF, '')
+ self.assertEqual(output, (msg + '\r\n')*2 )
+
+
+ def test_spawn_expect_ascii_unicode(self):
+ # A bytes-based spawn should be able to handle ASCII-only unicode, for
+ # backwards compatibility.
+ p = pexpect.spawn('cat')
+ p.sendline('Camelot')
+ p.expect('Camelot')
+
+ p.sendline('Aargh')
+ p.sendline('Aårgh')
+ p.expect_exact('Aargh')
+
+ p.sendeof()
+ p.expect(pexpect.EOF)
+
+ def test_spawn_send_unicode(self):
+ # A bytes-based spawn should be able to send arbitrary unicode
+ p = pexpect.spawn('cat')
+ p.sendline('3½')
+ p.sendeof()
+ p.expect(pexpect.EOF)
+
+ def test_spawn_utf8_incomplete(self):
+ # This test case ensures correct incremental decoding, which
+ # otherwise fails when the stream inspected by os.read()
+ # does not align exactly at a utf-8 multibyte boundary:
+ # UnicodeDecodeError: 'utf8' codec can't decode byte 0xe2 in
+ # position 0: unexpected end of data
+ p = pexpect.spawnu('cat', maxread=1)
+ p.sendline('▁▂▃▄▅▆▇█')
+ p.sendeof()
+ p.expect('▁▂▃▄▅▆▇█')
+
+ def test_readline_bin_echo(self):
+ # Test using readline() with spawnu objects. pexpect 3.2 had threw
+ # a TypeError when concatenating a bytestring to a unicode type.
+
+ # given,
+ child = pexpect.spawnu('echo', ['input', ])
+
+ # exercise,
+ assert child.readline() == 'input' + child.crlf
+
+ def test_unicode_argv(self):
+ """ Ensure a program can be executed with unicode arguments. """
+ p = pexpect.spawn(u'echo ǝpoɔıun', timeout=5, encoding='utf8')
+ p.expect(u'ǝpoɔıun')
+ p.expect(pexpect.EOF)
+ assert not p.isalive()
+ assert p.exitstatus == 0
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(UnicodeTests, 'test')
Index: third_party/Python/module/pexpect-4.6/tests/test_which.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/test_which.py
+++ third_party/Python/module/pexpect-4.6/tests/test_which.py
@@ -0,0 +1,291 @@
+# -*- coding: utf-8 -*-
+import subprocess
+import tempfile
+import shutil
+import errno
+import os
+
+import pexpect
+from . import PexpectTestCase
+
+import pytest
+
+
+class TestCaseWhich(PexpectTestCase.PexpectTestCase):
+ " Tests for pexpect.which(). "
+
+ def test_which_finds_ls(self):
+ " which() can find ls(1). "
+ exercise = pexpect.which("ls")
+ assert exercise is not None
+ assert exercise.startswith('/')
+
+ def test_path_from_env(self):
+ " executable found from optional env argument "
+ bin_name = 'pexpect-test-path-from-env'
+ tempdir = tempfile.mkdtemp()
+ try:
+ bin_path = os.path.join(tempdir, bin_name)
+ with open(bin_path, 'w') as f:
+ f.write('# test file not to be run')
+ try:
+ os.chmod(bin_path, 0o700)
+ found_path = pexpect.which(bin_name, env={'PATH': tempdir})
+ finally:
+ os.remove(bin_path)
+ self.assertEqual(bin_path, found_path)
+ finally:
+ os.rmdir(tempdir)
+
+ def test_os_defpath_which(self):
+ " which() finds an executable in $PATH and returns its abspath. "
+
+ bin_dir = tempfile.mkdtemp()
+ temp_obj = tempfile.NamedTemporaryFile(
+ suffix=u'.sh', prefix=u'ǝpoɔıun-',
+ dir=bin_dir, delete=False)
+ bin_path = temp_obj.name
+ fname = os.path.basename(temp_obj.name)
+ save_path = os.environ['PATH']
+ save_defpath = os.defpath
+
+ try:
+ # setup
+ os.environ['PATH'] = ''
+ os.defpath = bin_dir
+ with open(bin_path, 'w') as fp:
+ pass
+
+ # given non-executable,
+ os.chmod(bin_path, 0o400)
+
+ # exercise absolute and relative,
+ assert pexpect.which(bin_path) is None
+ assert pexpect.which(fname) is None
+
+ # given executable,
+ os.chmod(bin_path, 0o700)
+
+ # exercise absolute and relative,
+ assert pexpect.which(bin_path) == bin_path
+ assert pexpect.which(fname) == bin_path
+
+ finally:
+ # restore,
+ os.environ['PATH'] = save_path
+ os.defpath = save_defpath
+
+ # destroy scratch files and folders,
+ if os.path.exists(bin_path):
+ os.unlink(bin_path)
+ if os.path.exists(bin_dir):
+ os.rmdir(bin_dir)
+
+ def test_path_search_which(self):
+ " which() finds an executable in $PATH and returns its abspath. "
+ fname = 'gcc'
+ bin_dir = tempfile.mkdtemp()
+ bin_path = os.path.join(bin_dir, fname)
+ save_path = os.environ['PATH']
+ try:
+ # setup
+ os.environ['PATH'] = bin_dir
+ with open(bin_path, 'w') as fp:
+ pass
+
+ # given non-executable,
+ os.chmod(bin_path, 0o400)
+
+ # exercise absolute and relative,
+ assert pexpect.which(bin_path) is None
+ assert pexpect.which(fname) is None
+
+ # given executable,
+ os.chmod(bin_path, 0o700)
+
+ # exercise absolute and relative,
+ assert pexpect.which(bin_path) == bin_path
+ assert pexpect.which(fname) == bin_path
+
+ finally:
+ # restore,
+ os.environ['PATH'] = save_path
+
+ # destroy scratch files and folders,
+ if os.path.exists(bin_path):
+ os.unlink(bin_path)
+ if os.path.exists(bin_dir):
+ os.rmdir(bin_dir)
+
+ def test_which_follows_symlink(self):
+ " which() follows symlinks and returns its path. "
+ fname = 'original'
+ symname = 'extra-crispy'
+ bin_dir = tempfile.mkdtemp()
+ bin_path = os.path.join(bin_dir, fname)
+ sym_path = os.path.join(bin_dir, symname)
+ save_path = os.environ['PATH']
+ try:
+ # setup
+ os.environ['PATH'] = bin_dir
+ with open(bin_path, 'w') as fp:
+ pass
+ os.chmod(bin_path, 0o400)
+ os.symlink(bin_path, sym_path)
+
+ # should not be found because symlink points to non-executable
+ assert pexpect.which(symname) is None
+
+ # but now it should -- because it is executable
+ os.chmod(bin_path, 0o700)
+ assert pexpect.which(symname) == sym_path
+
+ finally:
+ # restore,
+ os.environ['PATH'] = save_path
+
+ # destroy scratch files, symlinks, and folders,
+ if os.path.exists(sym_path):
+ os.unlink(sym_path)
+ if os.path.exists(bin_path):
+ os.unlink(bin_path)
+ if os.path.exists(bin_dir):
+ os.rmdir(bin_dir)
+
+ def test_which_should_not_match_folders(self):
+ " Which does not match folders, even though they are executable. "
+ # make up a path and insert a folder that is 'executable', a naive
+ # implementation might match (previously pexpect versions 3.2 and
+ # sh versions 1.0.8, reported by @lcm337.)
+ fname = 'g++'
+ bin_dir = tempfile.mkdtemp()
+ bin_dir2 = os.path.join(bin_dir, fname)
+ save_path = os.environ['PATH']
+ try:
+ os.environ['PATH'] = bin_dir
+ os.mkdir(bin_dir2, 0o755)
+ # should not be found because it is not executable *file*,
+ # but rather, has the executable bit set, as a good folder
+ # should -- it should not be returned because it fails isdir()
+ exercise = pexpect.which(fname)
+ assert exercise is None
+
+ finally:
+ # restore,
+ os.environ['PATH'] = save_path
+ # destroy scratch folders,
+ for _dir in (bin_dir2, bin_dir,):
+ if os.path.exists(_dir):
+ os.rmdir(_dir)
+
+ def test_which_should_match_other_group_user(self):
+ " which() returns executables by other, group, and user ownership. "
+ # create an executable and test that it is found using which() for
+ # each of the 'other', 'group', and 'user' permission bits.
+ fname = 'g77'
+ bin_dir = tempfile.mkdtemp()
+ bin_path = os.path.join(bin_dir, fname)
+ save_path = os.environ['PATH']
+ try:
+ # setup
+ os.environ['PATH'] = bin_dir
+
+ # an interpreted script requires the ability to read,
+ # whereas a binary program requires only to be executable.
+ #
+ # to gain access to a binary program, we make a copy of
+ # the existing system program echo(1).
+ bin_echo = None
+ for pth in ('/bin/echo', '/usr/bin/echo'):
+ if os.path.exists(pth):
+ bin_echo = pth
+ break
+ bin_which = None
+ for pth in ('/bin/which', '/usr/bin/which'):
+ if os.path.exists(pth):
+ bin_which = pth
+ break
+ if not bin_echo or not bin_which:
+ pytest.skip('needs `echo` and `which` binaries')
+ shutil.copy(bin_echo, bin_path)
+ isroot = os.getuid() == 0
+ for should_match, mode in (
+ # note that although the file may have matching 'group' or
+ # 'other' executable permissions, it is *not* executable
+ # because the current uid is the owner of the file -- which
+ # takes precedence
+ (False, 0o000), # ----------, no
+ (isroot, 0o001), # ---------x, no
+ (isroot, 0o010), # ------x---, no
+ (True, 0o100), # ---x------, yes
+ (False, 0o002), # --------w-, no
+ (False, 0o020), # -----w----, no
+ (False, 0o200), # --w-------, no
+ (isroot, 0o003), # --------wx, no
+ (isroot, 0o030), # -----wx---, no
+ (True, 0o300), # --wx------, yes
+ (False, 0o004), # -------r--, no
+ (False, 0o040), # ----r-----, no
+ (False, 0o400), # -r--------, no
+ (isroot, 0o005), # -------r-x, no
+ (isroot, 0o050), # ----r-x---, no
+ (True, 0o500), # -r-x------, yes
+ (False, 0o006), # -------rw-, no
+ (False, 0o060), # ----rw----, no
+ (False, 0o600), # -rw-------, no
+ (isroot, 0o007), # -------rwx, no
+ (isroot, 0o070), # ----rwx---, no
+ (True, 0o700), # -rwx------, yes
+ (isroot, 0o4001), # ---S-----x, no
+ (isroot, 0o4010), # ---S--x---, no
+ (True, 0o4100), # ---s------, yes
+ (isroot, 0o4003), # ---S----wx, no
+ (isroot, 0o4030), # ---S-wx---, no
+ (True, 0o4300), # --ws------, yes
+ (isroot, 0o2001), # ------S--x, no
+ (isroot, 0o2010), # ------s---, no
+ (True, 0o2100), # ---x--S---, yes
+
+ ):
+ mode_str = '{0:0>4o}'.format(mode)
+
+ # given file mode,
+ os.chmod(bin_path, mode)
+
+ # exercise whether we may execute
+ can_execute = True
+ try:
+ subprocess.Popen(fname).wait() == 0
+ except OSError as err:
+ if err.errno != errno.EACCES:
+ raise
+ # permission denied
+ can_execute = False
+
+ assert should_match == can_execute, (
+ should_match, can_execute, mode_str)
+
+ # exercise whether which(1) would match
+ proc = subprocess.Popen((bin_which, fname),
+ env={'PATH': bin_dir},
+ stdout=subprocess.PIPE)
+ bin_which_match = bool(not proc.wait())
+ assert should_match == bin_which_match, (
+ should_match, bin_which_match, mode_str)
+
+ # finally, exercise pexpect's which(1) matches
+ # the same.
+ pexpect_match = bool(pexpect.which(fname))
+
+ assert should_match == pexpect_match == bin_which_match, (
+ should_match, pexpect_match, bin_which_match, mode_str)
+
+ finally:
+ # restore,
+ os.environ['PATH'] = save_path
+
+ # destroy scratch files and folders,
+ if os.path.exists(bin_path):
+ os.unlink(bin_path)
+ if os.path.exists(bin_dir):
+ os.rmdir(bin_dir)
Index: third_party/Python/module/pexpect-4.6/tests/test_winsize.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/test_winsize.py
+++ third_party/Python/module/pexpect-4.6/tests/test_winsize.py
@@ -0,0 +1,60 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+import unittest
+from . import PexpectTestCase
+import time
+
+class TestCaseWinsize(PexpectTestCase.PexpectTestCase):
+
+ def test_initial_winsize(self):
+ """ Assert initial window dimension size (24, 80). """
+ p = pexpect.spawn('{self.PYTHONBIN} sigwinch_report.py'
+ .format(self=self), timeout=3)
+ # default size by PtyProcess class is 24 rows by 80 columns.
+ p.expect_exact('Initial Size: (24, 80)')
+ p.close()
+
+ def test_initial_winsize_by_dimension(self):
+ """ Assert user-parameter window dimension size is initial. """
+ p = pexpect.spawn('{self.PYTHONBIN} sigwinch_report.py'
+ .format(self=self), timeout=3,
+ dimensions=(40, 100))
+ p.expect_exact('Initial Size: (40, 100)')
+ p.close()
+
+ def test_setwinsize(self):
+ """ Ensure method .setwinsize() sends signal caught by child. """
+ p = pexpect.spawn('{self.PYTHONBIN} sigwinch_report.py'
+ .format(self=self), timeout=3)
+ # Note that we must await the installation of the child process'
+ # signal handler,
+ p.expect_exact('READY')
+ p.setwinsize(19, 84)
+ p.expect_exact('SIGWINCH: (19, 84)')
+ p.close()
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(TestCaseWinsize,'test')
+
+
Index: third_party/Python/module/pexpect-4.6/tests/tetris.data
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/tetris.data
+++ third_party/Python/module/pexpect-4.6/tests/tetris.data
@@ -0,0 +1,3 @@
+[2J
+[24;1H J->LEFT K->ROTATE L->RIGHT SPACE->DROP P->PAUSE Q->QUIT
+[1;28HXX[1;36HXXXXXXXX[1;50HXX[2;28HXX[2;50HXX[3;28HXX[3;50HXX[4;28HXX[4;50HXX[5;28HXX[5;50HXX[6;28HXX[6;50HXX[7;28HXX[7;50HXX[8;28HXX[8;50HXX[9;28HXX[9;50HXX[10;28HXX[10;50HXX[11;28HXX[11;50HXX[12;28HXX[12;50HXX[13;28HXX[13;50HXX[14;28HXX[14;50HXX[15;28HXX[15;50HXX[16;28HXX[16;50HXX[17;28HXX[17;50HXX[18;28HXX[18;50HXX[19;28HXX[19;50HXX[20;28HXX[20;50HXX[21;28HXXXXXXXXXXXXXXXXXXXXXXXX[1;36H [2;36HXXXXXXXX[21;50HXX[2;36H [3;36HXXXXXXXX[21;50HXX[3;36H [4;36HXXXXXXXX[21;50HXX[4;36H [5;36HXXXXXXXX[21;50HXX[5;34HXX[5;42H [21;50HXX[5;34H [6;34HXXXXXXXX[21;50HXX[6;32HXX[6;40H [21;50HXX[6;30HXX[6;38H [21;50HXX[6;30H [7;30HXXXXXXXX[21;50HXX[21;50HXX[21;50HXX[21;50HXX[7;30H [8;30HXXXXXXXX[21;50HXX[8;30H [20;30HXXXXXXXX[21;50HXX[1;36HXXXXXX[2;36HXX[21;50HXX[1;36H [2;38HXXXX[3;36HXX[21;50HXX[2;36H [2;42HXX[3;36H XX[21;50HXX[2;38H [3;40HXXXX[4;38HXX[21;50HXX[3;38H [3;44HXX[4;38H XX[21;50HXX[3;40H [3;46HXX[4;40H XX[21;50HXX[3;42H [3;48HXX[4;42H XX[21;50HXX[21;50HXX[21;50HXX[21;50HXX[21;50HXX[21;50HXX[21;50HXX[3;44H [4;46HXXXX[5;44HXX[21;50HXX[4;44H [5;46HXXXX[6;44HXX[21;50HXX[5;44H [6;44H [19;44HXXXXXX[20;44HXX[21;50HXX[1;36HXXXXXX[2;36HXX[21;50HXX[1;36H [2;38HXXXX[3;36HXX[21;50HXX[2;36H [2;42HXX[3;36H XX[21;50HXX[2;38H [2;44HXX[3;38H XX[21;50HXX[2;40H [3;42HXXXX[4;40HXX[21;50HXX[2;42HXX[3;40H [3;44H [4;40H XXXX[21;50HXX[2;42H XX[3;40HXX[3;44HXX[4;42H [21;50HXX[2;44H [3;40H [4;40HXXXXXX[21;50HXX[3;44H [4;40H [17;44HXX[18;40HXXXXXX[21;50HXX[1;36HXXXX[21;50HXX[1;36H [1;40HXX[2;36HXXXX[21;50HXX[1;36HXX[1;40H [2;34HXX[2;38H [21;50HXX[1;36H [2;34H [2;38HXX[3;34HXXXX[21;50HXX[2;34HXX[2;38H [3;32HXX[3;36H [21;50HXX[2;32HXX[2;36H [3;30HXX[3;34H [21;50HXX[21;50HXX[2;32H [3;30H [3;34HXX[4;30HXXXX[21;50HXX[21;50HXX[3;32H [4;30H [18;32HXXXX[19;30HXXXX[21;50HXX[1;36HXXXXXX[2;36HXX[21;50HXX[1;36H [1;42HXX[2;36H XX[21;50HXX[1;38H [2;40HXXXX[3;38HXX[21;50HXX[2;38H [2;44HXX[3;38H XX[21;50HXX[2;40H [2;46HXX[3;40H XX[21;50HXX[2;42H [2;48HXX[3;42H XX[21;50HXX[2;44H [3;46HXXXX[4;44HXX[21;50HXX[21;50HXX[21;50HXX[3;44H [4;44H [15;44HXXXXXX[16;44HXX[21;50HXX[1;36HXXXXXXXX[21;50HXX[1;34HXX[1;42H [21;50HXX[1;34H [2;34HXXXXXXXX[21;50HXX[2;32HXX[2;40H [21;50HXX[2;30HXX[2;38H [21;50HXX[21;50HXX[21;50HXX[21;50HXX[21;50HXX[2;30H [3;30HXXXXXXXX[21;50HXX[3;30H [17;30HXXXXXXXX[21;50HXX[1;38HXXXX[21;50HXX[1;38H [16;36HXXXX[17;38HXXXX[21;50HXX[21;50HXX[1;36HXXXX[21;50HXX[1;36H [1;40HXX[21;50HXX[2;38HXXXX[21;50HXX[1;38H [1;42HXX[2;38H [2;42HXX[21;50HXX[1;40H [1;44HXX[2;40H [2;44HXX[21;50HXX[1;42H [1;46HXX[2;42H [2;46HXX[21;50HXX[1;44H [3;44HXXXX[21;50HXX[2;44H [3;44H [13;44HXXXX[14;44HXXXX[21;50HXX[1;36HXXXXXX[2;40HXX[21;50HXX[1;34HXX[1;40H [2;38HXX [21;50HXX[1;34H [2;34HXXXX[3;38HXX[21;50HXX[2;32HXX[2;38H [3;36HXX [21;50HXX[2;30HXX[2;36H [3;34HXX [21;50HXX[21;50HXX[21;50HXX[21;50HXX[2;30H [3;34H [15;30HXXXXXX[16;34HXX[21;50HXX[1;36HXXXXXXXX[21;50HXX[1;36H [1;44HXX[21;50HXX[1;38H [2;38HXXXXXXXX[21;50HXX[1;40HXX[2;38H [2;42H [3;40HXX[4;40HXX[21;50HXX[1;40H [5;40HXX[21;50HXX[2;40H [3;38HXX[3;42HXXXX[4;40H [5;40H [21;50HXX[2;40HXX[3;38H [3;42H [4;40HXX[5;40HXX[21;50HXX[2;40H [6;40HXX[21;50HXX[3;40H [4;40H [5;40H [6;40H [13;40HXX[14;40HXX[15;40HXX[16;40HXX[21;50HXX[1;36HXXXXXX[2;38HXX[21;50HXX[1;34HXX[1;40H [2;36HXX [21;50HXX[1;32HXX[1;38H [2;34HXX [21;50HXX[1;32H [21;50HXX[1;36H [2;36HXX[3;34HXX[21;50HXX[1;32HXX [2;32HXX[2;36H [3;32HXX [21;50HXX[2;30HXX[3;32H [21;50HXX[1;32H [2;30H [2;34H [3;30HXXXXXX[21;50HXX[2;32H [3;30H [13;32HXX[14;30HXXXXXX[21;50HXX[1;36HXXXXXXXX[21;50HXX[1;36H [1;44HXX[21;50HXX[1;38H [1;42H [2;40HXX[3;40HXX[21;50HXX[1;40H XX[2;40H XX[3;40H XX[21;50HXX[4;42HXX[21;50HXX[1;42H [2;40HXX[2;44HXXXX[3;42H [4;42H [21;50HXX[2;40H [2;48HXX[21;50HXX[1;44HXX[2;42H [2;46H [3;44HXX[4;44HXX[21;50HXX[1;44H [5;44HXX[21;50HXX[2;44H [3;44H [4;44H [5;44H [9;44HXX[10;44HXX[11;44HXX[12;44HXX[21;50HXX[1;36HXXXXXX[2;36HXX[21;50HXX[1;36H [1;40H [2;36H XXXX[21;50HXX[1;36HXX [2;36HXX[2;40H [21;50HXX[1;34HXX[1;38HXX[2;36H [21;50HXX[1;34H [2;34HXXXXXX[21;50HXX[1;36HXX [2;32HXX[2;38H [21;50HXX[1;32HXXXX [2;32H [2;36H [3;34HXX[21;50HXX[1;30HXX[1;34H [2;32HXX [3;32HXX [21;50HXX[1;30H [2;30HXX[4;32HXX[21;50HXX[2;30H [3;32H [4;32H [10;30HXXXX[11;32HXX[12;32HXX[21;50HXX[1;36HXXXXXX[2;40HXX[21;50HXX[1;36H [1;40H [2;38HXX [21;50HXX[1;36HXX[1;40HXX[2;38H [21;50HXX[1;38H [2;36HXXXXXX[21;50HXX[1;36H XX[2;36H [2;40H [3;36HXXXX[21;50HXX[1;38H [2;38H [3;36H [13;38HXX[14;38HXX[15;36HXXXX[21;50HXX[1;36HXXXXXX[2;36HXX[21;50HXX[1;36H [1;42HXX[2;36H XX[21;50HXX[1;38H [2;40HXXXX[3;38HXX[21;50HXX[1;40HXX[2;38H [2;42H [3;38H XXXX[21;50HXX[1;40H XX[2;40H XX[3;40H [3;44HXX[21;50HXX[1;42H XX[2;40HXX[2;44HXX[3;42H [21;50HXX[1;44H XX[2;40H [2;46HXX[21;50HXX[1;46H [2;42H [3;42HXXXXXX[21;50HXX[2;42HXXXX [3;42H [3;46H [4;44HXX[21;50HXX[2;42H [3;44H [4;44H [6;42HXXXX[7;44HXX[8;44HXX[21;50HXX[1;38HXXXX[21;50HXX[1;36HXX[1;40H [2;36HXX[21;50HXX[1;34HXX[1;38H [2;34HXX [21;50HXX[1;34H [2;36HXX[3;34HXX[21;50HXX[1;34HXX[2;34H [2;38HXX[3;34H [21;50HXX[1;32HXX[1;36H [2;34HXX[2;38H [21;50HXX[1;32H [2;32HXX[2;36H [3;32HXX[21;50HXX[1;32HXX [2;30HXX[2;34H [3;30HXX [21;50HXX[1;32H [2;30H [3;32HXX[4;30HXX[21;50HXX[2;32H [3;30H [4;30H [7;32HXX[8;30HXXXX[9;30HXX[21;50HXX[1;36HXXXX[21;50HXX[21;50HXX[1;36H [1;40HXX[21;50HXX[21;50HXX[2;38HXXXX[21;50HXX[1;38H [1;42HXX[2;38H [2;42HXX[21;50HXX[21;50HXX[1;40H [1;44HXX[2;40H [2;44HXX[21;50HXX[21;50HXX[1;42H [3;42HXXXX[21;50HXX[2;42H [3;42H [4;42HXXXX[5;42HXXXX[21;50HXX[1;36HXXXX[21;50HXX[1;36H [1;40HXX[2;40HXX[21;50HXX[1;36HXX[1;40H [2;40H [21;50HXX[1;36H [1;40HXX[2;40HXX[21;50HXX[1;40H [2;38HXX[3;40HXX[21;50HXX[1;38H [2;38H [3;40H [10;38HXX[11;38HXXXX[12;40HXX[21;50HXX[1;36HXXXXXX[2;40HXX[21;50HXX[1;36H [2;40H [9;36HXXXXXX[10;40HXX[21;50HXX[21;50HXX[1;38HXXXX[21;50HXX[1;36HXX[1;40H [2;36HXX[21;50HXX[1;34HXX[1;38H [2;34HXX [21;50HXX[1;34H [2;36HXX[3;34HXX[21;50HXX[1;34HXX[2;34H [2;38HXX[3;34H [21;50HXX[1;32HXX[1;36H [2;34HXX[2;38H [21;50HXX[1;32H [2;34H [6;32HXXXX[7;34HXXXX[21;50HXX[1;36HXXXXXX[2;40HXX[21;50HXX[1;36H [1;42HXX[2;40H XX[21;50HXX[1;38H [1;42H [2;40HXX [21;50HXX[1;40H XX[2;40H XX[21;50HXX[1;40HXX[1;44HXX[2;42H [21;50HXX[1;42H [2;40HXXXXXX[21;50HXX[1;40H XX[2;40H [2;46HXX[21;50HXX[1;42H XX[2;42H [2;46H [3;42HXXXX[21;50HXX[21;50HXX[1;38HXXXX[21;50HXX[1;36HXX[1;40H [2;36HXX[21;50HXX[1;36H [2;38HXX[3;36HXX[21;50HXX[1;36HXX [2;34HXX[2;38H [3;34HXX [21;50HXX[1;34HXX[2;34H [2;38HXX[3;34H [21;50HXX[1;32HXX[1;36H [2;34HXX[2;38H [21;50HXX[1;32H [2;32HXX[2;36H [3;32HXX[21;50HXX[1;34H [2;32H [3;34HXX[4;32HXX[21;50HXX[2;32HXX [3;30HXX[3;34H [4;30HXX [21;50HXX[2;32H [3;30H [4;30H XX[5;30HXXXX[6;30HXX[21;50HXX[1;36HXXXXXX[2;40HXX[21;50HXX[1;36H [1;42HXX[2;40H XX[21;50HXX[1;38H [1;42H [2;40HXX [21;50HXX[1;40H XX[2;40H XX[21;50HXX[21;50HXX[1;38HXXXX[21;50HXX[21;50HXX[1;36HXX[1;40H [2;36HXX[21;50HXX[1;36H [2;36H [4;38HXX[5;36HXXXX[6;36HXX[21;50HXX[1;36HXXXX[21;50HXX[21;50HXX[1;34HXX[1;38H [21;50HXX[2;34HXXXX[21;50HXX[21;50HXX[1;32HXX[1;36H [2;32HXX[2;36H [21;50HXX[21;50HXX[1;30HXX[1;34H [2;30HXX[2;34H [21;50HXX[1;30H [3;30HXXXX[21;50HXX[21;50HXX[1;36HXXXX[21;50HXX[1;36H [1;40HXX[21;50HXX[21;50HXX[21;50HXX[21;50HXX[2;38HXXXX[21;50HXX[21;50HXX[21;50HXX[21;50HXX[21;50HXX[1;38H [3;38HXXXX[21;50HXX[21;50HXX[21;50HXX[21;50HXX[21;50HXX
Index: third_party/Python/module/pexpect-4.6/tests/ticker.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/ticker.py
+++ third_party/Python/module/pexpect-4.6/tests/ticker.py
@@ -0,0 +1,28 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+import time, sys
+
+for i in range(5):
+ print "tick"
+ time.sleep(1)
+
+sys.exit(0)
Index: third_party/Python/module/pexpect-4.6/tests/torturet.vt
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/torturet.vt
+++ third_party/Python/module/pexpect-4.6/tests/torturet.vt
@@ -0,0 +1,61 @@
+\<>[H[1;2;3;4qPrEM1\[?4h[0m
+[H[J[7m#6(0a`opqrs`(B This is the (0`srqpo`a(B[1m
+#3VT100 series Torture Test Demonstration.
+#4VT100 series Torture Test Demonstration.
+#6[1;5m Watch the blinking lights [4;24r[0m
+[0q[1q[0q[2q[0q[3q[0q[4q[0q
+[0q[1q[0q[2q[0q[3q[0q[4q[0q
+[0q[1q[0q[2q[0q[3q[0q[4q[0q
+PrEM0\[4;1H[J[24;1H
+
+This file is a VT100-series Torture Test. It demonstrates all the visual
+attributes of the VT100 terminal.
+
+The top line is double-width/single-height with inverse-video line-drawing
+characters. The 2nd and 3rd lines are double-width/double-height in bold
+inverse video. They also show the limited scrolling region.
+
+The remaining lines will show NORMAL, BOLD, BLINK, INVERSE, and all 16
+combinations of those 4 attributes. They show that there is a difference
+between an underscore character and the underline attribute, and that
+lower-case decenders go below the underline.
+
+A window pane is drawn in the lower right to show how the line-drawing set
+can be used. At the lower left is the character set double-wide/double-high
+to show the dot-matrix used. Upper-case characters are 8 by 7 in a 10 by 10
+character cell, with 1 blank row on top and 2 on the bottom. The underline
+attribute uses the first bottom blank row, lower-case decenders use both.
+
+
+
+[0mThis is a normal line __________________________________________________y_
+[1mThis is a bold line (normal unless the Advanced Video Option is installed)
+[0;4mThis line is underlined _ " " " " " " _y_
+[0;5mThis is a blinking line _ " " " " " " _y_
+[0;7mThis is inverse video _ (underlined if no AVO and cursor is underline) _y_
+[0mNormal gjpqy [4mUnderline[0;0m [5m Blink [4mUnderline+Blink gjpqy[0m
+[1mBold gjpqy [4mUnderline[0;1m [5m Blink [4mUnderline+Blink gjpqy[0m
+[7mInverse [4mUnderline[0;7m [5m Blink [4mUnderline+Blink[0;7m
+[1mBold+Inverse [4mUnderline[0;1;7m [5m Blink [4mUnderline+Blink[0m
+PrEM1\[A
+#6This is double [1mwidth[0m
+#3This is double [1mheight[0m
+#4This is double [1mheight[0m
+#6[7;4m_[0;7mABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ioy
+#3[7;4m_[0;7mABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ioy
+#4[7;4m_[0;7mABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ioy[3A
+[0m[CA[CC[CE[CG[CI[CK[CM[CO[CQ[CS[CU[CW[CY[C0[C2[C4[C6[C8[Ci[Cy
+[4m_[0m[CB[CD[CF[CH[CJ[CL[CN[CP[CR[CT[CV[CX[CZ[C1[C3[C5[C7[C9[Co
+[4m_[0m[CB[CD[CF[CH[CJ[CL[CN[CP[CR[CT[CV[CX[CZ[C1[C3[C5[C7[C9[Co
+(0#6[7m`abcdefghijklmnopqrstuvwxyz{|}~[0m lqwqk
+#3[7m`abcdefghijklmnopqrstuvwxyz{|}~[0m tqnqu
+#4[7m`abcdefghijklmnopqrstuvwxyz{|}~[0m tqnqu[3A[0m
+[Ca[Cc[Ce[Cg[Ci[Ck[Cm[Co[Cq[Cs[Cu[Cw[Cy[C{[C}
+`[Cb[Cd[Cf[Ch[Cj[Cl[Cn[Cp[Cr[Ct[Cv[Cx[Cz[C|[C~
+`[Cb[Cd[Cf[Ch[Cj[Cl[Cn[Cp[Cr[Ct[Cv[Cx[Cz[C|[C~(B
+#6[7m`abcdefghijklmnopqrstuvwxyz{|}~(0[0m mqvqj[A(B
+[0m[Ca[Cc[Ce[Cg[Ci[Ck[Cm[Co[Cq[Cs[Cu[Cw[Cy[C{[C}
+PrEM0\ $PrEM0 works on GIGI [A[1;7m
+ This test created by Joe Smith, 8-May-85 [0m
+[1;r[22;1H
+
Index: third_party/Python/module/pexpect-4.6/tests/utils.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tests/utils.py
+++ third_party/Python/module/pexpect-4.6/tests/utils.py
@@ -0,0 +1,7 @@
+import os
+
+def no_coverage_env():
+ "Return a copy of os.environ that won't trigger coverage measurement."
+ env = os.environ.copy()
+ env.pop('COV_CORE_SOURCE', None)
+ return env
\ No newline at end of file
Index: third_party/Python/module/pexpect-4.6/tools/display-fpathconf.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tools/display-fpathconf.py
+++ third_party/Python/module/pexpect-4.6/tools/display-fpathconf.py
@@ -0,0 +1,41 @@
+#!/usr/bin/env python
+"""Displays os.fpathconf values related to terminals. """
+from __future__ import print_function
+import sys
+import os
+
+
+def display_fpathconf():
+ DISP_VALUES = (
+ ('PC_MAX_CANON', ('Max no. of bytes in a '
+ 'terminal canonical input line.')),
+ ('PC_MAX_INPUT', ('Max no. of bytes for which '
+ 'space is available in a terminal input queue.')),
+ ('PC_PIPE_BUF', ('Max no. of bytes which will '
+ 'be written atomically to a pipe.')),
+ ('PC_VDISABLE', 'Terminal character disabling value.')
+ )
+ FMT = '{name:<13} {value:<5} {description}'
+
+ # column header
+ print(FMT.format(name='name', value='value', description='description'))
+ print(FMT.format(name=('-' * 13), value=('-' * 5), description=('-' * 11)))
+
+ fd = sys.stdin.fileno()
+ for name, description in DISP_VALUES:
+ key = os.pathconf_names.get(name, None)
+ if key is None:
+ value = 'UNDEF'
+ else:
+ try:
+ value = os.fpathconf(fd, name)
+ except OSError as err:
+ value = 'OSErrno {0.errno}'.format(err)
+ if name == 'PC_VDISABLE':
+ value = hex(value)
+ print(FMT.format(name=name, value=value, description=description))
+ print()
+
+
+if __name__ == '__main__':
+ display_fpathconf()
Index: third_party/Python/module/pexpect-4.6/tools/display-maxcanon.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tools/display-maxcanon.py
+++ third_party/Python/module/pexpect-4.6/tools/display-maxcanon.py
@@ -0,0 +1,80 @@
+#!/usr/bin/env python
+"""
+This tool uses pexpect to test expected Canonical mode length.
+
+All systems use the value of MAX_CANON which can be found using
+fpathconf(3) value PC_MAX_CANON -- with the exception of Linux
+and FreeBSD.
+
+Linux, though defining a value of 255, actually honors the value
+of 4096 from linux kernel include file tty.h definition
+N_TTY_BUF_SIZE.
+
+Linux also does not honor IMAXBEL. termios(3) states, "Linux does not
+implement this bit, and acts as if it is always set." Although these
+tests ensure it is enabled, this is a non-op for Linux.
+
+FreeBSD supports neither, and instead uses a fraction (1/5) of the tty
+speed which is always 9600. Therefor, the maximum limited input line
+length is 9600 / 5 = 1920.
+
+These tests only ensure the correctness of the behavior described by
+the sendline() docstring -- the values listed there, and above should
+be equal to the output of the given OS described, but no promises!
+"""
+# std import
+from __future__ import print_function
+import sys
+import os
+
+
+def detect_maxcanon():
+ import pexpect
+ bashrc = os.path.join(
+ # re-use pexpect/replwrap.py's bashrc file,
+ os.path.dirname(__file__), os.path.pardir, 'pexpect', 'bashrc.sh')
+
+ child = pexpect.spawn('bash', ['--rcfile', bashrc],
+ echo=True, encoding='utf8', timeout=3)
+
+ child.sendline(u'echo -n READY_; echo GO')
+ child.expect_exact(u'READY_GO')
+
+ child.sendline(u'stty icanon imaxbel erase ^H; echo -n retval: $?')
+ child.expect_exact(u'retval: 0')
+
+ child.sendline(u'echo -n GO_; echo AGAIN')
+ child.expect_exact(u'GO_AGAIN')
+ child.sendline(u'cat')
+
+ child.delaybeforesend = 0
+
+ column, blocksize = 0, 64
+ ch_marker = u'_'
+
+ print('auto-detecting MAX_CANON: ', end='')
+ sys.stdout.flush()
+
+ while True:
+ child.send(ch_marker * blocksize)
+ result = child.expect([ch_marker * blocksize, u'\a'])
+ if result == 0:
+ # entire block fit without emitting bel
+ column += blocksize
+ elif result == 1:
+ # an '\a' was emitted, count the number of ch_markers
+ # found since last blocksize, determining our MAX_CANON
+ column += child.before.count(ch_marker)
+ break
+ print(column)
+
+if __name__ == '__main__':
+ try:
+ detect_maxcanon()
+ except ImportError:
+ # we'd like to use this with CI -- but until we integrate
+ # with tox, we can't determine a period in testing when
+ # the pexpect module has been installed
+ print('warning: pexpect not in module path, MAX_CANON '
+ 'could not be determined by systems test.',
+ file=sys.stderr)
Index: third_party/Python/module/pexpect-4.6/tools/display-sighandlers.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tools/display-sighandlers.py
+++ third_party/Python/module/pexpect-4.6/tools/display-sighandlers.py
@@ -0,0 +1,24 @@
+#!/usr/bin/env python
+# Displays all signals, their values, and their handlers.
+from __future__ import print_function
+import signal
+FMT = '{name:<10} {value:<5} {description}'
+
+# header
+print(FMT.format(name='name', value='value', description='description'))
+print('-' * (33))
+
+for name, value in [(signal_name, getattr(signal, signal_name))
+ for signal_name in dir(signal)
+ if signal_name.startswith('SIG')
+ and not signal_name.startswith('SIG_')]:
+ try:
+ handler = signal.getsignal(value)
+ except ValueError:
+ # FreeBSD: signal number out of range
+ handler = 'out of range'
+ description = {
+ signal.SIG_IGN: "ignored(SIG_IGN)",
+ signal.SIG_DFL: "default(SIG_DFL)"
+ }.get(handler, handler)
+ print(FMT.format(name=name, value=value, description=description))
Index: third_party/Python/module/pexpect-4.6/tools/display-terminalinfo.py
===================================================================
--- third_party/Python/module/pexpect-4.6/tools/display-terminalinfo.py
+++ third_party/Python/module/pexpect-4.6/tools/display-terminalinfo.py
@@ -0,0 +1,212 @@
+#!/usr/bin/env python
+""" Display known information about our terminal. """
+from __future__ import print_function
+import termios
+import locale
+import sys
+import os
+
+BITMAP_IFLAG = {
+ 'IGNBRK': 'ignore BREAK condition',
+ 'BRKINT': 'map BREAK to SIGINTR',
+ 'IGNPAR': 'ignore (discard) parity errors',
+ 'PARMRK': 'mark parity and framing errors',
+ 'INPCK': 'enable checking of parity errors',
+ 'ISTRIP': 'strip 8th bit off chars',
+ 'INLCR': 'map NL into CR',
+ 'IGNCR': 'ignore CR',
+ 'ICRNL': 'map CR to NL (ala CRMOD)',
+ 'IXON': 'enable output flow control',
+ 'IXOFF': 'enable input flow control',
+ 'IXANY': 'any char will restart after stop',
+ 'IMAXBEL': 'ring bell on input queue full',
+ 'IUCLC': 'translate upper case to lower case',
+}
+
+BITMAP_OFLAG = {
+ 'OPOST': 'enable following output processing',
+ 'ONLCR': 'map NL to CR-NL (ala CRMOD)',
+ 'OXTABS': 'expand tabs to spaces',
+ 'ONOEOT': 'discard EOT\'s `^D\' on output)',
+ 'OCRNL': 'map CR to NL',
+ 'OLCUC': 'translate lower case to upper case',
+ 'ONOCR': 'No CR output at column 0',
+ 'ONLRET': 'NL performs CR function',
+}
+
+BITMAP_CFLAG = {
+ 'CSIZE': 'character size mask',
+ 'CS5': '5 bits (pseudo)',
+ 'CS6': '6 bits',
+ 'CS7': '7 bits',
+ 'CS8': '8 bits',
+ 'CSTOPB': 'send 2 stop bits',
+ 'CREAD': 'enable receiver',
+ 'PARENB': 'parity enable',
+ 'PARODD': 'odd parity, else even',
+ 'HUPCL': 'hang up on last close',
+ 'CLOCAL': 'ignore modem status lines',
+ 'CCTS_OFLOW': 'CTS flow control of output',
+ 'CRTSCTS': 'same as CCTS_OFLOW',
+ 'CRTS_IFLOW': 'RTS flow control of input',
+ 'MDMBUF': 'flow control output via Carrier',
+}
+
+BITMAP_LFLAG = {
+ 'ECHOKE': 'visual erase for line kill',
+ 'ECHOE': 'visually erase chars',
+ 'ECHO': 'enable echoing',
+ 'ECHONL': 'echo NL even if ECHO is off',
+ 'ECHOPRT': 'visual erase mode for hardcopy',
+ 'ECHOCTL': 'echo control chars as ^(Char)',
+ 'ISIG': 'enable signals INTR, QUIT, [D]SUSP',
+ 'ICANON': 'canonicalize input lines',
+ 'ALTWERASE': 'use alternate WERASE algorithm',
+ 'IEXTEN': 'enable DISCARD and LNEXT',
+ 'EXTPROC': 'external processing',
+ 'TOSTOP': 'stop background jobs from output',
+ 'FLUSHO': 'output being flushed (state)',
+ 'NOKERNINFO': 'no kernel output from VSTATUS',
+ 'PENDIN': 'XXX retype pending input (state)',
+ 'NOFLSH': 'don\'t flush after interrupt',
+}
+
+CTLCHAR_INDEX = {
+ 'VEOF': 'EOF',
+ 'VEOL': 'EOL',
+ 'VEOL2': 'EOL2',
+ 'VERASE': 'ERASE',
+ 'VWERASE': 'WERASE',
+ 'VKILL': 'KILL',
+ 'VREPRINT': 'REPRINT',
+ 'VINTR': 'INTR',
+ 'VQUIT': 'QUIT',
+ 'VSUSP': 'SUSP',
+ 'VDSUSP': 'DSUSP',
+ 'VSTART': 'START',
+ 'VSTOP': 'STOP',
+ 'VLNEXT': 'LNEXT',
+ 'VDISCARD': 'DISCARD',
+ 'VMIN': '---',
+ 'VTIME': '---',
+ 'VSTATUS': 'STATUS',
+}
+
+
+def display_bitmask(kind, bitmap, value):
+ """ Display all matching bitmask values for ``value`` given ``bitmap``. """
+ col1_width = max(map(len, list(bitmap.keys()) + [kind]))
+ col2_width = 7
+ FMT = '{name:>{col1_width}} {value:>{col2_width}} {description}'
+ print(FMT.format(name=kind,
+ value='Value',
+ description='Description',
+ col1_width=col1_width,
+ col2_width=col2_width))
+ print('{0} {1} {2}'.format('-' * col1_width,
+ '-' * col2_width,
+ '-' * max(map(len, bitmap.values()))))
+ for flag_name, description in bitmap.items():
+ try:
+ bitmask = getattr(termios, flag_name)
+ bit_val = 'on' if bool(value & bitmask) else 'off'
+ except AttributeError:
+ bit_val = 'undef'
+ print(FMT.format(name=flag_name,
+ value=bit_val,
+ description=description,
+ col1_width=col1_width,
+ col2_width=col2_width))
+ print()
+
+
+def display_ctl_chars(index, cc):
+ """ Display all control character indicies, names, and values. """
+ title = 'Special Character'
+ col1_width = len(title)
+ col2_width = max(map(len, index.values()))
+ FMT = '{idx:<{col1_width}} {name:<{col2_width}} {value}'
+ print('Special line Characters'.center(40).rstrip())
+ print(FMT.format(idx='Index',
+ name='Name',
+ value='Value',
+ col1_width=col1_width,
+ col2_width=col2_width))
+ print('{0} {1} {2}'.format('-' * col1_width,
+ '-' * col2_width,
+ '-' * 10))
+ for index_name, name in index.items():
+ try:
+ index = getattr(termios, index_name)
+ value = cc[index]
+ if value == b'\xff':
+ value = '_POSIX_VDISABLE'
+ else:
+ value = repr(value)
+ except AttributeError:
+ value = 'undef'
+ print(FMT.format(idx=index_name,
+ name=name,
+ value=value,
+ col1_width=col1_width,
+ col2_width=col2_width))
+ print()
+
+
+def display_conf(kind, names, getter):
+ col1_width = max(map(len, names))
+ FMT = '{name:>{col1_width}} {value}'
+ print(FMT.format(name=kind,
+ value='value',
+ col1_width=col1_width))
+ print('{0} {1}'.format('-' * col1_width, '-' * 27))
+ for name in names:
+ try:
+ value = getter(name)
+ except OSError as err:
+ value = err
+ print(FMT.format(name=name, value=value, col1_width=col1_width))
+ print()
+
+
+def main():
+ fd = sys.stdin.fileno()
+ locale.setlocale(locale.LC_ALL, '')
+ encoding = locale.getpreferredencoding()
+
+ print('os.isatty({0}) => {1}'.format(fd, os.isatty(fd)))
+ print('locale.getpreferredencoding() => {0}'.format(encoding))
+
+ display_conf(kind='pathconf',
+ names=os.pathconf_names,
+ getter=lambda name: os.fpathconf(fd, name))
+
+ try:
+ (iflag, oflag, cflag, lflag, ispeed, ospeed, cc
+ ) = termios.tcgetattr(fd)
+ except termios.error as err:
+ print('stdin is not a typewriter: {0}'.format(err))
+ else:
+ display_bitmask(kind='Input Mode',
+ bitmap=BITMAP_IFLAG,
+ value=iflag)
+ display_bitmask(kind='Output Mode',
+ bitmap=BITMAP_OFLAG,
+ value=oflag)
+ display_bitmask(kind='Control Mode',
+ bitmap=BITMAP_CFLAG,
+ value=cflag)
+ display_bitmask(kind='Local Mode',
+ bitmap=BITMAP_LFLAG,
+ value=lflag)
+ display_ctl_chars(index=CTLCHAR_INDEX,
+ cc=cc)
+ try:
+ print('os.ttyname({0}) => {1}'.format(fd, os.ttyname(fd)))
+ print('os.ctermid() => {0}'.format(os.ctermid()))
+ except OSError as e:
+ # Travis fails on ttyname with errno 0 'Error'.
+ print("Error inspecting TTY: {0}".format(e))
+
+if __name__ == '__main__':
+ main()
Index: third_party/Python/module/pexpect-4.6/tools/teamcity-coverage-report.sh
===================================================================
--- third_party/Python/module/pexpect-4.6/tools/teamcity-coverage-report.sh
+++ third_party/Python/module/pexpect-4.6/tools/teamcity-coverage-report.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# This is to be executed by each individual OS test. It only
+# combines coverage files and reports locally to the given
+# TeamCity build configuration.
+set -e
+set -o pipefail
+[ -z ${TEMP} ] && TEMP=/tmp
+
+# combine all .coverage* files,
+coverage combine
+
+# create ascii report,
+report_file=$(mktemp $TEMP/coverage.XXXXX)
+coverage report --rcfile=`dirname $0`/../.coveragerc > "${report_file}" 2>/dev/null
+
+# Report Code Coverage for TeamCity, using 'Service Messages',
+# https://confluence.jetbrains.com/display/TCD8/How+To...#HowTo...-ImportcoverageresultsinTeamCity
+# https://confluence.jetbrains.com/display/TCD8/Custom+Chart#CustomChart-DefaultStatisticsValuesProvidedbyTeamCity
+total_no_lines=$(awk '/TOTAL/{printf("%s",$2)}' < "${report_file}")
+total_no_misses=$(awk '/TOTAL/{printf("%s",$3)}' < "${report_file}")
+total_no_covered=$((${total_no_lines} - ${total_no_misses}))
+echo "##teamcity[buildStatisticValue key='CodeCoverageAbsLTotal' value='""${total_no_lines}""']"
+echo "##teamcity[buildStatisticValue key='CodeCoverageAbsLCovered' value='""${total_no_covered}""']"
+
+# Display for human consumption and remove ascii file.
+cat "${report_file}"
+rm "${report_file}"
Index: third_party/Python/module/pexpect-4.6/tools/teamcity-runtests.sh
===================================================================
--- third_party/Python/module/pexpect-4.6/tools/teamcity-runtests.sh
+++ third_party/Python/module/pexpect-4.6/tools/teamcity-runtests.sh
@@ -0,0 +1,64 @@
+#!/bin/bash
+#
+# This script assumes that the project 'ptyprocess' is
+# available in the parent of the project's folder.
+set -e
+set -o pipefail
+
+if [ -z $1 ]; then
+ echo "$0 (2.6|2.7|3.3|3.4)"
+ exit 1
+fi
+
+export PYTHONIOENCODING=UTF8
+export LANG=en_US.UTF-8
+
+pyversion=$1
+shift
+here=$(cd `dirname $0`; pwd)
+osrel=$(uname -s)
+venv=teamcity-pexpect
+venv_wrapper=$(which virtualenvwrapper.sh)
+
+if [ -z $venv_wrapper ]; then
+ echo "virtualenvwrapper.sh not found in PATH." >&2
+ exit 1
+fi
+
+. ${venv_wrapper}
+rmvirtualenv ${venv} || true
+mkvirtualenv -p `which python${pyversion}` ${venv} || true
+workon ${venv}
+
+# install ptyprocess
+cd $here/../../ptyprocess
+pip uninstall --yes ptyprocess || true
+python setup.py install
+
+# install all test requirements
+pip install --upgrade pytest-cov coverage coveralls pytest-capturelog
+
+# run tests
+cd $here/..
+ret=0
+py.test \
+ --cov pexpect \
+ --cov-config .coveragerc \
+ --junit-xml=results.${osrel}.py${pyversion}.xml \
+ --verbose \
+ --verbose \
+ "$@" || ret=$?
+
+if [ $ret -ne 0 ]; then
+ # we always exit 0, preferring instead the jUnit XML
+ # results to be the dominate cause of a failed build.
+ echo "py.test returned exit code ${ret}." >&2
+ echo "the build should detect and report these failing tests." >&2
+fi
+
+# combine all coverage to single file, report for this build,
+# then move into ./build-output/ as a unique artifact to allow
+# the final "Full build" step to combine and report to coveralls.io
+`dirname $0`/teamcity-coverage-report.sh
+mkdir -p build-output
+mv .coverage build-output/.coverage.${osrel}.py{$pyversion}.$RANDOM.$$
Index: third_party/Python/module/ptyprocess-0.6.0/.gitignore
===================================================================
--- third_party/Python/module/ptyprocess-0.6.0/.gitignore
+++ third_party/Python/module/ptyprocess-0.6.0/.gitignore
@@ -0,0 +1,7 @@
+__pycache__
+*.pyc
+
+/build/
+/dist/
+MANIFEST
+docs/_build/
Index: third_party/Python/module/ptyprocess-0.6.0/.travis.yml
===================================================================
--- third_party/Python/module/ptyprocess-0.6.0/.travis.yml
+++ third_party/Python/module/ptyprocess-0.6.0/.travis.yml
@@ -0,0 +1,9 @@
+language: python
+python:
+ - "3.6"
+ - "3.5"
+ - "3.4"
+ - "2.7"
+# command to run tests
+script: py.test --verbose --verbose
+sudo: False
Index: third_party/Python/module/ptyprocess-0.6.0/LICENSE
===================================================================
--- third_party/Python/module/ptyprocess-0.6.0/LICENSE
+++ third_party/Python/module/ptyprocess-0.6.0/LICENSE
@@ -0,0 +1,16 @@
+Ptyprocess is under the ISC license, as code derived from Pexpect.
+ http://opensource.org/licenses/ISC
+
+Copyright (c) 2013-2014, Pexpect development team
+Copyright (c) 2012, Noah Spurrier
+
+PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY PURPOSE
+WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE COPYRIGHT NOTICE
+AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. THE SOFTWARE IS PROVIDED
+"AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT
+SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
Index: third_party/Python/module/ptyprocess-0.6.0/README.rst
===================================================================
--- third_party/Python/module/ptyprocess-0.6.0/README.rst
+++ third_party/Python/module/ptyprocess-0.6.0/README.rst
@@ -0,0 +1,15 @@
+Launch a subprocess in a pseudo terminal (pty), and interact with both the
+process and its pty.
+
+Sometimes, piping stdin and stdout is not enough. There might be a password
+prompt that doesn't read from stdin, output that changes when it's going to a
+pipe rather than a terminal, or curses-style interfaces that rely on a terminal.
+If you need to automate these things, running the process in a pseudo terminal
+(pty) is the answer.
+
+Interface::
+
+ p = PtyProcessUnicode.spawn(['python'])
+ p.read(20)
+ p.write('6+6\n')
+ p.read(20)
Index: third_party/Python/module/ptyprocess-0.6.0/docs/Makefile
===================================================================
--- third_party/Python/module/ptyprocess-0.6.0/docs/Makefile
+++ third_party/Python/module/ptyprocess-0.6.0/docs/Makefile
@@ -0,0 +1,177 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+PAPER =
+BUILDDIR = _build
+
+# User-friendly check for sphinx-build
+ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
+$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
+endif
+
+# Internal variables.
+PAPEROPT_a4 = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+# the i18n builder cannot share the environment and doctrees with the others
+I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
+
+help:
+ @echo "Please use \`make ' where is one of"
+ @echo " html to make standalone HTML files"
+ @echo " dirhtml to make HTML files named index.html in directories"
+ @echo " singlehtml to make a single large HTML file"
+ @echo " pickle to make pickle files"
+ @echo " json to make JSON files"
+ @echo " htmlhelp to make HTML files and a HTML help project"
+ @echo " qthelp to make HTML files and a qthelp project"
+ @echo " devhelp to make HTML files and a Devhelp project"
+ @echo " epub to make an epub"
+ @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+ @echo " latexpdf to make LaTeX files and run them through pdflatex"
+ @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
+ @echo " text to make text files"
+ @echo " man to make manual pages"
+ @echo " texinfo to make Texinfo files"
+ @echo " info to make Texinfo files and run them through makeinfo"
+ @echo " gettext to make PO message catalogs"
+ @echo " changes to make an overview of all changed/added/deprecated items"
+ @echo " xml to make Docutils-native XML files"
+ @echo " pseudoxml to make pseudoxml-XML files for display purposes"
+ @echo " linkcheck to check all external links for integrity"
+ @echo " doctest to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+ rm -rf $(BUILDDIR)/*
+
+html:
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+ $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml:
+ $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+ @echo
+ @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+pickle:
+ $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+ @echo
+ @echo "Build finished; now you can process the pickle files."
+
+json:
+ $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+ @echo
+ @echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+ $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+ @echo
+ @echo "Build finished; now you can run HTML Help Workshop with the" \
+ ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+ $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+ @echo
+ @echo "Build finished; now you can run "qcollectiongenerator" with the" \
+ ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+ @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Ptyprocess.qhcp"
+ @echo "To view the help file:"
+ @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Ptyprocess.qhc"
+
+devhelp:
+ $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+ @echo
+ @echo "Build finished."
+ @echo "To view the help file:"
+ @echo "# mkdir -p $$HOME/.local/share/devhelp/Ptyprocess"
+ @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Ptyprocess"
+ @echo "# devhelp"
+
+epub:
+ $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+ @echo
+ @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+latex:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo
+ @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+ @echo "Run \`make' in that directory to run these through (pdf)latex" \
+ "(use \`make latexpdf' here to do that automatically)."
+
+latexpdf:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through pdflatex..."
+ $(MAKE) -C $(BUILDDIR)/latex all-pdf
+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+latexpdfja:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through platex and dvipdfmx..."
+ $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+text:
+ $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+ @echo
+ @echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+man:
+ $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+ @echo
+ @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+texinfo:
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+ @echo
+ @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
+ @echo "Run \`make' in that directory to run these through makeinfo" \
+ "(use \`make info' here to do that automatically)."
+
+info:
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+ @echo "Running Texinfo files through makeinfo..."
+ make -C $(BUILDDIR)/texinfo info
+ @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
+
+gettext:
+ $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
+ @echo
+ @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
+
+changes:
+ $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+ @echo
+ @echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+ $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+ @echo
+ @echo "Link check complete; look for any errors in the above output " \
+ "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+ $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+ @echo "Testing of doctests in the sources finished, look at the " \
+ "results in $(BUILDDIR)/doctest/output.txt."
+
+xml:
+ $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
+ @echo
+ @echo "Build finished. The XML files are in $(BUILDDIR)/xml."
+
+pseudoxml:
+ $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
+ @echo
+ @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
Index: third_party/Python/module/ptyprocess-0.6.0/docs/api.rst
===================================================================
--- third_party/Python/module/ptyprocess-0.6.0/docs/api.rst
+++ third_party/Python/module/ptyprocess-0.6.0/docs/api.rst
@@ -0,0 +1,10 @@
+Ptyprocess API
+==============
+
+.. module:: ptyprocess
+
+.. autoclass:: PtyProcess
+
+ .. automethod:: spawn
+
+.. autoclass:: PtyProcessUnicode
Index: third_party/Python/module/ptyprocess-0.6.0/docs/conf.py
===================================================================
--- third_party/Python/module/ptyprocess-0.6.0/docs/conf.py
+++ third_party/Python/module/ptyprocess-0.6.0/docs/conf.py
@@ -0,0 +1,266 @@
+# -*- coding: utf-8 -*-
+#
+# Ptyprocess documentation build configuration file, created by
+# sphinx-quickstart on Mon Oct 13 11:03:02 2014.
+#
+# This file is execfile()d with the current directory set to its
+# containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys
+import os
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+sys.path.insert(0, os.path.abspath('..'))
+
+# -- General configuration ------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = [
+ 'sphinx.ext.autodoc',
+ 'sphinx.ext.intersphinx',
+ 'sphinx.ext.viewcode',
+]
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'Ptyprocess'
+copyright = u'2014, Thomas Kluyver'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = '0.5'
+# The full version, including alpha/beta/rc tags.
+release = version + '.2'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['_build']
+
+# The reST default role (used for this markup: `text`) to use for all
+# documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+# If true, keep warnings as "system message" paragraphs in the built documents.
+#keep_warnings = False
+
+
+# -- Options for HTML output ----------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+html_theme = 'default'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further. For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents. If None, it defaults to
+# " v documentation".
+#html_title = None
+
+# A shorter title for the navigation bar. Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# Add any extra paths that contain custom files (such as robots.txt or
+# .htaccess) here, relative to this directory. These files are copied
+# directly to the root of the documentation.
+#html_extra_path = []
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a tag referring to it. The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'Ptyprocessdoc'
+
+
+# -- Options for LaTeX output ---------------------------------------------
+
+latex_elements = {
+# The paper size ('letterpaper' or 'a4paper').
+#'papersize': 'letterpaper',
+
+# The font size ('10pt', '11pt' or '12pt').
+#'pointsize': '10pt',
+
+# Additional stuff for the LaTeX preamble.
+#'preamble': '',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title,
+# author, documentclass [howto, manual, or own class]).
+latex_documents = [
+ ('index', 'Ptyprocess.tex', u'Ptyprocess Documentation',
+ u'Thomas Kluyver', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output ---------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+ ('index', 'ptyprocess', u'Ptyprocess Documentation',
+ [u'Thomas Kluyver'], 1)
+]
+
+# If true, show URL addresses after external links.
+#man_show_urls = False
+
+
+# -- Options for Texinfo output -------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+# dir menu entry, description, category)
+texinfo_documents = [
+ ('index', 'Ptyprocess', u'Ptyprocess Documentation',
+ u'Thomas Kluyver', 'Ptyprocess', 'One line description of project.',
+ 'Miscellaneous'),
+]
+
+# Documents to append as an appendix to all manuals.
+#texinfo_appendices = []
+
+# If false, no module index is generated.
+#texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#texinfo_show_urls = 'footnote'
+
+# If true, do not generate a @detailmenu in the "Top" node's menu.
+#texinfo_no_detailmenu = False
+
+
+# Example configuration for intersphinx: refer to the Python standard library.
+intersphinx_mapping = {'http://docs.python.org/': None}
Index: third_party/Python/module/ptyprocess-0.6.0/docs/images/pty_vs_popen.svg
===================================================================
--- third_party/Python/module/ptyprocess-0.6.0/docs/images/pty_vs_popen.svg
+++ third_party/Python/module/ptyprocess-0.6.0/docs/images/pty_vs_popen.svg
@@ -0,0 +1,759 @@
+
+
+
+
Index: third_party/Python/module/ptyprocess-0.6.0/docs/index.rst
===================================================================
--- third_party/Python/module/ptyprocess-0.6.0/docs/index.rst
+++ third_party/Python/module/ptyprocess-0.6.0/docs/index.rst
@@ -0,0 +1,53 @@
+Ptyprocess
+==========
+
+.. include:: ../README.rst
+
+Contents:
+
+.. toctree::
+ :maxdepth: 2
+
+ api
+
+What is a pty?
+--------------
+
+A pty is a kernel-level object which processes can write data to and read data
+from, a bit like a pipe.
+
+Unlike a pipe, data moves through a single pty in both directions. When you use
+a program in a shell pipeline, or with :class:`subprocess.Popen` in Python, up
+to three pipes are created for the process's standard streams (stdin, stdout
+and stderr). When you run a program using ptyprocess, all three of its standard
+streams are connected to a single pty:
+
+.. image:: images/pty_vs_popen.png
+
+A pty also does more than a pipe. It keeps track of the window size (rows and
+columns of characters) and notifies child processes (with a SIGWINCH signal)
+when it changes. In *cooked mode*, it does some processing of data sent from the
+parent process, so for instance the byte ``03`` (entered as Ctrl-C) will cause
+SIGINT to be sent to the child process.
+
+Many command line programs behave differently if they detect that stdin or stdout
+is connected to a terminal instead of a pipe (using
+`isatty() `_), because this normally means
+that they're being used interactively by a human user.
+They may format output differently (e.g. ``ls`` lists files in columns)
+or prompt the user to confirm actions.
+When you run these programs in ptyprocess, they will exhibit their 'interactive'
+behaviour, instead of the 'pipe' behaviour you'll see using ``Popen()``.
+
+.. seealso::
+
+ `The TTY demystified `_
+ Detailed article by Linus Akesson
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+
Index: third_party/Python/module/ptyprocess-0.6.0/ptyprocess/__init__.py
===================================================================
--- third_party/Python/module/ptyprocess-0.6.0/ptyprocess/__init__.py
+++ third_party/Python/module/ptyprocess-0.6.0/ptyprocess/__init__.py
@@ -0,0 +1,4 @@
+"""Run a subprocess in a pseudo terminal"""
+from .ptyprocess import PtyProcess, PtyProcessUnicode, PtyProcessError
+
+__version__ = '0.6.0'
Index: third_party/Python/module/ptyprocess-0.6.0/ptyprocess/_fork_pty.py
===================================================================
--- third_party/Python/module/ptyprocess-0.6.0/ptyprocess/_fork_pty.py
+++ third_party/Python/module/ptyprocess-0.6.0/ptyprocess/_fork_pty.py
@@ -0,0 +1,78 @@
+"""Substitute for the forkpty system call, to support Solaris.
+"""
+import os
+import errno
+
+from pty import (STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO, CHILD)
+from .util import PtyProcessError
+
+def fork_pty():
+ '''This implements a substitute for the forkpty system call. This
+ should be more portable than the pty.fork() function. Specifically,
+ this should work on Solaris.
+
+ Modified 10.06.05 by Geoff Marshall: Implemented __fork_pty() method to
+ resolve the issue with Python's pty.fork() not supporting Solaris,
+ particularly ssh. Based on patch to posixmodule.c authored by Noah
+ Spurrier::
+
+ http://mail.python.org/pipermail/python-dev/2003-May/035281.html
+
+ '''
+
+ parent_fd, child_fd = os.openpty()
+ if parent_fd < 0 or child_fd < 0:
+ raise OSError("os.openpty() failed")
+
+ pid = os.fork()
+ if pid == CHILD:
+ # Child.
+ os.close(parent_fd)
+ pty_make_controlling_tty(child_fd)
+
+ os.dup2(child_fd, STDIN_FILENO)
+ os.dup2(child_fd, STDOUT_FILENO)
+ os.dup2(child_fd, STDERR_FILENO)
+
+ else:
+ # Parent.
+ os.close(child_fd)
+
+ return pid, parent_fd
+
+def pty_make_controlling_tty(tty_fd):
+ '''This makes the pseudo-terminal the controlling tty. This should be
+ more portable than the pty.fork() function. Specifically, this should
+ work on Solaris. '''
+
+ child_name = os.ttyname(tty_fd)
+
+ # Disconnect from controlling tty, if any. Raises OSError of ENXIO
+ # if there was no controlling tty to begin with, such as when
+ # executed by a cron(1) job.
+ try:
+ fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY)
+ os.close(fd)
+ except OSError as err:
+ if err.errno != errno.ENXIO:
+ raise
+
+ os.setsid()
+
+ # Verify we are disconnected from controlling tty by attempting to open
+ # it again. We expect that OSError of ENXIO should always be raised.
+ try:
+ fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY)
+ os.close(fd)
+ raise PtyProcessError("OSError of errno.ENXIO should be raised.")
+ except OSError as err:
+ if err.errno != errno.ENXIO:
+ raise
+
+ # Verify we can open child pty.
+ fd = os.open(child_name, os.O_RDWR)
+ os.close(fd)
+
+ # Verify we now have a controlling tty.
+ fd = os.open("/dev/tty", os.O_WRONLY)
+ os.close(fd)
Index: third_party/Python/module/ptyprocess-0.6.0/ptyprocess/ptyprocess.py
===================================================================
--- third_party/Python/module/ptyprocess-0.6.0/ptyprocess/ptyprocess.py
+++ third_party/Python/module/ptyprocess-0.6.0/ptyprocess/ptyprocess.py
@@ -0,0 +1,836 @@
+import codecs
+import errno
+import fcntl
+import io
+import os
+import pty
+import resource
+import signal
+import struct
+import sys
+import termios
+import time
+
+try:
+ import builtins # Python 3
+except ImportError:
+ import __builtin__ as builtins # Python 2
+
+# Constants
+from pty import (STDIN_FILENO, CHILD)
+
+from .util import which, PtyProcessError
+
+_platform = sys.platform.lower()
+
+# Solaris uses internal __fork_pty(). All others use pty.fork().
+_is_solaris = (
+ _platform.startswith('solaris') or
+ _platform.startswith('sunos'))
+
+if _is_solaris:
+ use_native_pty_fork = False
+ from . import _fork_pty
+else:
+ use_native_pty_fork = True
+
+PY3 = sys.version_info[0] >= 3
+
+if PY3:
+ def _byte(i):
+ return bytes([i])
+else:
+ def _byte(i):
+ return chr(i)
+
+ class FileNotFoundError(OSError): pass
+ class TimeoutError(OSError): pass
+
+_EOF, _INTR = None, None
+
+def _make_eof_intr():
+ """Set constants _EOF and _INTR.
+
+ This avoids doing potentially costly operations on module load.
+ """
+ global _EOF, _INTR
+ if (_EOF is not None) and (_INTR is not None):
+ return
+
+ # inherit EOF and INTR definitions from controlling process.
+ try:
+ from termios import VEOF, VINTR
+ fd = None
+ for name in 'stdin', 'stdout':
+ stream = getattr(sys, '__%s__' % name, None)
+ if stream is None or not hasattr(stream, 'fileno'):
+ continue
+ try:
+ fd = stream.fileno()
+ except ValueError:
+ continue
+ if fd is None:
+ # no fd, raise ValueError to fallback on CEOF, CINTR
+ raise ValueError("No stream has a fileno")
+ intr = ord(termios.tcgetattr(fd)[6][VINTR])
+ eof = ord(termios.tcgetattr(fd)[6][VEOF])
+ except (ImportError, OSError, IOError, ValueError, termios.error):
+ # unless the controlling process is also not a terminal,
+ # such as cron(1), or when stdin and stdout are both closed.
+ # Fall-back to using CEOF and CINTR. There
+ try:
+ from termios import CEOF, CINTR
+ (intr, eof) = (CINTR, CEOF)
+ except ImportError:
+ # ^C, ^D
+ (intr, eof) = (3, 4)
+
+ _INTR = _byte(intr)
+ _EOF = _byte(eof)
+
+# setecho and setwinsize are pulled out here because on some platforms, we need
+# to do this from the child before we exec()
+
+def _setecho(fd, state):
+ errmsg = 'setecho() may not be called on this platform (it may still be possible to enable/disable echo when spawning the child process)'
+
+ try:
+ attr = termios.tcgetattr(fd)
+ except termios.error as err:
+ if err.args[0] == errno.EINVAL:
+ raise IOError(err.args[0], '%s: %s.' % (err.args[1], errmsg))
+ raise
+
+ if state:
+ attr[3] = attr[3] | termios.ECHO
+ else:
+ attr[3] = attr[3] & ~termios.ECHO
+
+ try:
+ # I tried TCSADRAIN and TCSAFLUSH, but these were inconsistent and
+ # blocked on some platforms. TCSADRAIN would probably be ideal.
+ termios.tcsetattr(fd, termios.TCSANOW, attr)
+ except IOError as err:
+ if err.args[0] == errno.EINVAL:
+ raise IOError(err.args[0], '%s: %s.' % (err.args[1], errmsg))
+ raise
+
+def _setwinsize(fd, rows, cols):
+ # Some very old platforms have a bug that causes the value for
+ # termios.TIOCSWINSZ to be truncated. There was a hack here to work
+ # around this, but it caused problems with newer platforms so has been
+ # removed. For details see https://github.com/pexpect/pexpect/issues/39
+ TIOCSWINSZ = getattr(termios, 'TIOCSWINSZ', -2146929561)
+ # Note, assume ws_xpixel and ws_ypixel are zero.
+ s = struct.pack('HHHH', rows, cols, 0, 0)
+ fcntl.ioctl(fd, TIOCSWINSZ, s)
+
+class PtyProcess(object):
+ '''This class represents a process running in a pseudoterminal.
+
+ The main constructor is the :meth:`spawn` classmethod.
+ '''
+ string_type = bytes
+ if PY3:
+ linesep = os.linesep.encode('ascii')
+ crlf = '\r\n'.encode('ascii')
+
+ @staticmethod
+ def write_to_stdout(b):
+ try:
+ return sys.stdout.buffer.write(b)
+ except AttributeError:
+ # If stdout has been replaced, it may not have .buffer
+ return sys.stdout.write(b.decode('ascii', 'replace'))
+ else:
+ linesep = os.linesep
+ crlf = '\r\n'
+ write_to_stdout = sys.stdout.write
+
+ encoding = None
+
+ argv = None
+ env = None
+ launch_dir = None
+
+ def __init__(self, pid, fd):
+ _make_eof_intr() # Ensure _EOF and _INTR are calculated
+ self.pid = pid
+ self.fd = fd
+ readf = io.open(fd, 'rb', buffering=0)
+ writef = io.open(fd, 'wb', buffering=0, closefd=False)
+ self.fileobj = io.BufferedRWPair(readf, writef)
+
+ self.terminated = False
+ self.closed = False
+ self.exitstatus = None
+ self.signalstatus = None
+ # status returned by os.waitpid
+ self.status = None
+ self.flag_eof = False
+ # Used by close() to give kernel time to update process status.
+ # Time in seconds.
+ self.delayafterclose = 0.1
+ # Used by terminate() to give kernel time to update process status.
+ # Time in seconds.
+ self.delayafterterminate = 0.1
+
+ @classmethod
+ def spawn(
+ cls, argv, cwd=None, env=None, echo=True, preexec_fn=None,
+ dimensions=(24, 80)):
+ '''Start the given command in a child process in a pseudo terminal.
+
+ This does all the fork/exec type of stuff for a pty, and returns an
+ instance of PtyProcess.
+
+ If preexec_fn is supplied, it will be called with no arguments in the
+ child process before exec-ing the specified command.
+ It may, for instance, set signal handlers to SIG_DFL or SIG_IGN.
+
+ Dimensions of the psuedoterminal used for the subprocess can be
+ specified as a tuple (rows, cols), or the default (24, 80) will be used.
+ '''
+ # Note that it is difficult for this method to fail.
+ # You cannot detect if the child process cannot start.
+ # So the only way you can tell if the child process started
+ # or not is to try to read from the file descriptor. If you get
+ # EOF immediately then it means that the child is already dead.
+ # That may not necessarily be bad because you may have spawned a child
+ # that performs some task; creates no stdout output; and then dies.
+
+ if not isinstance(argv, (list, tuple)):
+ raise TypeError("Expected a list or tuple for argv, got %r" % argv)
+
+ # Shallow copy of argv so we can modify it
+ argv = argv[:]
+ command = argv[0]
+
+ command_with_path = which(command)
+ if command_with_path is None:
+ raise FileNotFoundError('The command was not found or was not ' +
+ 'executable: %s.' % command)
+ command = command_with_path
+ argv[0] = command
+
+ # [issue #119] To prevent the case where exec fails and the user is
+ # stuck interacting with a python child process instead of whatever
+ # was expected, we implement the solution from
+ # http://stackoverflow.com/a/3703179 to pass the exception to the
+ # parent process
+
+ # [issue #119] 1. Before forking, open a pipe in the parent process.
+ exec_err_pipe_read, exec_err_pipe_write = os.pipe()
+
+ if use_native_pty_fork:
+ pid, fd = pty.fork()
+ else:
+ # Use internal fork_pty, for Solaris
+ pid, fd = _fork_pty.fork_pty()
+
+ # Some platforms must call setwinsize() and setecho() from the
+ # child process, and others from the master process. We do both,
+ # allowing IOError for either.
+
+ if pid == CHILD:
+ # set window size
+ try:
+ _setwinsize(STDIN_FILENO, *dimensions)
+ except IOError as err:
+ if err.args[0] not in (errno.EINVAL, errno.ENOTTY):
+ raise
+
+ # disable echo if spawn argument echo was unset
+ if not echo:
+ try:
+ _setecho(STDIN_FILENO, False)
+ except (IOError, termios.error) as err:
+ if err.args[0] not in (errno.EINVAL, errno.ENOTTY):
+ raise
+
+ # [issue #119] 3. The child closes the reading end and sets the
+ # close-on-exec flag for the writing end.
+ os.close(exec_err_pipe_read)
+ fcntl.fcntl(exec_err_pipe_write, fcntl.F_SETFD, fcntl.FD_CLOEXEC)
+
+ # Do not allow child to inherit open file descriptors from parent,
+ # with the exception of the exec_err_pipe_write of the pipe
+ # Impose ceiling on max_fd: AIX bugfix for users with unlimited
+ # nofiles where resource.RLIMIT_NOFILE is 2^63-1 and os.closerange()
+ # occasionally raises out of range error
+ max_fd = min(1048576, resource.getrlimit(resource.RLIMIT_NOFILE)[0])
+ os.closerange(3, exec_err_pipe_write)
+ os.closerange(exec_err_pipe_write+1, max_fd)
+
+ if cwd is not None:
+ os.chdir(cwd)
+
+ if preexec_fn is not None:
+ try:
+ preexec_fn()
+ except Exception as e:
+ ename = type(e).__name__
+ tosend = '{}:0:{}'.format(ename, str(e))
+ if PY3:
+ tosend = tosend.encode('utf-8')
+
+ os.write(exec_err_pipe_write, tosend)
+ os.close(exec_err_pipe_write)
+ os._exit(1)
+
+ try:
+ if env is None:
+ os.execv(command, argv)
+ else:
+ os.execvpe(command, argv, env)
+ except OSError as err:
+ # [issue #119] 5. If exec fails, the child writes the error
+ # code back to the parent using the pipe, then exits.
+ tosend = 'OSError:{}:{}'.format(err.errno, str(err))
+ if PY3:
+ tosend = tosend.encode('utf-8')
+ os.write(exec_err_pipe_write, tosend)
+ os.close(exec_err_pipe_write)
+ os._exit(os.EX_OSERR)
+
+ # Parent
+ inst = cls(pid, fd)
+
+ # Set some informational attributes
+ inst.argv = argv
+ if env is not None:
+ inst.env = env
+ if cwd is not None:
+ inst.launch_dir = cwd
+
+ # [issue #119] 2. After forking, the parent closes the writing end
+ # of the pipe and reads from the reading end.
+ os.close(exec_err_pipe_write)
+ exec_err_data = os.read(exec_err_pipe_read, 4096)
+ os.close(exec_err_pipe_read)
+
+ # [issue #119] 6. The parent reads eof (a zero-length read) if the
+ # child successfully performed exec, since close-on-exec made
+ # successful exec close the writing end of the pipe. Or, if exec
+ # failed, the parent reads the error code and can proceed
+ # accordingly. Either way, the parent blocks until the child calls
+ # exec.
+ if len(exec_err_data) != 0:
+ try:
+ errclass, errno_s, errmsg = exec_err_data.split(b':', 2)
+ exctype = getattr(builtins, errclass.decode('ascii'), Exception)
+
+ exception = exctype(errmsg.decode('utf-8', 'replace'))
+ if exctype is OSError:
+ exception.errno = int(errno_s)
+ except:
+ raise Exception('Subprocess failed, got bad error data: %r'
+ % exec_err_data)
+ else:
+ raise exception
+
+ try:
+ inst.setwinsize(*dimensions)
+ except IOError as err:
+ if err.args[0] not in (errno.EINVAL, errno.ENOTTY, errno.ENXIO):
+ raise
+
+ return inst
+
+ def __repr__(self):
+ clsname = type(self).__name__
+ if self.argv is not None:
+ args = [repr(self.argv)]
+ if self.env is not None:
+ args.append("env=%r" % self.env)
+ if self.launch_dir is not None:
+ args.append("cwd=%r" % self.launch_dir)
+
+ return "{}.spawn({})".format(clsname, ", ".join(args))
+
+ else:
+ return "{}(pid={}, fd={})".format(clsname, self.pid, self.fd)
+
+ @staticmethod
+ def _coerce_send_string(s):
+ if not isinstance(s, bytes):
+ return s.encode('utf-8')
+ return s
+
+ @staticmethod
+ def _coerce_read_string(s):
+ return s
+
+ def __del__(self):
+ '''This makes sure that no system resources are left open. Python only
+ garbage collects Python objects. OS file descriptors are not Python
+ objects, so they must be handled explicitly. If the child file
+ descriptor was opened outside of this class (passed to the constructor)
+ then this does not close it. '''
+
+ if not self.closed:
+ # It is possible for __del__ methods to execute during the
+ # teardown of the Python VM itself. Thus self.close() may
+ # trigger an exception because os.close may be None.
+ try:
+ self.close()
+ # which exception, shouldn't we catch explicitly .. ?
+ except:
+ pass
+
+
+ def fileno(self):
+ '''This returns the file descriptor of the pty for the child.
+ '''
+ return self.fd
+
+ def close(self, force=True):
+ '''This closes the connection with the child application. Note that
+ calling close() more than once is valid. This emulates standard Python
+ behavior with files. Set force to True if you want to make sure that
+ the child is terminated (SIGKILL is sent if the child ignores SIGHUP
+ and SIGINT). '''
+ if not self.closed:
+ self.flush()
+ self.fileobj.close() # Closes the file descriptor
+ # Give kernel time to update process status.
+ time.sleep(self.delayafterclose)
+ if self.isalive():
+ if not self.terminate(force):
+ raise PtyProcessError('Could not terminate the child.')
+ self.fd = -1
+ self.closed = True
+ #self.pid = None
+
+ def flush(self):
+ '''This does nothing. It is here to support the interface for a
+ File-like object. '''
+
+ pass
+
+ def isatty(self):
+ '''This returns True if the file descriptor is open and connected to a
+ tty(-like) device, else False.
+
+ On SVR4-style platforms implementing streams, such as SunOS and HP-UX,
+ the child pty may not appear as a terminal device. This means
+ methods such as setecho(), setwinsize(), getwinsize() may raise an
+ IOError. '''
+
+ return os.isatty(self.fd)
+
+ def waitnoecho(self, timeout=None):
+ '''This waits until the terminal ECHO flag is set False. This returns
+ True if the echo mode is off. This returns False if the ECHO flag was
+ not set False before the timeout. This can be used to detect when the
+ child is waiting for a password. Usually a child application will turn
+ off echo mode when it is waiting for the user to enter a password. For
+ example, instead of expecting the "password:" prompt you can wait for
+ the child to set ECHO off::
+
+ p = pexpect.spawn('ssh user@example.com')
+ p.waitnoecho()
+ p.sendline(mypassword)
+
+ If timeout==None then this method to block until ECHO flag is False.
+ '''
+
+ if timeout is not None:
+ end_time = time.time() + timeout
+ while True:
+ if not self.getecho():
+ return True
+ if timeout < 0 and timeout is not None:
+ return False
+ if timeout is not None:
+ timeout = end_time - time.time()
+ time.sleep(0.1)
+
+ def getecho(self):
+ '''This returns the terminal echo mode. This returns True if echo is
+ on or False if echo is off. Child applications that are expecting you
+ to enter a password often set ECHO False. See waitnoecho().
+
+ Not supported on platforms where ``isatty()`` returns False. '''
+
+ try:
+ attr = termios.tcgetattr(self.fd)
+ except termios.error as err:
+ errmsg = 'getecho() may not be called on this platform'
+ if err.args[0] == errno.EINVAL:
+ raise IOError(err.args[0], '%s: %s.' % (err.args[1], errmsg))
+ raise
+
+ self.echo = bool(attr[3] & termios.ECHO)
+ return self.echo
+
+ def setecho(self, state):
+ '''This sets the terminal echo mode on or off. Note that anything the
+ child sent before the echo will be lost, so you should be sure that
+ your input buffer is empty before you call setecho(). For example, the
+ following will work as expected::
+
+ p = pexpect.spawn('cat') # Echo is on by default.
+ p.sendline('1234') # We expect see this twice from the child...
+ p.expect(['1234']) # ... once from the tty echo...
+ p.expect(['1234']) # ... and again from cat itself.
+ p.setecho(False) # Turn off tty echo
+ p.sendline('abcd') # We will set this only once (echoed by cat).
+ p.sendline('wxyz') # We will set this only once (echoed by cat)
+ p.expect(['abcd'])
+ p.expect(['wxyz'])
+
+ The following WILL NOT WORK because the lines sent before the setecho
+ will be lost::
+
+ p = pexpect.spawn('cat')
+ p.sendline('1234')
+ p.setecho(False) # Turn off tty echo
+ p.sendline('abcd') # We will set this only once (echoed by cat).
+ p.sendline('wxyz') # We will set this only once (echoed by cat)
+ p.expect(['1234'])
+ p.expect(['1234'])
+ p.expect(['abcd'])
+ p.expect(['wxyz'])
+
+
+ Not supported on platforms where ``isatty()`` returns False.
+ '''
+ _setecho(self.fd, state)
+
+ self.echo = state
+
+ def read(self, size=1024):
+ """Read and return at most ``size`` bytes from the pty.
+
+ Can block if there is nothing to read. Raises :exc:`EOFError` if the
+ terminal was closed.
+
+ Unlike Pexpect's ``read_nonblocking`` method, this doesn't try to deal
+ with the vagaries of EOF on platforms that do strange things, like IRIX
+ or older Solaris systems. It handles the errno=EIO pattern used on
+ Linux, and the empty-string return used on BSD platforms and (seemingly)
+ on recent Solaris.
+ """
+ try:
+ s = self.fileobj.read1(size)
+ except (OSError, IOError) as err:
+ if err.args[0] == errno.EIO:
+ # Linux-style EOF
+ self.flag_eof = True
+ raise EOFError('End Of File (EOF). Exception style platform.')
+ raise
+ if s == b'':
+ # BSD-style EOF (also appears to work on recent Solaris (OpenIndiana))
+ self.flag_eof = True
+ raise EOFError('End Of File (EOF). Empty string style platform.')
+
+ return s
+
+ def readline(self):
+ """Read one line from the pseudoterminal, and return it as unicode.
+
+ Can block if there is nothing to read. Raises :exc:`EOFError` if the
+ terminal was closed.
+ """
+ try:
+ s = self.fileobj.readline()
+ except (OSError, IOError) as err:
+ if err.args[0] == errno.EIO:
+ # Linux-style EOF
+ self.flag_eof = True
+ raise EOFError('End Of File (EOF). Exception style platform.')
+ raise
+ if s == b'':
+ # BSD-style EOF (also appears to work on recent Solaris (OpenIndiana))
+ self.flag_eof = True
+ raise EOFError('End Of File (EOF). Empty string style platform.')
+
+ return s
+
+ def _writeb(self, b, flush=True):
+ n = self.fileobj.write(b)
+ if flush:
+ self.fileobj.flush()
+ return n
+
+ def write(self, s, flush=True):
+ """Write bytes to the pseudoterminal.
+
+ Returns the number of bytes written.
+ """
+ return self._writeb(s, flush=flush)
+
+ def sendcontrol(self, char):
+ '''Helper method that wraps send() with mnemonic access for sending control
+ character to the child (such as Ctrl-C or Ctrl-D). For example, to send
+ Ctrl-G (ASCII 7, bell, '\a')::
+
+ child.sendcontrol('g')
+
+ See also, sendintr() and sendeof().
+ '''
+ char = char.lower()
+ a = ord(char)
+ if 97 <= a <= 122:
+ a = a - ord('a') + 1
+ byte = _byte(a)
+ return self._writeb(byte), byte
+ d = {'@': 0, '`': 0,
+ '[': 27, '{': 27,
+ '\\': 28, '|': 28,
+ ']': 29, '}': 29,
+ '^': 30, '~': 30,
+ '_': 31,
+ '?': 127}
+ if char not in d:
+ return 0, b''
+
+ byte = _byte(d[char])
+ return self._writeb(byte), byte
+
+ def sendeof(self):
+ '''This sends an EOF to the child. This sends a character which causes
+ the pending parent output buffer to be sent to the waiting child
+ program without waiting for end-of-line. If it is the first character
+ of the line, the read() in the user program returns 0, which signifies
+ end-of-file. This means to work as expected a sendeof() has to be
+ called at the beginning of a line. This method does not send a newline.
+ It is the responsibility of the caller to ensure the eof is sent at the
+ beginning of a line. '''
+
+ return self._writeb(_EOF), _EOF
+
+ def sendintr(self):
+ '''This sends a SIGINT to the child. It does not require
+ the SIGINT to be the first character on a line. '''
+
+ return self._writeb(_INTR), _INTR
+
+ def eof(self):
+ '''This returns True if the EOF exception was ever raised.
+ '''
+
+ return self.flag_eof
+
+ def terminate(self, force=False):
+ '''This forces a child process to terminate. It starts nicely with
+ SIGHUP and SIGINT. If "force" is True then moves onto SIGKILL. This
+ returns True if the child was terminated. This returns False if the
+ child could not be terminated. '''
+
+ if not self.isalive():
+ return True
+ try:
+ self.kill(signal.SIGHUP)
+ time.sleep(self.delayafterterminate)
+ if not self.isalive():
+ return True
+ self.kill(signal.SIGCONT)
+ time.sleep(self.delayafterterminate)
+ if not self.isalive():
+ return True
+ self.kill(signal.SIGINT)
+ time.sleep(self.delayafterterminate)
+ if not self.isalive():
+ return True
+ if force:
+ self.kill(signal.SIGKILL)
+ time.sleep(self.delayafterterminate)
+ if not self.isalive():
+ return True
+ else:
+ return False
+ return False
+ except OSError:
+ # I think there are kernel timing issues that sometimes cause
+ # this to happen. I think isalive() reports True, but the
+ # process is dead to the kernel.
+ # Make one last attempt to see if the kernel is up to date.
+ time.sleep(self.delayafterterminate)
+ if not self.isalive():
+ return True
+ else:
+ return False
+
+ def wait(self):
+ '''This waits until the child exits. This is a blocking call. This will
+ not read any data from the child, so this will block forever if the
+ child has unread output and has terminated. In other words, the child
+ may have printed output then called exit(), but, the child is
+ technically still alive until its output is read by the parent. '''
+
+ if self.isalive():
+ pid, status = os.waitpid(self.pid, 0)
+ else:
+ return self.exitstatus
+ self.exitstatus = os.WEXITSTATUS(status)
+ if os.WIFEXITED(status):
+ self.status = status
+ self.exitstatus = os.WEXITSTATUS(status)
+ self.signalstatus = None
+ self.terminated = True
+ elif os.WIFSIGNALED(status):
+ self.status = status
+ self.exitstatus = None
+ self.signalstatus = os.WTERMSIG(status)
+ self.terminated = True
+ elif os.WIFSTOPPED(status): # pragma: no cover
+ # You can't call wait() on a child process in the stopped state.
+ raise PtyProcessError('Called wait() on a stopped child ' +
+ 'process. This is not supported. Is some other ' +
+ 'process attempting job control with our child pid?')
+ return self.exitstatus
+
+ def isalive(self):
+ '''This tests if the child process is running or not. This is
+ non-blocking. If the child was terminated then this will read the
+ exitstatus or signalstatus of the child. This returns True if the child
+ process appears to be running or False if not. It can take literally
+ SECONDS for Solaris to return the right status. '''
+
+ if self.terminated:
+ return False
+
+ if self.flag_eof:
+ # This is for Linux, which requires the blocking form
+ # of waitpid to get the status of a defunct process.
+ # This is super-lame. The flag_eof would have been set
+ # in read_nonblocking(), so this should be safe.
+ waitpid_options = 0
+ else:
+ waitpid_options = os.WNOHANG
+
+ try:
+ pid, status = os.waitpid(self.pid, waitpid_options)
+ except OSError as e:
+ # No child processes
+ if e.errno == errno.ECHILD:
+ raise PtyProcessError('isalive() encountered condition ' +
+ 'where "terminated" is 0, but there was no child ' +
+ 'process. Did someone else call waitpid() ' +
+ 'on our process?')
+ else:
+ raise
+
+ # I have to do this twice for Solaris.
+ # I can't even believe that I figured this out...
+ # If waitpid() returns 0 it means that no child process
+ # wishes to report, and the value of status is undefined.
+ if pid == 0:
+ try:
+ ### os.WNOHANG) # Solaris!
+ pid, status = os.waitpid(self.pid, waitpid_options)
+ except OSError as e: # pragma: no cover
+ # This should never happen...
+ if e.errno == errno.ECHILD:
+ raise PtyProcessError('isalive() encountered condition ' +
+ 'that should never happen. There was no child ' +
+ 'process. Did someone else call waitpid() ' +
+ 'on our process?')
+ else:
+ raise
+
+ # If pid is still 0 after two calls to waitpid() then the process
+ # really is alive. This seems to work on all platforms, except for
+ # Irix which seems to require a blocking call on waitpid or select,
+ # so I let read_nonblocking take care of this situation
+ # (unfortunately, this requires waiting through the timeout).
+ if pid == 0:
+ return True
+
+ if pid == 0:
+ return True
+
+ if os.WIFEXITED(status):
+ self.status = status
+ self.exitstatus = os.WEXITSTATUS(status)
+ self.signalstatus = None
+ self.terminated = True
+ elif os.WIFSIGNALED(status):
+ self.status = status
+ self.exitstatus = None
+ self.signalstatus = os.WTERMSIG(status)
+ self.terminated = True
+ elif os.WIFSTOPPED(status):
+ raise PtyProcessError('isalive() encountered condition ' +
+ 'where child process is stopped. This is not ' +
+ 'supported. Is some other process attempting ' +
+ 'job control with our child pid?')
+ return False
+
+ def kill(self, sig):
+ """Send the given signal to the child application.
+
+ In keeping with UNIX tradition it has a misleading name. It does not
+ necessarily kill the child unless you send the right signal. See the
+ :mod:`signal` module for constants representing signal numbers.
+ """
+
+ # Same as os.kill, but the pid is given for you.
+ if self.isalive():
+ os.kill(self.pid, sig)
+
+ def getwinsize(self):
+ """Return the window size of the pseudoterminal as a tuple (rows, cols).
+ """
+ TIOCGWINSZ = getattr(termios, 'TIOCGWINSZ', 1074295912)
+ s = struct.pack('HHHH', 0, 0, 0, 0)
+ x = fcntl.ioctl(self.fd, TIOCGWINSZ, s)
+ return struct.unpack('HHHH', x)[0:2]
+
+ def setwinsize(self, rows, cols):
+ """Set the terminal window size of the child tty.
+
+ This will cause a SIGWINCH signal to be sent to the child. This does not
+ change the physical window size. It changes the size reported to
+ TTY-aware applications like vi or curses -- applications that respond to
+ the SIGWINCH signal.
+ """
+ return _setwinsize(self.fd, rows, cols)
+
+
+class PtyProcessUnicode(PtyProcess):
+ """Unicode wrapper around a process running in a pseudoterminal.
+
+ This class exposes a similar interface to :class:`PtyProcess`, but its read
+ methods return unicode, and its :meth:`write` accepts unicode.
+ """
+ if PY3:
+ string_type = str
+ else:
+ string_type = unicode # analysis:ignore
+
+ def __init__(self, pid, fd, encoding='utf-8', codec_errors='strict'):
+ super(PtyProcessUnicode, self).__init__(pid, fd)
+ self.encoding = encoding
+ self.codec_errors = codec_errors
+ self.decoder = codecs.getincrementaldecoder(encoding)(errors=codec_errors)
+
+ def read(self, size=1024):
+ """Read at most ``size`` bytes from the pty, return them as unicode.
+
+ Can block if there is nothing to read. Raises :exc:`EOFError` if the
+ terminal was closed.
+
+ The size argument still refers to bytes, not unicode code points.
+ """
+ b = super(PtyProcessUnicode, self).read(size)
+ return self.decoder.decode(b, final=False)
+
+ def readline(self):
+ """Read one line from the pseudoterminal, and return it as unicode.
+
+ Can block if there is nothing to read. Raises :exc:`EOFError` if the
+ terminal was closed.
+ """
+ b = super(PtyProcessUnicode, self).readline()
+ return self.decoder.decode(b, final=False)
+
+ def write(self, s):
+ """Write the unicode string ``s`` to the pseudoterminal.
+
+ Returns the number of bytes written.
+ """
+ b = s.encode(self.encoding)
+ return super(PtyProcessUnicode, self).write(b)
Index: third_party/Python/module/ptyprocess-0.6.0/ptyprocess/util.py
===================================================================
--- third_party/Python/module/ptyprocess-0.6.0/ptyprocess/util.py
+++ third_party/Python/module/ptyprocess-0.6.0/ptyprocess/util.py
@@ -0,0 +1,71 @@
+try:
+ from shutil import which # Python >= 3.3
+except ImportError:
+ import os, sys
+
+ # This is copied from Python 3.4.1
+ def which(cmd, mode=os.F_OK | os.X_OK, path=None):
+ """Given a command, mode, and a PATH string, return the path which
+ conforms to the given mode on the PATH, or None if there is no such
+ file.
+
+ `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result
+ of os.environ.get("PATH"), or can be overridden with a custom search
+ path.
+
+ """
+ # Check that a given file can be accessed with the correct mode.
+ # Additionally check that `file` is not a directory, as on Windows
+ # directories pass the os.access check.
+ def _access_check(fn, mode):
+ return (os.path.exists(fn) and os.access(fn, mode)
+ and not os.path.isdir(fn))
+
+ # If we're given a path with a directory part, look it up directly rather
+ # than referring to PATH directories. This includes checking relative to the
+ # current directory, e.g. ./script
+ if os.path.dirname(cmd):
+ if _access_check(cmd, mode):
+ return cmd
+ return None
+
+ if path is None:
+ path = os.environ.get("PATH", os.defpath)
+ if not path:
+ return None
+ path = path.split(os.pathsep)
+
+ if sys.platform == "win32":
+ # The current directory takes precedence on Windows.
+ if not os.curdir in path:
+ path.insert(0, os.curdir)
+
+ # PATHEXT is necessary to check on Windows.
+ pathext = os.environ.get("PATHEXT", "").split(os.pathsep)
+ # See if the given file matches any of the expected path extensions.
+ # This will allow us to short circuit when given "python.exe".
+ # If it does match, only test that one, otherwise we have to try
+ # others.
+ if any(cmd.lower().endswith(ext.lower()) for ext in pathext):
+ files = [cmd]
+ else:
+ files = [cmd + ext for ext in pathext]
+ else:
+ # On other platforms you don't have things like PATHEXT to tell you
+ # what file suffixes are executable, so just pass on cmd as-is.
+ files = [cmd]
+
+ seen = set()
+ for dir in path:
+ normdir = os.path.normcase(dir)
+ if not normdir in seen:
+ seen.add(normdir)
+ for thefile in files:
+ name = os.path.join(dir, thefile)
+ if _access_check(name, mode):
+ return name
+ return None
+
+
+class PtyProcessError(Exception):
+ """Generic error class for this package."""
Index: third_party/Python/module/ptyprocess-0.6.0/pyproject.toml
===================================================================
--- third_party/Python/module/ptyprocess-0.6.0/pyproject.toml
+++ third_party/Python/module/ptyprocess-0.6.0/pyproject.toml
@@ -0,0 +1,24 @@
+[build-system]
+requires = ["flit"]
+build-backend = "flit.buildapi"
+
+[tool.flit.metadata]
+module = "ptyprocess"
+author = "Thomas Kluyver"
+author-email = "thomas@kluyver.me.uk"
+home-page = "https://github.com/pexpect/ptyprocess"
+description-file = "README.rst"
+classifiers = [
+ "Development Status :: 5 - Production/Stable",
+ "Environment :: Console",
+ "Intended Audience :: Developers",
+ "Intended Audience :: System Administrators",
+ "License :: OSI Approved :: ISC License (ISCL)",
+ "Operating System :: POSIX",
+ "Operating System :: MacOS :: MacOS X",
+ "Programming Language :: Python",
+ "Programming Language :: Python :: 2.7",
+ "Programming Language :: Python :: 3",
+ "Topic :: Terminals"
+]
+
Index: third_party/Python/module/ptyprocess-0.6.0/readthedocs.yml
===================================================================
--- third_party/Python/module/ptyprocess-0.6.0/readthedocs.yml
+++ third_party/Python/module/ptyprocess-0.6.0/readthedocs.yml
@@ -0,0 +1,2 @@
+python:
+ version: 3
Index: third_party/Python/module/ptyprocess-0.6.0/tests/test_echo.py
===================================================================
--- third_party/Python/module/ptyprocess-0.6.0/tests/test_echo.py
+++ third_party/Python/module/ptyprocess-0.6.0/tests/test_echo.py
@@ -0,0 +1,36 @@
+import time
+import unittest
+from ptyprocess.ptyprocess import _is_solaris
+from ptyprocess import PtyProcess
+
+class PtyEchoTestCase(unittest.TestCase):
+
+ def _read_until_eof(self, proc):
+ """Read away all output on ``proc`` until EOF."""
+ while True:
+ try:
+ proc.read()
+ except EOFError:
+ return
+
+ @unittest.skipIf(_is_solaris, "waitnoecho cannot be called on this platform.")
+ def test_waitnoecho_forever(self):
+ """Ensure waitnoecho() with no timeout will return when echo=False."""
+ cat = PtyProcess.spawn(['cat'], echo=False)
+ assert cat.waitnoecho() == True
+ assert cat.echo == False
+ assert cat.getecho() == False
+ cat.sendeof()
+ self._read_until_eof(cat)
+ assert cat.wait() == 0
+
+ @unittest.skipIf(_is_solaris, "waitnoecho cannot be called on this platform.")
+ def test_waitnoecho_timeout(self):
+ """Ensure waitnoecho() with timeout will return when using stty to unset echo."""
+ cat = PtyProcess.spawn(['cat'], echo=True)
+ assert cat.waitnoecho(timeout=1) == False
+ assert cat.echo == True
+ assert cat.getecho() == True
+ cat.sendeof()
+ self._read_until_eof(cat)
+ assert cat.wait() == 0
Index: third_party/Python/module/ptyprocess-0.6.0/tests/test_invalid_binary.py
===================================================================
--- third_party/Python/module/ptyprocess-0.6.0/tests/test_invalid_binary.py
+++ third_party/Python/module/ptyprocess-0.6.0/tests/test_invalid_binary.py
@@ -0,0 +1,74 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import time
+import unittest
+from ptyprocess import PtyProcess, PtyProcessUnicode
+import errno
+import os
+import stat
+import tempfile
+
+class InvalidBinaryChars(unittest.TestCase):
+
+ def test_invalid_binary(self):
+ '''This tests that we correctly handle the case where we attempt to
+ spawn a child process but the exec call fails'''
+
+ # Create a file that should fail the exec call
+ dirpath = tempfile.mkdtemp()
+ fullpath = os.path.join(dirpath, "test")
+
+ with open(fullpath, 'wb') as f:
+ # Add some constant so it will never be executable
+ # - Not 0x54AD (Windows PE)
+ # - Not 0x7FEF (ELF)
+ # - Not 0410 or 0413 (a.out)
+ # - Not 0x2321 (script)
+ file_start = b'\x00\x00'
+ file_data = file_start + os.urandom(1022)
+ f.write(file_data)
+
+ # Make it executable
+ st = os.stat(fullpath)
+ os.chmod(fullpath, st.st_mode | stat.S_IEXEC)
+
+ # TODO Verify this does what is intended on Windows
+ try:
+ child = PtyProcess.spawn([fullpath])
+ # If we get here then an OSError was not raised
+ child.close()
+ raise AssertionError("OSError was not raised")
+ except OSError as err:
+ if errno.ENOEXEC == err.errno:
+ # This is what should happen
+ pass
+ else:
+ # Re-raise the original error to fail the test
+ raise
+ finally:
+ os.unlink(fullpath)
+ os.rmdir(dirpath)
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(InvalidBinaryChars,'test')
+
Index: third_party/Python/module/ptyprocess-0.6.0/tests/test_preexec_fn.py
===================================================================
--- third_party/Python/module/ptyprocess-0.6.0/tests/test_preexec_fn.py
+++ third_party/Python/module/ptyprocess-0.6.0/tests/test_preexec_fn.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import unittest
+import shutil
+from ptyprocess import PtyProcess
+import os
+import tempfile
+
+class PreexecFns(unittest.TestCase):
+ def test_preexec(self):
+ td = tempfile.mkdtemp()
+ filepath = os.path.join(td, 'foo')
+ def pef():
+ with open(filepath, 'w') as f:
+ f.write('bar')
+
+ try:
+ child = PtyProcess.spawn(['ls'], preexec_fn=pef)
+ child.close()
+ with open(filepath, 'r') as f:
+ assert f.read() == 'bar'
+
+ finally:
+ shutil.rmtree(td)
+
+ def test_preexec_error(self):
+ def func():
+ raise ValueError("Test error condition")
+
+ try:
+ child = PtyProcess.spawn(['ls'], preexec_fn=func)
+ # If we get here then an error was not raised
+ child.close()
+ raise AssertionError("ValueError was not raised")
+ except ValueError as err:
+ if str(err) != "Test error condition":
+ # Re-raise the original error to fail the test
+ raise
+
+
Index: third_party/Python/module/ptyprocess-0.6.0/tests/test_spawn.py
===================================================================
--- third_party/Python/module/ptyprocess-0.6.0/tests/test_spawn.py
+++ third_party/Python/module/ptyprocess-0.6.0/tests/test_spawn.py
@@ -0,0 +1,113 @@
+import os
+import time
+import select
+import unittest
+from ptyprocess.ptyprocess import which
+from ptyprocess import PtyProcess, PtyProcessUnicode
+
+class PtyTestCase(unittest.TestCase):
+ def setUp(self):
+ self.cmd = u'echo $ENV_KEY; exit 0\n'
+ self.env = os.environ.copy()
+ self.env_key = u'ENV_KEY'
+ self.env_value = u'env_value'
+ self.env[self.env_key] = self.env_value
+
+ def _canread(self, fd, timeout=1):
+ return fd in select.select([fd], [], [], timeout)[0]
+
+ def _spawn_sh(self, ptyp, cmd, outp, env_value):
+ # given,
+ p = ptyp.spawn(['sh'], env=self.env)
+ p.write(cmd)
+
+ # exercise,
+ while True:
+ try:
+ outp += p.read()
+ except EOFError:
+ break
+
+ # verify, input is echo to output
+ assert cmd.strip() in outp
+
+ # result of echo $ENV_KEY in output
+ assert env_value in outp
+
+ # exit successfully (exit 0)
+ assert p.wait() == 0
+
+
+ def test_spawn_sh(self):
+ outp = b''
+ self._spawn_sh(PtyProcess, self.cmd.encode('ascii'),
+ outp, self.env_value.encode('ascii'))
+
+ def test_spawn_sh_unicode(self):
+ outp = u''
+ self._spawn_sh(PtyProcessUnicode, self.cmd,
+ outp, self.env_value)
+
+ def test_quick_spawn(self):
+ """Spawn a very short-lived process."""
+ # so far only reproducible on Solaris 11, spawning a process
+ # that exits very quickly raised an exception at 'inst.setwinsize',
+ # because the pty file descriptor was quickly lost after exec().
+ PtyProcess.spawn(['true'])
+
+ def _interactive_repl_unicode(self, echo):
+ """Test Call and response with echo ON/OFF."""
+ # given,
+ bc = PtyProcessUnicode.spawn(['bc'], echo=echo)
+ given_input = u'2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2\n'
+ expected_output = u'40'
+
+ # gnu-bc will display a long FSF banner on startup,
+ # whereas bsd-bc (on FreeBSD, Solaris) display no
+ # banner at all. To ensure we've read up to our
+ # current prompt, read until the response of '2^16' is found.
+ time.sleep(1)
+
+ bc.write(u'2^16\n')
+ outp = u''
+ while self._canread(bc.fd):
+ outp += bc.read()
+ assert u'65536' in outp
+
+ # exercise,
+ bc.write(given_input)
+
+ while self._canread(bc.fd, timeout=2):
+ outp += bc.read()
+
+ # with echo ON, we should see our input.
+ #
+ # note: we cannot assert the reverse: on Solaris, FreeBSD,
+ # and OSX, our input is echoed to output even with echo=False,
+ # something to do with the non-gnu version of bc(1), perhaps.
+ if echo:
+ assert given_input.strip() in outp
+
+ # we should most certainly see the result output.
+ assert expected_output in outp
+
+ # exercise sending EOF
+ bc.sendeof()
+
+ # validate EOF on read
+ while True:
+ try:
+ bc.read()
+ except EOFError:
+ break
+
+ # validate exit status,
+ assert bc.wait() == 0
+
+ @unittest.skipIf(which('bc') is None, "bc(1) not found on this server.")
+ def test_interactive_repl_unicode_noecho(self):
+ self._interactive_repl_unicode(echo=False)
+
+ @unittest.skipIf(which('bc') is None, "bc(1) not found on this server.")
+ def test_interactive_repl_unicode_echo(self):
+ self._interactive_repl_unicode(echo=True)
Index: third_party/Python/module/ptyprocess-0.6.0/tests/test_wait.py
===================================================================
--- third_party/Python/module/ptyprocess-0.6.0/tests/test_wait.py
+++ third_party/Python/module/ptyprocess-0.6.0/tests/test_wait.py
@@ -0,0 +1,32 @@
+""" Test cases for PtyProcess.wait method. """
+import time
+import unittest
+from ptyprocess import PtyProcess
+
+
+class TestWaitAfterTermination(unittest.TestCase):
+ """Various test cases for PtyProcess.wait()"""
+
+ def test_wait_true_shortproc(self):
+ """Ensure correct (True) wait status for short-lived processes."""
+ child = PtyProcess.spawn(['true'])
+ # Wait so we're reasonable sure /bin/true has terminated
+ time.sleep(0.2)
+ self.assertEqual(child.wait(), 0)
+
+ def test_wait_false_shortproc(self):
+ """Ensure correct (False) wait status for short-lived processes."""
+ child = PtyProcess.spawn(['false'])
+ # Wait so we're reasonable sure /bin/false has terminated
+ time.sleep(0.2)
+ self.assertNotEqual(child.wait(), 0)
+
+ def test_wait_twice_longproc(self):
+ """Ensure correct wait status when called twice."""
+ # previous versions of ptyprocess raises PtyProcessError when
+ # wait was called more than once with "Cannot wait for dead child
+ # process.". No longer true since v0.5.
+ child = PtyProcess.spawn(['sleep', '1'])
+ # this call to wait() will block for 1s
+ for count in range(2):
+ self.assertEqual(child.wait(), 0, count)