Imported Upstream version 6.10.0.49

Former-commit-id: 1d6753294b2993e1fbf92de9366bb9544db4189b
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2020-01-16 16:38:04 +00:00
parent d94e79959b
commit 468663ddbb
48518 changed files with 2789335 additions and 61176 deletions

View File

@@ -0,0 +1,370 @@
"""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()

View File

@@ -0,0 +1,370 @@
#!/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)

View File

@@ -0,0 +1,31 @@
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.

View File

@@ -0,0 +1,21 @@
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.

View File

@@ -0,0 +1,10 @@
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

View File

@@ -0,0 +1,45 @@
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/

View File

@@ -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;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 322 B

View File

@@ -0,0 +1,135 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Pexpect - Examples</title>
<link rel="stylesheet" href="clean.css" type="text/css">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="Author" content="Noah Spurrier">
<meta name="Keywords"
content="pexpect, Noah Spurrier, Python, Libes, TCL, Expect, pipe, popen, pyExpect, expectpy, expect-like, expect-alike, expect like">
<meta name="Description" content="Examples for using Pexpect.">
</head>
<body bgcolor="#ffffff" text="#000000">
<div id="Header">
<h1>Pexpect Examples</h1>
</div>
<div id="Content">
<p><span class="code">hive.py</span></p>
<p><blockquote>
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.
</p></blockquote>
<p><span class="code">script.py</span></p>
<p><blockquote>
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.
</p></blockquote>
<p><span class="code">fix_cvs_files.py</span></p>
<p><blockquote>
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.
</p></blockquote>
<p><span class="code">ftp.py</span></p>
<p><blockquote>
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.
</p></blockquote>
<p><span class="code">monitor.py</span></p>
<p><blockquote>
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.
</p></blockquote>
<p><span class="code">passmass.py</span></p>
<p><blockquote>
This will login to each given server and change the
password of the
given user. This demonstrates scripting logins and
passwords.
</p></blockquote>
<p><span class="code">python.py</span></p>
<p><blockquote>
This starts the python interpreter and prints the
greeting message backwards.
It then gives the user iteractive control of Python.
It's pretty useless!
</p></blockquote>
<p><span class="code">rippy.py</span></p>
<p><blockquote>
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.
</p></blockquote>
<p><span class="code">sshls.py</span></p>
<p><blockquote>
This lists a directory on a remote machine.
</p></blockquote>
<p><span class="code">ssh_tunnel.py</span></p>
<p><blockquote>
This starts an SSH tunnel to a remote machine. It
monitors the connection
and restarts the tunnel if it goes down.
</p></blockquote>
<p><span class="code">uptime.py</span></p>
<p><blockquote>
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.
</blockquote>
<p>
<a href="http://sourceforge.net/projects/pexpect/"
title="The Pexpect project page on SourceForge.net"> <img
src="http://sourceforge.net/sflogo.php?group_id=59762&amp;type=5"
alt="The Pexpect project page on SourceForge.net" border="0"
height="31" width="105"> </a>
</p>
</div>
</body>
</html>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,72 @@
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.

View File

@@ -0,0 +1,85 @@
#!/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)

View File

@@ -0,0 +1,40 @@
#!/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()

View File

@@ -0,0 +1,339 @@
#!/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] + \
'<img src="http://www.noah.org/cursor.gif">' + 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<username>[^@:]*)(:?)(?P<password>.*)(?!\\)@(?P<hostname>[^:]*):?(?P<port>[0-9]*)')
else:
p = re.compile(
r'(?P<username>)(?P<password>)(?P<hostname>[^:]*):?(?P<port>[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)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,132 @@
#!/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()

View File

@@ -0,0 +1,135 @@
#!/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()

View File

@@ -0,0 +1,139 @@
#!/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()

View File

@@ -0,0 +1,33 @@
#!/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

Some files were not shown because too many files have changed in this diff Show More