summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Kluyver <takowl@gmail.com>2014-01-27 18:26:41 -0800
committerThomas Kluyver <takowl@gmail.com>2014-01-27 18:26:41 -0800
commit1972ab52a651de11246cc2aeaee654dc0f3a8437 (patch)
tree0a69c4857b39c371dcc2ea526709b13a38bc5f39
parent13ec3b0e134159d0168811862a9d7980847ca4e0 (diff)
parent71038acb1aa00a7383147f066001e654ca01716c (diff)
downloadpexpect-1972ab52a651de11246cc2aeaee654dc0f3a8437.tar.gz
Merge pull request #36 from takluyver/pxssh-docs
Pxssh docs
-rw-r--r--doc/api/pxssh.rst15
-rw-r--r--pexpect/pxssh.py112
2 files changed, 66 insertions, 61 deletions
diff --git a/doc/api/pxssh.rst b/doc/api/pxssh.rst
index c3388f0..0b67839 100644
--- a/doc/api/pxssh.rst
+++ b/doc/api/pxssh.rst
@@ -12,18 +12,19 @@ pxssh class
.. automethod:: __init__
- .. attribute:: auto_prompt_reset
+ .. attribute:: PROMPT
- Set this to False to prevent :meth:`login` from setting a unique prompt
- which can easily be located.
+ The regex pattern to search for to find the prompt. If you call :meth:`login`
+ with ``auto_prompt_reset=False``, you must set this attribute manually.
- .. attribute:: PROMPT
+ .. attribute:: force_password
- The regex pattern to search for to find the prompt. If
- :attr:`auto_prompt_reset` is False, you must set this attribute manually.
+ If this is set to True, public key authentication is disabled, forcing the
+ server to ask for a password. Note that the sysadmin can disable password
+ logins, in which case this won't work.
.. automethod:: login
.. automethod:: logout
.. automethod:: prompt
.. automethod:: sync_original_prompt
- .. automethod:: set_unique_prompt \ No newline at end of file
+ .. automethod:: set_unique_prompt
diff --git a/pexpect/pxssh.py b/pexpect/pxssh.py
index a068625..a18076e 100644
--- a/pexpect/pxssh.py
+++ b/pexpect/pxssh.py
@@ -53,20 +53,20 @@ class pxssh (spawn):
hostname = raw_input('hostname: ')
username = raw_input('username: ')
password = getpass.getpass('password: ')
- s.login (hostname, username, password)
- s.sendline ('uptime') # run a command
+ s.login(hostname, username, password)
+ s.sendline('uptime') # run a command
s.prompt() # match the prompt
- print s.before # print everything before the prompt.
- s.sendline ('ls -l')
+ print(s.before) # print everything before the prompt.
+ s.sendline('ls -l')
s.prompt()
- print s.before
- s.sendline ('df')
+ print(s.before)
+ s.sendline('df')
s.prompt()
- print s.before
+ print(s.before)
s.logout()
- except pxssh.ExceptionPxssh, e:
- print "pxssh failed on login."
- print str(e)
+ except pxssh.ExceptionPxssh as e:
+ print("pxssh failed on login.")
+ print(e)
Note that if you have ssh-agent running while doing development with pxssh
then this can lead to a lot of confusion. Many X display managers (xdm,
@@ -85,7 +85,8 @@ class pxssh (spawn):
s.login (hostname, username, password)
'''
- def __init__ (self, timeout=30, maxread=2000, searchwindowsize=None, logfile=None, cwd=None, env=None):
+ def __init__ (self, timeout=30, maxread=2000, searchwindowsize=None,
+ logfile=None, cwd=None, env=None):
spawn.__init__(self, None, timeout=timeout, maxread=maxread, searchwindowsize=searchwindowsize, logfile=logfile, cwd=cwd, env=env)
@@ -118,10 +119,8 @@ class pxssh (spawn):
# Unsetting SSH_ASKPASS on the remote side doesn't disable it! Annoying!
#self.SSH_OPTS = "-x -o'RSAAuthentication=no' -o 'PubkeyAuthentication=no'"
self.force_password = False
- self.auto_prompt_reset = True
-
- def levenshtein_distance(self, a,b):
+ def levenshtein_distance(self, a, b):
'''This calculates the Levenshtein distance between a and b.
'''
@@ -141,7 +140,6 @@ class pxssh (spawn):
return current[n]
def try_read_prompt(self, timeout_multiplier):
-
'''This facilitates using communication timeouts to perform
synchronization as quickly as possible, while supporting high latency
connections with a tunable worst case performance. Fast connections
@@ -174,7 +172,6 @@ class pxssh (spawn):
return prompt
def sync_original_prompt (self, sync_multiplier=1.0):
-
'''This attempts to find the prompt. Basically, press enter and record
the response; press enter again and record the response; if the two
responses are similar then assume we are at the original prompt.
@@ -214,9 +211,13 @@ class pxssh (spawn):
### TODO: This is getting messy and I'm pretty sure this isn't perfect.
### TODO: I need to draw a flow chart for this.
- def login (self,server,username,password='',terminal_type='ansi',original_prompt=r"[#$]",login_timeout=10,port=None,auto_prompt_reset=True,ssh_key=None,quiet=True,sync_multiplier=1,check_local_ip=True):
+ def login (self, server, username, password='', terminal_type='ansi',
+ original_prompt=r"[#$]", login_timeout=10, port=None,
+ auto_prompt_reset=True, ssh_key=None, quiet=True,
+ sync_multiplier=1, check_local_ip=True):
+ '''This logs the user into the given server.
- '''This logs the user into the given server. It uses the
+ It uses
'original_prompt' to try to find the prompt right after login. When it
finds the prompt it immediately tries to reset the prompt to something
more easily matched. The default 'original_prompt' is very optimistic
@@ -224,7 +225,7 @@ class pxssh (spawn):
prompt as exactly as possible to prevent false matches by server
strings such as the "Message Of The Day". On many systems you can
disable the MOTD on the remote server by creating a zero-length file
- called "~/.hushlogin" on the remote server. If a prompt cannot be found
+ called :file:`~/.hushlogin` on the remote server. If a prompt cannot be found
then this will not necessarily cause the login to fail. In the case of
a timeout when looking for the prompt we assume that the original
prompt was so weird that we could not match it, so we use a few tricks
@@ -233,11 +234,12 @@ class pxssh (spawn):
then login() raises an :class:`ExceptionPxssh` exception.
In some situations it is not possible or desirable to reset the
- original prompt. In this case, set :attr:`auto_prompt_reset` to False to
+ original prompt. In this case, pass ``auto_prompt_reset=False`` to
inhibit setting the prompt to the UNIQUE_PROMPT. Remember that pxssh
- uses a unique prompt in the prompt() method. If the original prompt is
- not reset then this will disable the prompt() method unless you
- manually set the PROMPT attribute. '''
+ uses a unique prompt in the :meth:`prompt` method. If the original prompt is
+ not reset then this will disable the :meth:`prompt` method unless you
+ manually set the :attr:`PROMPT` attribute.
+ '''
ssh_options = ''
if quiet:
@@ -252,7 +254,7 @@ class pxssh (spawn):
try:
os.path.isfile(ssh_key)
except:
- raise ExceptionPxssh ('private ssh key does not exist')
+ raise ExceptionPxssh('private ssh key does not exist')
ssh_options = ssh_options + ' -i %s' % (ssh_key)
cmd = "ssh %s -l %s %s" % (ssh_options, username, server)
@@ -279,7 +281,7 @@ class pxssh (spawn):
if i==0:
# This is weird. This should not happen twice in a row.
self.close()
- raise ExceptionPxssh ('Weird error. Got "are you sure" prompt twice.')
+ raise ExceptionPxssh('Weird error. Got "are you sure" prompt twice.')
elif i==1: # can occur if you have a public key pair set to authenticate.
### TODO: May NOT be OK if expect() got tricked and matched a false prompt.
pass
@@ -289,13 +291,13 @@ class pxssh (spawn):
# If we get the password prompt again then this means
# we didn't get the password right the first time.
self.close()
- raise ExceptionPxssh ('password refused')
+ raise ExceptionPxssh('password refused')
elif i==3: # permission denied -- password was bad.
self.close()
- raise ExceptionPxssh ('permission denied')
+ raise ExceptionPxssh('permission denied')
elif i==4: # terminal type again? WTF?
self.close()
- raise ExceptionPxssh ('Weird error. Got "terminal type" prompt twice.')
+ raise ExceptionPxssh('Weird error. Got "terminal type" prompt twice.')
elif i==5: # Timeout
#This is tricky... I presume that we are at the command-line prompt.
#It may be that the shell prompt was so weird that we couldn't match
@@ -306,26 +308,26 @@ class pxssh (spawn):
pass
elif i==6: # Connection closed by remote host
self.close()
- raise ExceptionPxssh ('connection closed')
+ raise ExceptionPxssh('connection closed')
else: # Unexpected
self.close()
- raise ExceptionPxssh ('unexpected login response')
+ raise ExceptionPxssh('unexpected login response')
if not self.sync_original_prompt(sync_multiplier):
self.close()
- raise ExceptionPxssh ('could not synchronize with original prompt')
+ raise ExceptionPxssh('could not synchronize with original prompt')
# We appear to be in.
# set shell prompt to something unique.
if auto_prompt_reset:
if not self.set_unique_prompt():
self.close()
- raise ExceptionPxssh ('could not set shell prompt\n'+self.before)
+ raise ExceptionPxssh('could not set shell prompt\n'+self.before)
return True
def logout (self):
+ '''Sends exit to the remote shell.
- '''This sends exit to the remote shell. If there are stopped jobs then
- this automatically sends exit twice. '''
-
+ If there are stopped jobs then this automatically sends exit twice.
+ '''
self.sendline("exit")
index = self.expect([EOF, "(?i)there are stopped jobs"])
if index==1:
@@ -333,18 +335,21 @@ class pxssh (spawn):
self.expect(EOF)
self.close()
- def prompt (self, timeout=-1):
+ def prompt(self, timeout=-1):
+ '''Match the next shell prompt.
- '''This matches the shell prompt. This is little more than a short-cut
- to the expect() method. This returns True if the shell prompt was
- matched. This returns False if a timeout was raised. Note that if you
- called :meth:`login` with :attr:`auto_prompt_reset` set to False then
- before calling :meth:`prompt` you must set the :attr:`PROMPT` attribute
- to a regex that it will use for matching the prompt.
+ This is little more than a short-cut to the :meth:`~pexpect.spawn.expect`
+ method. Note that if you called :meth:`login` with
+ ``auto_prompt_reset=False``, then before calling :meth:`prompt` you must
+ set the :attr:`PROMPT` attribute to a regex that it will use for
+ matching the prompt.
Calling :meth:`prompt` will erase the contents of the :attr:`before`
attribute even if no prompt is ever matched. If timeout is not given or
it is set to -1 then self.timeout is used.
+
+ :return: True if the shell prompt was matched, False if the timeout was
+ reached.
'''
if timeout == -1:
@@ -354,9 +359,8 @@ class pxssh (spawn):
return False
return True
- def set_unique_prompt (self):
-
- '''This sets the remote prompt to something more unique than # or $.
+ def set_unique_prompt(self):
+ '''This sets the remote prompt to something more unique than ``#`` or ``$``.
This makes it easier for the :meth:`prompt` method to match the shell prompt
unambiguously. This method is called automatically by the :meth:`login`
method, but you may want to call it manually if you somehow reset the
@@ -365,18 +369,18 @@ class pxssh (spawn):
the remote host to set the prompt, so this assumes the remote host is
ready to receive commands.
- Alternatively, you may use your own prompt pattern. Just set the PROMPT
- attribute to a regular expression that matches it. In this case you
- should call login() with auto_prompt_reset=False; then set the PROMPT
- attribute. After that the prompt() method will try to match your prompt
- pattern.'''
+ Alternatively, you may use your own prompt pattern. In this case you
+ should call :meth:`login` with ``auto_prompt_reset=False``; then set the
+ :attr:`PROMPT` attribute to a regular expression. After that, the
+ :meth:`prompt` method will try to match your prompt pattern.
+ '''
- self.sendline ("unset PROMPT_COMMAND")
- self.sendline (self.PROMPT_SET_SH) # sh-style
+ self.sendline("unset PROMPT_COMMAND")
+ self.sendline(self.PROMPT_SET_SH) # sh-style
i = self.expect ([TIMEOUT, self.PROMPT], timeout=10)
if i == 0: # csh-style
- self.sendline (self.PROMPT_SET_CSH)
- i = self.expect ([TIMEOUT, self.PROMPT], timeout=10)
+ self.sendline(self.PROMPT_SET_CSH)
+ i = self.expect([TIMEOUT, self.PROMPT], timeout=10)
if i == 0:
return False
return True