summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornoah <noah@656d521f-e311-0410-88e0-e7920216d269>2007-03-07 03:38:52 +0000
committernoah <noah@656d521f-e311-0410-88e0-e7920216d269>2007-03-07 03:38:52 +0000
commit3b83f590704fb158bc8a0df0b681f06f82ff31ac (patch)
tree8836fb2948afb5712bc45f20d7555bc5e60e4911
parentf06d6c64d591cefa4bcc72f304f80178a2834990 (diff)
downloadpexpect-3b83f590704fb158bc8a0df0b681f06f82ff31ac.tar.gz
Updated docs.
git-svn-id: http://pexpect.svn.sourceforge.net/svnroot/pexpect/trunk@462 656d521f-e311-0410-88e0-e7920216d269
-rw-r--r--[-rwxr-xr-x]pexpect/ANSI.py307
-rw-r--r--pexpect/FSM.py239
-rw-r--r--pexpect/pexpect.py6
-rw-r--r--pexpect/psh.py7
-rw-r--r--pexpect/pxssh.py4
-rw-r--r--[-rwxr-xr-x]pexpect/screen.py201
6 files changed, 469 insertions, 295 deletions
diff --git a/pexpect/ANSI.py b/pexpect/ANSI.py
index 030d3f1..9162389 100755..100644
--- a/pexpect/ANSI.py
+++ b/pexpect/ANSI.py
@@ -1,134 +1,177 @@
-'''
-$Revision: 374 $
-$Date: 2006-03-06 18:47:28 -0800 (Mon, 06 Mar 2006) $
+"""This implements an ANSI terminal emulator as a subclass of screen.
-'''
+$Id$
+"""
# 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
-#
+# 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.something[0]
+ screen.write_ch(fsm.input_symbol)
-def Emit (fsm):
- screen = fsm.something[0]
- screen.write_ch(fsm.input_symbol)
def StartNumber (fsm):
- fsm.something.append (fsm.input_symbol)
+
+ fsm.something.append (fsm.input_symbol)
+
def BuildNumber (fsm):
- ns = fsm.something.pop()
- ns = ns + fsm.input_symbol
- fsm.something.append (ns)
+
+ ns = fsm.something.pop()
+ ns = ns + fsm.input_symbol
+ fsm.something.append (ns)
+
def DoBackOne (fsm):
- screen = fsm.something[0]
- screen.cursor_back ()
+
+ screen = fsm.something[0]
+ screen.cursor_back ()
+
def DoBack (fsm):
- count = int(fsm.something.pop())
- screen = fsm.something[0]
- screen.cursor_back (count)
+
+ count = int(fsm.something.pop())
+ screen = fsm.something[0]
+ screen.cursor_back (count)
+
def DoDownOne (fsm):
- screen = fsm.something[0]
- screen.cursor_down ()
+
+ screen = fsm.something[0]
+ screen.cursor_down ()
+
def DoDown (fsm):
- count = int(fsm.something.pop())
- screen = fsm.something[0]
- screen.cursor_down (count)
+
+ count = int(fsm.something.pop())
+ screen = fsm.something[0]
+ screen.cursor_down (count)
+
def DoForwardOne (fsm):
- screen = fsm.something[0]
- screen.cursor_forward ()
+
+ screen = fsm.something[0]
+ screen.cursor_forward ()
+
def DoForward (fsm):
- count = int(fsm.something.pop())
- screen = fsm.something[0]
- screen.cursor_forward (count)
+
+ count = int(fsm.something.pop())
+ screen = fsm.something[0]
+ screen.cursor_forward (count)
+
def DoUpReverse (fsm):
- screen = fsm.something[0]
- screen.cursor_up_reverse()
+
+ screen = fsm.something[0]
+ screen.cursor_up_reverse()
+
def DoUpOne (fsm):
- screen = fsm.something[0]
- screen.cursor_up ()
+
+ screen = fsm.something[0]
+ screen.cursor_up ()
+
def DoUp (fsm):
- count = int(fsm.something.pop())
- screen = fsm.something[0]
- screen.cursor_up (count)
+
+ count = int(fsm.something.pop())
+ screen = fsm.something[0]
+ screen.cursor_up (count)
+
def DoHome (fsm):
- c = int(fsm.something.pop())
- r = int(fsm.something.pop())
- screen = fsm.something[0]
- screen.cursor_home (r,c)
+
+ c = int(fsm.something.pop())
+ r = int(fsm.something.pop())
+ screen = fsm.something[0]
+ screen.cursor_home (r,c)
+
def DoHomeOrigin (fsm):
- c = 1
- r = 1
- screen = fsm.something[0]
- screen.cursor_home (r,c)
+
+ c = 1
+ r = 1
+ screen = fsm.something[0]
+ screen.cursor_home (r,c)
+
def DoEraseDown (fsm):
- screen = fsm.something[0]
- screen.erase_down()
+
+ screen = fsm.something[0]
+ screen.erase_down()
+
def DoErase (fsm):
- arg = int(fsm.something.pop())
- screen = fsm.something[0]
- if arg == 0:
- screen.erase_down()
- elif arg == 1:
- screen.erase_up()
- elif arg == 2:
- screen.erase_screen()
+
+ arg = int(fsm.something.pop())
+ screen = fsm.something[0]
+ if arg == 0:
+ screen.erase_down()
+ elif arg == 1:
+ screen.erase_up()
+ elif arg == 2:
+ screen.erase_screen()
+
def DoEraseEndOfLine (fsm):
- screen = fsm.something[0]
- screen.erase_end_of_line()
+
+ screen = fsm.something[0]
+ screen.erase_end_of_line()
+
def DoEraseLine (fsm):
- screen = fsm.something[0]
- if arg == 0:
- screen.end_of_line()
- elif arg == 1:
- screen.start_of_line()
- elif arg == 2:
- screen.erase_line()
+
+ screen = fsm.something[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.something[0]
- screen.scroll_screen()
+
+ screen = fsm.something[0]
+ screen.scroll_screen()
+
def DoCursorSave (fsm):
- screen = fsm.something[0]
- screen.cursor_save_attrs()
+
+ screen = fsm.something[0]
+ screen.cursor_save_attrs()
+
def DoCursorRestore (fsm):
- screen = fsm.something[0]
- screen.cursor_restore_attrs()
+
+ screen = fsm.something[0]
+ screen.cursor_restore_attrs()
+
def DoScrollRegion (fsm):
- screen = fsm.something[0]
- r2 = int(fsm.something.pop())
- r1 = int(fsm.something.pop())
- screen.scroll_screen_rows (r1,r2)
+
+ screen = fsm.something[0]
+ r2 = int(fsm.something.pop())
+ r1 = int(fsm.something.pop())
+ screen.scroll_screen_rows (r1,r2)
def DoMode (fsm):
- screen = fsm.something[0]
- mode = fsm.something.pop() # Should be 4
- # screen.setReplaceMode ()
+
+ screen = fsm.something[0]
+ mode = fsm.something.pop() # Should be 4
+ # screen.setReplaceMode ()
+
def Log (fsm):
- screen = fsm.something[0]
- fsm.something = [screen]
- fout = open ('log', 'a')
- fout.write (fsm.input_symbol + ',' + fsm.current_state + '\n')
- fout.close()
+
+ screen = fsm.something[0]
+ fsm.something = [screen]
+ fout = open ('log', 'a')
+ fout.write (fsm.input_symbol + ',' + fsm.current_state + '\n')
+ fout.close()
class term (screen.screen):
- '''This is a placeholder.
+ """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.
- '''
+
+ """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)
@@ -199,21 +242,30 @@ class ANSI (term):
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):
- '''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.
- '''
+
+ """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]
@@ -246,36 +298,37 @@ class ANSI (term):
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()
+# 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()
diff --git a/pexpect/FSM.py b/pexpect/FSM.py
index b327f82..d1ff58a 100644
--- a/pexpect/FSM.py
+++ b/pexpect/FSM.py
@@ -1,62 +1,66 @@
-'''This module implements a Finite State Machine (FSM).
-In addition to state this FSM also maintains a user defined "something".
-This "something" is effectively memory, so this FSM could be considered
-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:
+''' This module implements a Finite State Machine (FSM). In addition to state
+this FSM also maintains a user defined "something". This "something" is
+effectively memory, so this FSM could be considered 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:
+
+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 "something". The "something" attribute
-can be 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.
-
-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:
+
+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 "something". The "something" attribute can be 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.
+
+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:
+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.
+
+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
@@ -64,23 +68,25 @@ $Id$
'''
class ExceptionFSM(Exception):
+
'''This is the FSM Exception class.'''
+
def __init__(self, value):
self.value = value
def __str__(self):
return `self.value`
class FSM:
- '''This is a Finite State Machine (FSM).
- '''
+
+ '''This is a Finite State Machine (FSM). '''
def __init__(self, initial_state, something):
- '''This creates the FSM.
- You set the initial state here. The "something" 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.
- '''
+
+ '''This creates the FSM. You set the initial state here. The
+ "something" 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).
@@ -93,69 +99,85 @@ class FSM:
self.something = something
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__().
- '''
+
+ '''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, next_state):
- '''This adds a transition that associates
+
+ '''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 action may be set to None in which case the process() method will
+ ignore the action and only set the next_state.
You can also set transitions for a list of symbols by using
- add_transition_list().
- '''
+ add_transition_list(). '''
+
self.state_transitions[(input_symbol, state)] = (action, next_state)
def add_transition_list (self, list_input_symbols, state, action, next_state):
+
'''This adds the same transition for lots of different 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.
- '''
+ transitions that match character classes. '''
+
for input_symbol in list_input_symbols:
self.add_transition (input_symbol, state, action, next_state)
def add_transition_any (self, state, action, next_state):
- '''This adds a transition that associates
+
+ '''This adds a transition that associates::
+
(current_state) --> (action, next_state)
- The process() method checks these associations if it cannot
- first find a match of an (input_symbol, current_state).
- '''
+
+ The process() method checks these associations if it cannot first find
+ a match of an (input_symbol, current_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 for catching errors and undefined states.
+
+ '''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 for catching
+ errors and undefined states.
The default transition can be removed by setting the attribute
- default_transition to None.
- '''
+ 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 leaves the FSM unchanged. This does not update the current state
- nor does it trigger the output action. Normally you do not call
- this method. It is called by process().
+ This leaves the FSM unchanged. This does not update the current state
+ nor does it trigger the output action. Normally you do not call this
+ method. 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 (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.
+ 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 (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 self.state_transitions.has_key((input_symbol, self.current_state)):
return self.state_transitions[(input_symbol, self.current_state)]
elif self.state_transitions_any.has_key (self.current_state):
@@ -167,15 +189,15 @@ class FSM:
(str(input_symbol), str(self.current_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 input symbol. You can process a list of
- symbols (or a string) by calling process_list().
- '''
+
+ '''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 input symbol. You can process a list of symbols (or a
+ string) by calling process_list(). '''
+
self.input_symbol = input_symbol
(action, next_state) = self.get_transition (self.input_symbol, self.current_state)
if action != None:
@@ -183,9 +205,10 @@ class FSM:
self.current_state = next_state
def process_list (self, s):
- '''This takes a list and sends each element to process().
- The list may be a string.
- '''
+
+ '''This takes a list and sends each element to process(). The list may
+ be a string. '''
+
for c in s:
self.process (c)
diff --git a/pexpect/pexpect.py b/pexpect/pexpect.py
index b378958..a2bacc2 100644
--- a/pexpect/pexpect.py
+++ b/pexpect/pexpect.py
@@ -167,7 +167,8 @@ def run (command, timeout=-1, withexitstatus=False, events=None, extra_args=None
from pexpect import *
run ('scp foo myname@host.example.com:.', events={'(?i)password': mypassword})
- == Examples ==
+ Examples
+ ========
Start the apache daemon on the local machine::
@@ -184,7 +185,8 @@ def run (command, timeout=-1, withexitstatus=False, events=None, extra_args=None
from pexpect import *
(command_output, exitstatus) = run ('ls -l /bin', withexitstatus=1)
- === Tricky Examples ===
+ 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::
diff --git a/pexpect/psh.py b/pexpect/psh.py
index 916c8c5..6737c90 100644
--- a/pexpect/psh.py
+++ b/pexpect/psh.py
@@ -1,8 +1,9 @@
-"""This is a utility class to make shell scripting easier in Python.
-It combines Pexpect and wraps many Standard Python Library functions.
-The goal is to make Python an attractive alternative to Sh scripting.
+"""This is a utility class to make shell scripting easier in Python. It
+combines Pexpect and wraps many Standard Python Library functions.
+
$Id$
"""
+
import pexpect, os, sys
class psh (object):
diff --git a/pexpect/pxssh.py b/pexpect/pxssh.py
index c12e871..5bf64e6 100644
--- a/pexpect/pxssh.py
+++ b/pexpect/pxssh.py
@@ -27,7 +27,7 @@ class pxssh (spawn):
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:
+ Example that runs a few commands on a remote server and prints the result::
import pxssh
import getpass
@@ -58,7 +58,7 @@ class pxssh (spawn):
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'
- attirbute:
+ attribute::
s = pxssh.pxssh()
s.force_password = True
diff --git a/pexpect/screen.py b/pexpect/screen.py
index 1c1f217..6bcc3e4 100755..100644
--- a/pexpect/screen.py
+++ b/pexpect/screen.py
@@ -1,6 +1,7 @@
-'''
+"""This implements a virtual screen.
+
$Id$
-'''
+"""
import copy
#import string
@@ -25,8 +26,9 @@ DEL = 127 # Fill character; ignored on input.
SPACE = chr(32) # Space or blank character.
def constrain (n, min, max):
- """This returns n constrained to the min and max bounds.
- """
+
+ """This returns n constrained to the min and max bounds. """
+
if n < min:
return min
if n > max:
@@ -34,14 +36,13 @@ def constrain (n, min, max):
return n
class screen:
- """This maintains the state of a virtual text screen.
- This maintains a 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).
- """
+
+ """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):
self.rows = r
self.cols = c
@@ -57,16 +58,18 @@ class screen:
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.
- """
+
+ """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 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)
@@ -80,12 +83,17 @@ class screen:
self.put_abs (r,c,ch)
def cr (self):
- '''This moves the cursor to the beginning (col 1) of the current row.
- '''
+
+ """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.
- '''
+
+ """This moves the cursor down with scrolling.
+ """
+
old_r = self.cur_r
self.cursor_down()
if old_r == self.cur_r:
@@ -93,51 +101,69 @@ class screen:
self.erase_line()
def crlf (self):
- '''This advances the cursor with CRLF properties.
+
+ """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.'''
+
+ """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
+
+ """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.
- '''
+
+ """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)
@@ -156,107 +182,177 @@ class screen:
return sc
def cursor_constrain (self):
- '''This keeps the cursor within the screen area.
- '''
+
+ """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): # <ESC>[{ROW};{COLUMN}H
+
self.cur_r = r
self.cur_c = c
self.cursor_constrain ()
+
def cursor_back (self,count=1): # <ESC>[{COUNT}D (not confused with down)
+
self.cur_c = self.cur_c - count
self.cursor_constrain ()
+
def cursor_down (self,count=1): # <ESC>[{COUNT}B (not confused with back)
+
self.cur_r = self.cur_r + count
self.cursor_constrain ()
+
def cursor_forward (self,count=1): # <ESC>[{COUNT}C
+
self.cur_c = self.cur_c + count
self.cursor_constrain ()
+
def cursor_up (self,count=1): # <ESC>[{COUNT}A
+
self.cur_r = self.cur_r - count
self.cursor_constrain ()
+
def cursor_up_reverse (self): # <ESC> 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): # <ESC>[{ROW};{COLUMN}f
- '''Identical to Cursor Home.'''
+
+ """Identical to Cursor Home."""
+
self.cursor_home (r, c)
+
def cursor_save (self): # <ESC>[s
- '''Save current cursor position.'''
+
+ """Save current cursor position."""
+
self.cursor_save_attrs()
+
def cursor_unsave (self): # <ESC>[u
- '''Restores cursor position after a Save Cursor.'''
+
+ """Restores cursor position after a Save Cursor."""
+
self.cursor_restore_attrs()
+
def cursor_save_attrs (self): # <ESC>7
- '''Save current cursor position.'''
+
+ """Save current cursor position."""
+
self.cur_saved_r = self.cur_r
self.cur_saved_c = self.cur_c
+
def cursor_restore_attrs (self): # <ESC>8
- '''Restores cursor position after a Save Cursor.'''
+
+ """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.'''
+
+ """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): # <ESC>[r
- '''Enable scrolling for entire display.'''
+
+ """Enable scrolling for entire display."""
+
self.scroll_row_start = 1
self.scroll_row_end = self.rows
+
def scroll_screen_rows (self, rs, re): # <ESC>[{start};{end}r
- '''Enable scrolling from row {start} to row {end}.'''
+
+ """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): # <ESC>D
- '''Scroll display down one line.'''
+
+ """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): # <ESC>M
- '''Scroll display up one line.'''
+
+ """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): # <ESC>[0K -or- <ESC>[K
- '''Erases from the current cursor position to
- the end of the current line.'''
+
+ """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): # <ESC>[1K
- '''Erases from the current cursor position to
- the start of the current line.'''
+
+ """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): # <ESC>[2K
- '''Erases the entire current line.'''
+
+ """Erases the entire current line."""
+
self.fill_region (self.cur_r, 1, self.cur_r, self.cols)
+
def erase_down (self): # <ESC>[0J -or- <ESC>[J
- '''Erases the screen from the current line down to
- the bottom of the screen.'''
+
+ """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): # <ESC>[1J
- '''Erases the screen from the current line up to
- the top of the screen.'''
+
+ """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): # <ESC>[2J
- '''Erases the screen with the background color.'''
+
+ """Erases the screen with the background color."""
+
self.fill ()
def set_tab (self): # <ESC>H
- '''Sets a tab at the current position.'''
+
+ """Sets a tab at the current position."""
+
pass
+
def clear_tab (self): # <ESC>[g
- '''Clears tab at the current position.'''
+
+ """Clears tab at the current position."""
+
pass
+
def clear_all_tabs (self): # <ESC>[3g
- '''Clears all tabs.'''
+
+ """Clears all tabs."""
+
pass
# Insert line Esc [ Pn L
@@ -264,4 +360,3 @@ class screen:
# Delete character Esc [ Pn P
# Scrolling region Esc [ Pn(top);Pn(bot) r
-