summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Kluyver <takowl@gmail.com>2013-12-03 12:37:53 -0800
committerThomas Kluyver <takowl@gmail.com>2013-12-03 12:37:53 -0800
commitc1ee1ae113f701a2952228c0cf1c7331e6ff19ed (patch)
tree24eb44e3d08fba199265a84b5843beb32272417c
parent5caa22112a11f2cabdacd8302536580012a2bf98 (diff)
parent0c1bcae869c7fd9607f187c828de5eb2a2d7bbe5 (diff)
downloadpexpect-c1ee1ae113f701a2952228c0cf1c7331e6ff19ed.tar.gz
Merge pull request #26 from takluyver/examples-cleanup-1
Remove unhelpful examples
-rw-r--r--doc/examples.rst16
-rwxr-xr-xexamples/bd_client.py61
-rwxr-xr-xexamples/bd_serv.py338
-rwxr-xr-xexamples/fix_cvs_files.py115
-rwxr-xr-xexamples/rippy.py999
-rwxr-xr-xexamples/ssh_session.py120
-rwxr-xr-xexamples/sshls.py84
7 files changed, 0 insertions, 1733 deletions
diff --git a/doc/examples.rst b/doc/examples.rst
index cb89904..6338b5c 100644
--- a/doc/examples.rst
+++ b/doc/examples.rst
@@ -29,12 +29,6 @@ Examples.
This will start a subshell and log all input and output to a file.
This demonstrates the :meth:`~pexpect.spawn.interact` method of Pexpect.
-`fix_cvs_files.py <https://github.com/pexpect/pexpect/blob/master/examples/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 <https://github.com/pexpect/pexpect/blob/master/examples/ftp.py>`_
This demonstrates an FTP "bookmark". This connects to an ftp site;
does a few ftp tasks; and then gives the user interactive control over
@@ -57,16 +51,6 @@ Examples.
backwards. It then gives the user iteractive control of Python. It's
pretty useless!
-`rippy.py <https://github.com/pexpect/pexpect/blob/master/examples/rippy.py>`_
- This is a wizard for mencoder. It greatly simplifies the process of
- ripping a DVD to Divx (mpeg4) format. It can transcode from any video
- file to another. It has options for resampling the audio stream;
- removing interlace artifacts, fitting to a target file size, etc.
- There are lots of options, but the process is simple and easy to use.
-
-`sshls.py <https://github.com/pexpect/pexpect/blob/master/examples/sshls.py>`_
- This lists a directory on a remote machine.
-
`ssh_tunnel.py <https://github.com/pexpect/pexpect/blob/master/examples/ssh_tunnel.py>`_
This starts an SSH tunnel to a remote machine. It monitors the
connection and restarts the tunnel if it goes down.
diff --git a/examples/bd_client.py b/examples/bd_client.py
deleted file mode 100755
index 8be01f7..0000000
--- a/examples/bd_client.py
+++ /dev/null
@@ -1,61 +0,0 @@
-#!/usr/bin/env python
-
-'''This is a very simple client for the backdoor daemon. This is intended more
-for testing rather than normal use. See bd_serv.py
-
-PEXPECT LICENSE
-
- This license is approved by the OSI and FSF as GPL-compatible.
- http://opensource.org/licenses/isc-license.txt
-
- Copyright (c) 2012, Noah Spurrier <noah@noah.org>
- PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
- PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
- COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-'''
-
-from __future__ import print_function
-
-from __future__ import absolute_import
-
-import socket
-import sys, time, 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()
-
diff --git a/examples/bd_serv.py b/examples/bd_serv.py
deleted file mode 100755
index d4bb4ea..0000000
--- a/examples/bd_serv.py
+++ /dev/null
@@ -1,338 +0,0 @@
-#!/usr/bin/env python
-
-'''Back door shell server
-
-This exposes an shell terminal on a socket.
-
- --hostname : sets the remote host name to open an ssh connection to.
- --username : sets the user name to login with
- --password : (optional) sets the password to login with
- --port : set the local port for the server to listen on
- --watch : show the virtual screen after each client request
-
-PEXPECT LICENSE
-
- This license is approved by the OSI and FSF as GPL-compatible.
- http://opensource.org/licenses/isc-license.txt
-
- Copyright (c) 2012, Noah Spurrier <noah@noah.org>
- PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
- PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
- COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-'''
-
-from __future__ import print_function
-
-from __future__ import absolute_import
-
-# 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, pexpect, ANSI
-import time, sys, os, getopt, getpass, traceback, threading, 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:", end=' ')
- print((time.time() - start_time) / 60.0)
- except Exception as e:
- print(str(e))
- tb_dump = traceback.format_exc()
- print(str(tb_dump))
-
diff --git a/examples/fix_cvs_files.py b/examples/fix_cvs_files.py
deleted file mode 100755
index 23ba89b..0000000
--- a/examples/fix_cvs_files.py
+++ /dev/null
@@ -1,115 +0,0 @@
-#!/usr/bin/env python
-
-'''This is for cleaning up binary files improperly added to CVS. This script
-scans the given path to find binary files; checks with CVS to see if the sticky
-options are set to -kb; finally if sticky options are not -kb then uses 'cvs
-admin' to set the -kb option.
-
-This script ignores CVS directories, symbolic links, and files not known under
-CVS control (cvs status is 'Unknown').
-
-Run this on a CHECKED OUT module sandbox, not on the repository itself. After
-if fixes the sticky options on any files you should manually do a 'cvs commit'
-to accept the changes. Then be sure to have all users do a 'cvs up -A' to
-update the Sticky Option status.
-
-Noah Spurrier
-20030426
-
-PEXPECT LICENSE
-
- This license is approved by the OSI and FSF as GPL-compatible.
- http://opensource.org/licenses/isc-license.txt
-
- Copyright (c) 2012, Noah Spurrier <noah@noah.org>
- PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
- PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
- COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-'''
-
-from __future__ import absolute_import
-from __future__ import print_function
-
-import os, sys, time
-import pexpect
-
-VERBOSE = 1
-
-def is_binary (filename):
-
- '''Assume that any file with a character where the 8th bit is set is
- binary. '''
-
- fin = open(filename, 'rb')
- wholething = fin.read()
- fin.close()
- for c in wholething:
- if ord(c) & 0x80:
- return 1
- return 0
-
-def is_kb_sticky (filename):
-
- '''This checks if 'cvs status' reports '-kb' for Sticky options. If the
- Sticky Option status is '-ks' then this returns 1. If the status is
- 'Unknown' then it returns 1. Otherwise 0 is returned. '''
-
- try:
- s = pexpect.spawn ('cvs status %s' % filename)
- i = s.expect (['Sticky Options:\s*(.*)\r\n', 'Status: Unknown'])
- if i==1 and VERBOSE:
- print('File not part of CVS repository:', filename)
- return 1 # Pretend it's OK.
- if s.match.group(1) == '-kb':
- return 1
- s = None
- except:
- print('Something went wrong trying to run external cvs command.')
- print(' cvs status %s' % filename)
- print('The cvs command returned:')
- print(s.before)
- return 0
-
-def cvs_admin_kb (filename):
-
- '''This uses 'cvs admin' to set the '-kb' sticky option. '''
-
- s = pexpect.run ('cvs admin -kb %s' % filename)
- # There is a timing issue. If I run 'cvs admin' too quickly
- # cvs sometimes has trouble obtaining the directory lock.
- time.sleep(1)
-
-def walk_and_clean_cvs_binaries (arg, dirname, names):
-
- '''This contains the logic for processing files. This is the os.path.walk
- callback. This skips dirnames that end in CVS. '''
-
- if len(dirname)>3 and dirname[-3:]=='CVS':
- return
- for n in names:
- fullpath = os.path.join (dirname, n)
- if os.path.isdir(fullpath) or os.path.islink(fullpath):
- continue
- if is_binary(fullpath):
- if not is_kb_sticky (fullpath):
- if VERBOSE: print(fullpath)
- cvs_admin_kb (fullpath)
-
-def main ():
-
- if len(sys.argv) == 1:
- root = '.'
- else:
- root = sys.argv[1]
- os.path.walk (root, walk_and_clean_cvs_binaries, None)
-
-if __name__ == '__main__':
- main ()
diff --git a/examples/rippy.py b/examples/rippy.py
deleted file mode 100755
index 4e8ed3d..0000000
--- a/examples/rippy.py
+++ /dev/null
@@ -1,999 +0,0 @@
-#!/usr/bin/env python
-
-'''Rippy!
-
-This is old and probably does not work anymore.
-This script helps to convert video from one format to another.
-This is useful for ripping DVD to mpeg4 video (XviD, DivX).
-
-Features:
- * automatic crop detection
- * mp3 audio compression with resampling options
- * automatic bitrate calculation based on desired target size
- * optional interlace removal, b/w video optimization, video scaling
-
-Run the script with no arguments to start with interactive prompts:
- rippy.py
-Run the script with the filename of a config to start automatic mode:
- rippy.py rippy.conf
-
-After Rippy is finished it saves the current configuation in a file called
-'rippy.conf' in the local directoy. This can be used to rerun process using the
-exact same settings by passing the filename of the conf file as an argument to
-Rippy. Rippy will read the options from the file instead of asking you for
-options interactively. So if you run rippy with 'dry_run=1' then you can run
-the process again later using the 'rippy.conf' file. Don't forget to edit
-'rippy.conf' to set 'dry_run=0'!
-
-If you run rippy with 'dry_run' and 'verbose' true then the output generated is
-valid command line commands. you could (in theory) cut-and-paste the commands
-to a shell prompt. You will need to tweak some values such as crop area and bit
-rate because these cannot be calculated in a dry run. This is useful if you
-want to get an idea of what Rippy plans to do.
-
-For all the trouble that Rippy goes through to calculate the best bitrate for a
-desired target video size it sometimes fails to get it right. Sometimes the
-final video size will differ more than you wanted from the desired size, but if
-you are really motivated and have a lot of time on your hands then you can run
-Rippy again with a manually calculated bitrate. After all compression is done
-the first time Rippy will recalculate the bitrate to give you the nearly exact
-bitrate that would have worked. You can then edit the 'rippy.conf' file; set
-the video_bitrate with this revised bitrate; and then run Rippy all over again.
-There is nothing like 4-pass video compression to get it right! Actually, this
-could be done in three passes since I don't need to do the second pass
-compression before I calculate the revised bitrate. I'm also considering an
-enhancement where Rippy would compress ten spread out chunks, 1-minute in
-length to estimate the bitrate.
-
-PEXPECT LICENSE
-
- This license is approved by the OSI and FSF as GPL-compatible.
- http://opensource.org/licenses/isc-license.txt
-
- Copyright (c) 2012, Noah Spurrier <noah@noah.org>
- PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
- PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
- COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-'''
-
-from __future__ import print_function
-
-from __future__ import absolute_import
-
-import sys, os, re, math, stat, getopt, traceback, types, time
-import pexpect
-
-
-try:
- raw_input
-except NameError:
- raw_input = input
-
-
-__version__ = '1.2'
-__revision__ = '$Revision: 11 $'
-__all__ = ['main', __version__, __revision__]
-
-GLOBAL_LOGFILE_NAME = "rippy_%d.log" % os.getpid()
-GLOBAL_LOGFILE = open (GLOBAL_LOGFILE_NAME, "wb")
-
-###############################################################################
-# This giant section defines the prompts and defaults used in interactive mode.
-###############################################################################
-# Python dictionaries are unordered, so
-# I have this list that maintains the order of the keys.
-prompts_key_order = (
-'verbose_flag',
-'dry_run_flag',
-'video_source_filename',
-'video_chapter',
-'video_final_filename',
-'video_length',
-'video_aspect_ratio',
-'video_scale',
-'video_encode_passes',
-'video_codec',
-'video_fourcc_override',
-'video_bitrate',
-'video_bitrate_overhead',
-'video_target_size',
-'video_deinterlace_flag',
-'video_crop_area',
-'video_gray_flag',
-'subtitle_id',
-'audio_id',
-'audio_codec',
-'audio_raw_filename',
-'audio_volume_boost',
-'audio_sample_rate',
-'audio_bitrate',
-#'audio_lowpass_filter',
-'delete_tmp_files_flag'
-)
-#
-# The 'prompts' dictionary holds all the messages shown to the user in
-# interactive mode. The 'prompts' dictionary schema is defined as follows:
-# prompt_key : ( default value, prompt string, help string, level of difficulty (0,1,2) )
-#
-prompts = {
-'video_source_filename':("dvd://1", 'video source filename?', '''This is the filename of the video that you want to convert from.
-It can be any file that mencoder supports.
-You can also choose a DVD device using the dvd://1 syntax.
-Title 1 is usually the main title on a DVD.''',0),
-'video_chapter':("none",'video chapter?','''This is the chapter number. Usually disks such as TV series seasons will be divided into chapters. Maybe be set to none.''',0),
-'video_final_filename':("video_final.avi", "video final filename?", '''This is the name of the final video.''',0),
-'audio_raw_filename':("audiodump.wav", "audio raw filename?", '''This is the audio raw PCM filename. This is prior to compression.
-Note that mplayer automatically names this audiodump.wav, so don't change this.''',1000),
-#'audio_compressed_filename':("audiodump.mp3","Audio compressed filename?", '''This is the name of the compressed audio that will be mixed
-#into the final video. Normally you don't need to change this.''',2),
-'video_length':("none","video length in seconds?",'''This sets the length of the video in seconds. This is used to estimate the
-bitrate for a target video file size. Set to 'calc' to have Rippy calculate
-the length. Set to 'none' if you don't want rippy to estimate the bitrate --
-you will have to manually specify bitrate.''',1),
-'video_aspect_ratio':("calc","aspect ratio?",'''This sets the aspect ratio of the video. Most DVDs are 16/9 or 4/3.''',1),
-'video_scale':("none","video scale?",'''This scales the video to the given output size. The default is to do no scaling.
-You may type in a resolution such as 320x240 or you may use presets.
- qntsc: 352x240 (NTSC quarter screen)
- qpal: 352x288 (PAL quarter screen)
- ntsc: 720x480 (standard NTSC)
- pal: 720x576 (standard PAL)
- sntsc: 640x480 (square pixel NTSC)
- spal: 768x576 (square pixel PAL)''',1),
-'video_codec':("mpeg4","video codec?",'''This is the video compression to use. This is passed directly to mencoder, so
-any format that it recognizes should work. For XviD or DivX use mpeg4.
-Almost all MS Windows systems support wmv2 out of the box.
-Some common codecs include:
-mjpeg, h263, h263p, h264, mpeg4, msmpeg4, wmv1, wmv2, mpeg1video, mpeg2video, huffyuv, ffv1.
-''',2),
-'audio_codec':("mp3","audio codec?",'''This is the audio compression to use. This is passed directly to mencoder, so
-any format that it recognizes will work.
-Some common codecs include:
-mp3, mp2, aac, pcm
-See mencoder manual for details.''',2),
-'video_fourcc_override':("XVID","force fourcc code?",'''This forces the fourcc codec to the given value. XVID is safest for Windows.
-The following are common fourcc values:
- FMP4 - This is the mencoder default. This is the "real" value.
- XVID - used by Xvid (safest)
- DX50 -
- MP4S - Microsoft''',2),
-'video_encode_passes':("1","number of encode passes?",'''This sets how many passes to use to encode the video. You can choose 1 or 2.
-Using two pases takes twice as long as one pass, but produces a better
-quality video. I found that the improvement is not that impressive.''',1),
-'verbose_flag':("Y","verbose output?",'''This sets verbose output. If true then all commands and arguments are printed
-before they are run. This is useful to see exactly how commands are run.''',1),
-'dry_run_flag':("N","dry run?",'''This sets 'dry run' mode. If true then commands are not run. This is useful
-if you want to see what would the script would do.''',1),
-'video_bitrate':("calc","video bitrate?",'''This sets the video bitrate. This overrides video_target_size.
-Set to 'calc' to automatically estimate the bitrate based on the
-video final target size. If you set video_length to 'none' then
-you will have to specify this video_bitrate.''',1),
-'video_target_size':("737280000","video final target size?",'''This sets the target video size that you want to end up with.
-This is over-ridden by video_bitrate. In other words, if you specify
-video_bitrate then video_target_size is ignored.
-Due to the unpredictable nature of VBR compression the final video size
-may not exactly match. The following are common CDR sizes:
- 180MB CDR (21 minutes) holds 193536000 bytes
- 550MB CDR (63 minutes) holds 580608000 bytes
- 650MB CDR (74 minutes) holds 681984000 bytes
- 700MB CDR (80 minutes) holds 737280000 bytes''',0),
-'video_bitrate_overhead':("1.0","bitrate overhead factor?",'''Adjust this value if you want to leave more room for
-other files such as subtitle files.
-If you specify video_bitrate then this value is ignored.''',2),
-'video_crop_area':("detect","crop area?",'''This sets the crop area to remove black bars from the top or sides of the video.
-This helps save space. Set to 'detect' to automatically detect the crop area.
-Set to 'none' to not crop the video. Normally you don't need to change this.''',1),
-'video_deinterlace_flag':("N","is the video interlaced?",'''This sets the deinterlace flag. If set then mencoder will be instructed
-to filter out interlace artifacts (using '-vf pp=md').''',1),
-'video_gray_flag':("N","is the video black and white (gray)?",'''This improves output for black and white video.''',1),
-'subtitle_id':("None","Subtitle ID stream?",'''This selects the subtitle stream to extract from the source video.
-Normally, 0 is the English subtitle stream for a DVD.
-Subtitles IDs with higher numbers may be other languages.''',1),
-'audio_id':("128","audio ID stream?",'''This selects the audio stream to extract from the source video.
-If your source is a VOB file (DVD) then stream IDs start at 128.
-Normally, 128 is the main audio track for a DVD.
-Tracks with higher numbers may be other language dubs or audio commentary.''',1),
-'audio_sample_rate':("32000","audio sample rate (Hz) 48000, 44100, 32000, 24000, 12000",'''This sets the rate at which the compressed audio will be resampled.
-DVD audio is 48 kHz whereas music CDs use 44.1 kHz. The higher the sample rate
-the more space the audio track will take. That will leave less space for video.
-32 kHz is a good trade-off if you are trying to fit a video onto a CD.''',1),
-'audio_bitrate':("96","audio bitrate (kbit/s) 192, 128, 96, 64?",'''This sets the bitrate for MP3 audio compression.
-The higher the bitrate the more space the audio track will take.
-That will leave less space for video. Most people find music to be acceptable
-at 128 kBitS. 96 kBitS is a good trade-off if you are trying to fit a video onto a CD.''',1),
-'audio_volume_boost':("none","volume dB boost?",'''Many DVDs have very low audio volume. This sets an audio volume boost in Decibels.
-Values of 6 to 10 usually adjust quiet DVDs to a comfortable level.''',1),
-#'audio_lowpass_filter':("16","audio lowpass filter (kHz)?",'''This sets the low-pass filter for the audio.
-#Normally this should be half of the audio sample rate.
-#This improves audio compression and quality.
-#Normally you don't need to change this.''',1),
-'delete_tmp_files_flag':("N","delete temporary files when finished?",'''If Y then %s, audio_raw_filename, and 'divx2pass.log' will be deleted at the end.'''%GLOBAL_LOGFILE_NAME,1)
-}
-
-##############################################################################
-# This is the important convert control function
-##############################################################################
-def convert (options):
- '''This is the heart of it all -- this performs an end-to-end conversion of
- a video from one format to another. It requires a dictionary of options.
- The conversion process will also add some keys to the dictionary
- such as length of the video and crop area. The dictionary is returned.
- This options dictionary could be used again to repeat the convert process
- (it is also saved to rippy.conf as text).
- '''
- if options['subtitle_id'] is not None:
- print("# extract subtitles")
- apply_smart (extract_subtitles, options)
- else:
- print("# do not extract subtitles.")
-
- # Optimization
- # I really only need to calculate the exact video length if the user
- # selected 'calc' for video_bitrate
- # or
- # selected 'detect' for video_crop_area.
- if options['video_bitrate']=='calc' or options['video_crop_area']=='detect':
- # As strange as it seems, the only reliable way to calculate the length
- # of a video (in seconds) is to extract the raw, uncompressed PCM audio stream
- # and then calculate the length of that. This is because MP4 video is VBR, so
- # you cannot get exact time based on compressed size.
- if options['video_length']=='calc':
- print("# extract PCM raw audio to %s" % (options['audio_raw_filename']))
- apply_smart (extract_audio, options)
- options['video_length'] = apply_smart (get_length, options)
- print("# Length of raw audio file : %d seconds (%0.2f minutes)" % (options['video_length'], float(options['video_length'])/60.0))
- if options['video_bitrate']=='calc':
- options['video_bitrate'] = options['video_bitrate_overhead'] * apply_smart (calc_video_bitrate, options)
- print("# video bitrate : " + str(options['video_bitrate']))
- if options['video_crop_area']=='detect':
- options['video_crop_area'] = apply_smart (crop_detect, options)
- print("# crop area : " + str(options['video_crop_area']))
- print("# compression estimate")
- print(apply_smart (compression_estimate, options))
-
- print("# compress video")
- apply_smart (compress_video, options)
- 'audio_volume_boost',
-
- print("# delete temporary files:", end=' ')
- if options['delete_tmp_files_flag']:
- print("yes")
- apply_smart (delete_tmp_files, options)
- else:
- print("no")
-
- # Finish by saving options to rippy.conf and
- # calclating if final_size is less than target_size.
- o = ["# options used to create video\n"]
- video_actual_size = get_filesize (options['video_final_filename'])
- if options['video_target_size'] != 'none':
- revised_bitrate = calculate_revised_bitrate (options['video_bitrate'], options['video_target_size'], video_actual_size)
- o.append("# revised video_bitrate : %d\n" % revised_bitrate)
- for k,v in options.items():
- o.append (" %30s : %s\n" % (k, v))
- print('# '.join(o))
- fout = open("rippy.conf","wb").write(''.join(o))
- print("# final actual video size = %d" % video_actual_size)
- if options['video_target_size'] != 'none':
- if video_actual_size > options['video_target_size']:
- print("# FINAL VIDEO SIZE IS GREATER THAN DESIRED TARGET")
- print("# final video size is %d bytes over target size" % (video_actual_size - options['video_target_size']))
- else:
- print("# final video size is %d bytes under target size" % (options['video_target_size'] - video_actual_size))
- print("# If you want to run the entire compression process all over again")
- print("# to get closer to the target video size then trying using a revised")
- print("# video_bitrate of %d" % revised_bitrate)
-
- return options
-
-##############################################################################
-
-def exit_with_usage(exit_code=1):
- print(globals()['__doc__'])
- print('version:', globals()['__version__'])
- sys.stdout.flush()
- os._exit(exit_code)
-
-def check_missing_requirements ():
- '''This list of missing requirements (mencoder, mplayer, lame, and mkvmerge).
- Returns None if all requirements are in the execution path.
- '''
- missing = []
- if pexpect.which("mencoder") is None:
- missing.append("mencoder")
- if pexpect.which("mplayer") is None:
- missing.append("mplayer")
- cmd = "mencoder -oac help"
- (command_output, exitstatus) = run(cmd)
- ar = re.findall("(mp3lame)", command_output)
- if len(ar)==0:
- missing.append("Mencoder was not compiled with mp3lame support.")
-
- #if pexpect.which("lame") is None:
- # missing.append("lame")
- #if pexpect.which("mkvmerge") is None:
- # missing.append("mkvmerge")
- if len(missing)==0:
- return None
- return missing
-
-def input_option (message, default_value="", help=None, level=0, max_level=0):
- '''This is a fancy raw_input function.
- If the user enters '?' then the contents of help is printed.
-
- The 'level' and 'max_level' are used to adjust which advanced options
- are printed. 'max_level' is the level of options that the user wants
- to see. 'level' is the level of difficulty for this particular option.
- If this level is <= the max_level the user wants then the
- message is printed and user input is allowed; otherwise, the
- default value is returned automatically without user input.
- '''
- if default_value != '':
- message = "%s [%s] " % (message, default_value)
- if level > max_level:
- return default_value
- while 1:
- user_input = raw_input (message)
- if user_input=='?':
- print(help)
- elif user_input=='':
- return default_value
- else:
- break
- return user_input
-
-def progress_callback (d=None):
- '''This callback simply prints a dot to show activity.
- This is used when running external commands with pexpect.run.
- '''
- sys.stdout.write (".")
- sys.stdout.flush()
-
-def run(cmd):
- global GLOBAL_LOGFILE
- print(cmd, file=GLOBAL_LOGFILE)
- (command_output, exitstatus) = pexpect.run(cmd, events={pexpect.TIMEOUT:progress_callback}, timeout=5, withexitstatus=True, logfile=GLOBAL_LOGFILE)
- if exitstatus != 0:
- print("RUN FAILED. RETURNED EXIT STATUS:", exitstatus)
- print("RUN FAILED. RETURNED EXIT STATUS:", exitstatus, file=GLOBAL_LOGFILE)
- return (command_output, exitstatus)
-
-def apply_smart (func, args):
- '''This is similar to func(**args), but this won't complain about
- extra keys in 'args'. This ignores keys in 'args' that are
- not required by 'func'. This passes None to arguments that are
- not defined in 'args'. That's fine for arguments with a default valeue, but
- that's a bug for required arguments. I should probably raise a TypeError.
- The func parameter can be a function reference or a string.
- If it is a string then it is converted to a function reference.
- '''
- if type(func) is type(''):
- if func in globals():
- func = globals()[func]
- else:
- raise NameError("name '%s' is not defined" % func)
- if hasattr(func, '__func__'): # Handle case when func is a class method.
- func = func.__func__
- argcount = func.__code__.co_argcount
- required_args = dict([(k,args.get(k)) for k in func.__code__.co_varnames[:argcount]])
- return func(**required_args)
-
-def count_unique (items):
- '''This takes a list and returns a sorted list of tuples with a count of each unique item in the list.
- Example 1:
- count_unique(['a','b','c','a','c','c','a','c','c'])
- returns:
- [(5,'c'), (3,'a'), (1,'b')]
- Example 2 -- get the most frequent item in a list:
- count_unique(['a','b','c','a','c','c','a','c','c'])[0][1]
- returns:
- 'c'
- '''
- stats = {}
- for i in items:
- if i in stats:
- stats[i] = stats[i] + 1
- else:
- stats[i] = 1
- stats = [(v, k) for k, v in stats.items()]
- stats.sort()
- stats.reverse()
- return stats
-
-def calculate_revised_bitrate (video_bitrate, video_target_size, video_actual_size):
- '''This calculates a revised video bitrate given the video_bitrate used,
- the actual size that resulted, and the video_target_size.
- This can be used if you want to compress the video all over again in an
- attempt to get closer to the video_target_size.
- '''
- return int(math.floor(video_bitrate * (float(video_target_size) / float(video_actual_size))))
-
-def get_aspect_ratio (video_source_filename):
- '''This returns the aspect ratio of the original video.
- This is usualy 1.78:1(16/9) or 1.33:1(4/3).
- This function is very lenient. It basically guesses 16/9 whenever
- it cannot figure out the aspect ratio.
- '''
- cmd = "mplayer '%s' -vo png -ao null -frames 1" % video_source_filename
- (command_output, exitstatus) = run(cmd)
- ar = re.findall("Movie-Aspect is ([0-9]+\.?[0-9]*:[0-9]+\.?[0-9]*)", command_output)
- if len(ar)==0:
- return '16/9'
- if ar[0] == '1.78:1':
- return '16/9'
- if ar[0] == '1.33:1':
- return '4/3'
- return '16/9'
- #idh = re.findall("ID_VIDEO_HEIGHT=([0-9]+)", command_output)
- #if len(idw)==0 or len(idh)==0:
- # print 'WARNING!'
- # print 'Could not get aspect ration. Assuming 1.78:1 (16/9).'
- # return 1.78
- #return float(idw[0])/float(idh[0])
-#ID_VIDEO_WIDTH=720
-#ID_VIDEO_HEIGHT=480
-#Movie-Aspect is 1.78:1 - prescaling to correct movie aspect.
-
-
-def get_aid_list (video_source_filename):
- '''This returns a list of audio ids in the source video file.
- TODO: Also extract ID_AID_nnn_LANG to associate language. Not all DVDs include this.
- '''
- cmd = "mplayer '%s' -vo null -ao null -frames 0 -identify" % video_source_filename
- (command_output, exitstatus) = run(cmd)
- idl = re.findall("ID_AUDIO_ID=([0-9]+)", command_output)
- idl.sort()
- return idl
-
-def get_sid_list (video_source_filename):
- '''This returns a list of subtitle ids in the source video file.
- TODO: Also extract ID_SID_nnn_LANG to associate language. Not all DVDs include this.
- '''
- cmd = "mplayer '%s' -vo null -ao null -frames 0 -identify" % video_source_filename
- (command_output, exitstatus) = run(cmd)
- idl = re.findall("ID_SUBTITLE_ID=([0-9]+)", command_output)
- idl.sort()
- return idl
-
-def extract_audio (video_source_filename, audio_id=128, verbose_flag=0, dry_run_flag=0):
- '''This extracts the given audio_id track as raw uncompressed PCM from the given source video.
- Note that mplayer always saves this to audiodump.wav.
- At this time there is no way to set the output audio name.
- '''
- #cmd = "mplayer %(video_source_filename)s -vc null -vo null -aid %(audio_id)s -ao pcm:fast -noframedrop" % locals()
- cmd = "mplayer -quiet '%(video_source_filename)s' -vc dummy -vo null -aid %(audio_id)s -ao pcm:fast -noframedrop" % locals()
- if verbose_flag: print(cmd)
- if not dry_run_flag:
- run(cmd)
- print()
-
-def extract_subtitles (video_source_filename, subtitle_id=0, verbose_flag=0, dry_run_flag=0):
- '''This extracts the given subtitle_id track as VOBSUB format from the given source video.
- '''
- cmd = "mencoder -quiet '%(video_source_filename)s' -o /dev/null -nosound -ovc copy -vobsubout subtitles -vobsuboutindex 0 -sid %(subtitle_id)s" % locals()
- if verbose_flag: print(cmd)
- if not dry_run_flag:
- run(cmd)
- print()
-
-def get_length (audio_raw_filename):
- '''This attempts to get the length of the media file (length is time in seconds).
- This should not be confused with size (in bytes) of the file data.
- This is best used on a raw PCM AUDIO file because mplayer cannot get an accurate
- time for many compressed video and audio formats -- notably MPEG4 and MP3.
- Weird...
- This returns -1 if it cannot get the length of the given file.
- '''
- cmd = "mplayer %s -vo null -ao null -frames 0 -identify" % audio_raw_filename
- (command_output, exitstatus) = run(cmd)
- idl = re.findall("ID_LENGTH=([0-9.]*)", command_output)
- idl.sort()
- if len(idl) != 1:
- print("ERROR: cannot get length of raw audio file.")
- print("command_output of mplayer identify:")
- print(command_output)
- print("parsed command_output:")
- print(str(idl))
- return -1
- return float(idl[0])
-
-def get_filesize (filename):
- '''This returns the number of bytes a file takes on storage.'''
- return os.stat(filename)[stat.ST_SIZE]
-
-def calc_video_bitrate (video_target_size, audio_bitrate, video_length, extra_space=0, dry_run_flag=0):
- '''This gives an estimate of the video bitrate necessary to
- fit the final target size. This will take into account room to
- fit the audio and extra space if given (for container overhead or whatnot).
- video_target_size is in bytes,
- audio_bitrate is bits per second (96, 128, 256, etc.) ASSUMING CBR,
- video_length is in seconds,
- extra_space is in bytes.
- a 180MB CDR (21 minutes) holds 193536000 bytes.
- a 550MB CDR (63 minutes) holds 580608000 bytes.
- a 650MB CDR (74 minutes) holds 681984000 bytes.
- a 700MB CDR (80 minutes) holds 737280000 bytes.
- '''
- if dry_run_flag:
- return -1
- if extra_space is None: extra_space = 0
- #audio_size = os.stat(audio_compressed_filename)[stat.ST_SIZE]
- audio_size = (audio_bitrate * video_length * 1000) / 8.0
- video_target_size = video_target_size - audio_size - extra_space
- return (int)(calc_video_kbitrate (video_target_size, video_length))
-
-def calc_video_kbitrate (target_size, length_secs):
- '''Given a target byte size free for video data, this returns the bitrate in kBit/S.
- For mencoder vbitrate 1 kBit = 1000 Bits -- not 1024 bits.
- target_size = bitrate * 1000 * length_secs / 8
- target_size = bitrate * 125 * length_secs
- bitrate = target_size/(125*length_secs)
- '''
- return int(target_size / (125.0 * length_secs))
-
-def crop_detect (video_source_filename, video_length, dry_run_flag=0):
- '''This attempts to figure out the best crop for the given video file.
- Basically it runs crop detect for 10 seconds on five different places in the video.
- It picks the crop area that was most often detected.
- '''
- skip = int(video_length/9) # offset to skip (-ss option in mencoder)
- sample_length = 10
- cmd1 = "mencoder '%s' -quiet -ss %d -endpos %d -o /dev/null -nosound -ovc lavc -vf cropdetect" % (video_source_filename, skip, sample_length)
- cmd2 = "mencoder '%s' -quiet -ss %d -endpos %d -o /dev/null -nosound -ovc lavc -vf cropdetect" % (video_source_filename, 2*skip, sample_length)
- cmd3 = "mencoder '%s' -quiet -ss %d -endpos %d -o /dev/null -nosound -ovc lavc -vf cropdetect" % (video_source_filename, 4*skip, sample_length)
- cmd4 = "mencoder '%s' -quiet -ss %d -endpos %d -o /dev/null -nosound -ovc lavc -vf cropdetect" % (video_source_filename, 6*skip, sample_length)
- cmd5 = "mencoder '%s' -quiet -ss %d -endpos %d -o /dev/null -nosound -ovc lavc -vf cropdetect" % (video_source_filename, 8*skip, sample_length)
- if dry_run_flag:
- return "0:0:0:0"
- (command_output1, exitstatus1) = run(cmd1)
- (command_output2, exitstatus2) = run(cmd2)
- (command_output3, exitstatus3) = run(cmd3)
- (command_output4, exitstatus4) = run(cmd4)
- (command_output5, exitstatus5) = run(cmd5)
- idl = re.findall("-vf crop=([0-9]+:[0-9]+:[0-9]+:[0-9]+)", command_output1)
- idl = idl + re.findall("-vf crop=([0-9]+:[0-9]+:[0-9]+:[0-9]+)", command_output2)
- idl = idl + re.findall("-vf crop=([0-9]+:[0-9]+:[0-9]+:[0-9]+)", command_output3)
- idl = idl + re.findall("-vf crop=([0-9]+:[0-9]+:[0-9]+:[0-9]+)", command_output4)
- idl = idl + re.findall("-vf crop=([0-9]+:[0-9]+:[0-9]+:[0-9]+)", command_output5)
- items_count = count_unique(idl)
- return items_count[0][1]
-
-
-def build_compression_command (video_source_filename, video_final_filename, video_target_size, audio_id=128, video_bitrate=1000, video_codec='mpeg4', audio_codec='mp3', video_fourcc_override='FMP4', video_gray_flag=0, video_crop_area=None, video_aspect_ratio='16/9', video_scale=None, video_encode_passes=2, video_deinterlace_flag=0, audio_volume_boost=None, audio_sample_rate=None, audio_bitrate=None, seek_skip=None, seek_length=None, video_chapter=None):
-#Notes:For DVD, VCD, and SVCD use acodec=mp2 and vcodec=mpeg2video:
-#mencoder movie.avi -o movie.VOB -ovc lavc -oac lavc -lavcopts acodec=mp2:abitrate=224:vcodec=mpeg2video:vbitrate=2000
-
- #
- # build video filter (-vf) argument
- #
- video_filter = ''
- if video_crop_area and video_crop_area.lower()!='none':
- video_filter = video_filter + 'crop=%s' % video_crop_area
- if video_deinterlace_flag:
- if video_filter != '':
- video_filter = video_filter + ','
- video_filter = video_filter + 'pp=md'
- if video_scale and video_scale.lower()!='none':
- if video_filter != '':
- video_filter = video_filter + ','
- video_filter = video_filter + 'scale=%s' % video_scale
- # optional video rotation -- were you holding your camera sideways?
- #if video_filter != '':
- # video_filter = video_filter + ','
- #video_filter = video_filter + 'rotate=2'
- if video_filter != '':
- video_filter = '-vf ' + video_filter
-
- #
- # build chapter argument
- #
- if video_chapter is not None:
- chapter = '-chapter %d-%d' %(video_chapter,video_chapter)
- else:
- chapter = ''
-# chapter = '-chapter 2-2'
-
- #
- # build audio_filter argument
- #
- audio_filter = ''
- if audio_sample_rate:
- if audio_filter != '':
- audio_filter = audio_filter + ','
- audio_filter = audio_filter + 'lavcresample=%s' % audio_sample_rate
- if audio_volume_boost is not None:
- if audio_filter != '':
- audio_filter = audio_filter + ','
- audio_filter = audio_filter + 'volume=%0.1f:1'%audio_volume_boost
- if audio_filter != '':
- audio_filter = '-af ' + audio_filter
- #
- #if audio_sample_rate:
- # audio_filter = ('-srate %d ' % audio_sample_rate) + audio_filter
-
- #
- # build lavcopts argument
- #
- #lavcopts = '-lavcopts vcodec=%s:vbitrate=%d:mbd=2:aspect=%s:acodec=%s:abitrate=%d:vpass=1' % (video_codec,video_bitrate,audio_codec,audio_bitrate)
- lavcopts = '-lavcopts vcodec=%(video_codec)s:vbitrate=%(video_bitrate)d:mbd=2:aspect=%(video_aspect_ratio)s:acodec=%(audio_codec)s:abitrate=%(audio_bitrate)d:vpass=1' % (locals())
- if video_gray_flag:
- lavcopts = lavcopts + ':gray'
-
- seek_filter = ''
- if seek_skip is not None:
- seek_filter = '-ss %s' % (str(seek_skip))
- if seek_length is not None:
- seek_filter = seek_filter + ' -endpos %s' % (str(seek_length))
-
-# cmd = "mencoder -quiet -info comment='Arkivist' '%(video_source_filename)s' %(seek_filter)s %(chapter)s -aid %(audio_id)s -o '%(video_final_filename)s' -ffourcc %(video_fourcc_override)s -ovc lavc -oac lavc %(lavcopts)s %(video_filter)s %(audio_filter)s" % locals()
- cmd = "mencoder -quiet -info comment='Arkivist' '%(video_source_filename)s' %(seek_filter)s %(chapter)s -aid %(audio_id)s -o '%(video_final_filename)s' -ffourcc %(video_fourcc_override)s -ovc lavc -oac mp3lame %(lavcopts)s %(video_filter)s %(audio_filter)s" % locals()
- return cmd
-
-def compression_estimate (video_length, video_source_filename, video_final_filename, video_target_size, audio_id=128, video_bitrate=1000, video_codec='mpeg4', audio_codec='mp3', video_fourcc_override='FMP4', video_gray_flag=0, video_crop_area=None, video_aspect_ratio='16/9', video_scale=None, video_encode_passes=2, video_deinterlace_flag=0, audio_volume_boost=None, audio_sample_rate=None, audio_bitrate=None):
- '''This attempts to figure out the best compression ratio for a given set of compression options.
- '''
- # TODO Need to account for AVI overhead.
- skip = int(video_length/9) # offset to skip (-ss option in mencoder)
- sample_length = 10
- cmd1 = build_compression_command (video_source_filename, "compression_test_1.avi", video_target_size, audio_id, video_bitrate, video_codec, audio_codec, video_fourcc_override, video_gray_flag, video_crop_area, video_aspect_ratio, video_scale, video_encode_passes, video_deinterlace_flag, audio_volume_boost, audio_sample_rate, audio_bitrate, skip, sample_length)
- cmd2 = build_compression_command (video_source_filename, "compression_test_2.avi", video_target_size, audio_id, video_bitrate, video_codec, audio_codec, video_fourcc_override, video_gray_flag, video_crop_area, video_aspect_ratio, video_scale, video_encode_passes, video_deinterlace_flag, audio_volume_boost, audio_sample_rate, audio_bitrate, skip*2, sample_length)
- cmd3 = build_compression_command (video_source_filename, "compression_test_3.avi", video_target_size, audio_id, video_bitrate, video_codec, audio_codec, video_fourcc_override, video_gray_flag, video_crop_area, video_aspect_ratio, video_scale, video_encode_passes, video_deinterlace_flag, audio_volume_boost, audio_sample_rate, audio_bitrate, skip*4, sample_length)
- cmd4 = build_compression_command (video_source_filename, "compression_test_4.avi", video_target_size, audio_id, video_bitrate, video_codec, audio_codec, video_fourcc_override, video_gray_flag, video_crop_area, video_aspect_ratio, video_scale, video_encode_passes, video_deinterlace_flag, audio_volume_boost, audio_sample_rate, audio_bitrate, skip*6, sample_length)
- cmd5 = build_compression_command (video_source_filename, "compression_test_5.avi", video_target_size, audio_id, video_bitrate, video_codec, audio_codec, video_fourcc_override, video_gray_flag, video_crop_area, video_aspect_ratio, video_scale, video_encode_passes, video_deinterlace_flag, audio_volume_boost, audio_sample_rate, audio_bitrate, skip*8, sample_length)
- run(cmd1)
- run(cmd2)
- run(cmd3)
- run(cmd4)
- run(cmd5)
- size = get_filesize ("compression_test_1.avi")+get_filesize ("compression_test_2.avi")+get_filesize ("compression_test_3.avi")+get_filesize ("compression_test_4.avi")+get_filesize ("compression_test_5.avi")
- return (size / 5.0)
-
-def compress_video (video_source_filename, video_final_filename, video_target_size, audio_id=128, video_bitrate=1000, video_codec='mpeg4', audio_codec='mp3', video_fourcc_override='FMP4', video_gray_flag=0, video_crop_area=None, video_aspect_ratio='16/9', video_scale=None, video_encode_passes=2, video_deinterlace_flag=0, audio_volume_boost=None, audio_sample_rate=None, audio_bitrate=None, seek_skip=None, seek_length=None, video_chapter=None, verbose_flag=0, dry_run_flag=0):
- '''This compresses the video and audio of the given source video filename to the transcoded filename.
- This does a two-pass compression (I'm assuming mpeg4, I should probably make this smarter for other formats).
- '''
- #
- # do the first pass video compression
- #
- #cmd = "mencoder -quiet '%(video_source_filename)s' -ss 65 -endpos 20 -aid %(audio_id)s -o '%(video_final_filename)s' -ffourcc %(video_fourcc_override)s -ovc lavc -oac lavc %(lavcopts)s %(video_filter)s %(audio_filter)s" % locals()
-
- cmd = build_compression_command (video_source_filename, video_final_filename, video_target_size, audio_id, video_bitrate, video_codec, audio_codec, video_fourcc_override, video_gray_flag, video_crop_area, video_aspect_ratio, video_scale, video_encode_passes, video_deinterlace_flag, audio_volume_boost, audio_sample_rate, audio_bitrate, seek_skip, seek_length, video_chapter)
- if verbose_flag: print(cmd)
- if not dry_run_flag:
- run(cmd)
- print()
-
- # If not doing two passes then return early.
- if video_encode_passes!='2':
- return
-
- if verbose_flag:
- video_actual_size = get_filesize (video_final_filename)
- if video_actual_size > video_target_size:
- print("=======================================================")
- print("WARNING!")
- print("First pass compression resulted in")
- print("actual file size greater than target size.")
- print("Second pass will be too big.")
- print("=======================================================")
-
- #
- # do the second pass video compression
- #
- cmd = cmd.replace ('vpass=1', 'vpass=2')
- if verbose_flag: print(cmd)
- if not dry_run_flag:
- run(cmd)
- print()
- return
-
-def compress_audio (audio_raw_filename, audio_compressed_filename, audio_lowpass_filter=None, audio_sample_rate=None, audio_bitrate=None, verbose_flag=0, dry_run_flag=0):
- '''This is depricated.
- This compresses the raw audio file to the compressed audio filename.
- '''
- cmd = 'lame -h --athaa-sensitivity 1' # --cwlimit 11"
- if audio_lowpass_filter:
- cmd = cmd + ' --lowpass ' + audio_lowpass_filter
- if audio_bitrate:
- #cmd = cmd + ' --abr ' + audio_bitrate
- cmd = cmd + ' --cbr -b ' + audio_bitrate
- if audio_sample_rate:
- cmd = cmd + ' --resample ' + audio_sample_rate
- cmd = cmd + ' ' + audio_raw_filename + ' ' + audio_compressed_filename
- if verbose_flag: print(cmd)
- if not dry_run_flag:
- (command_output, exitstatus) = run(cmd)
- print()
- if exitstatus != 0:
- raise Exception('ERROR: lame failed to compress raw audio file.')
-
-def mux (video_final_filename, video_transcoded_filename, audio_compressed_filename, video_container_format, verbose_flag=0, dry_run_flag=0):
- '''This is depricated. I used to use a three-pass encoding where I would mix the audio track separately, but
- this never worked very well (loss of audio sync).'''
- if video_container_format.lower() == 'mkv': # Matroska
- mux_mkv (video_final_filename, video_transcoded_filename, audio_compressed_filename, verbose_flag, dry_run_flag)
- if video_container_format.lower() == 'avi':
- mux_avi (video_final_filename, video_transcoded_filename, audio_compressed_filename, verbose_flag, dry_run_flag)
-
-def mux_mkv (video_final_filename, video_transcoded_filename, audio_compressed_filename, verbose_flag=0, dry_run_flag=0):
- '''This is depricated.'''
- cmd = 'mkvmerge -o %s --noaudio %s %s' % (video_final_filename, video_transcoded_filename, audio_compressed_filename)
- if verbose_flag: print(cmd)
- if not dry_run_flag:
- run(cmd)
- print()
-
-def mux_avi (video_final_filename, video_transcoded_filename, audio_compressed_filename, verbose_flag=0, dry_run_flag=0):
- '''This is depricated.'''
- pass
-# cmd = "mencoder -quiet -oac copy -ovc copy -o '%s' -audiofile %s '%s'" % (video_final_filename, audio_compressed_filename, video_transcoded_filename)
-# if verbose_flag: print cmd
-# if not dry_run_flag:
-# run(cmd)
-# print
-
-def delete_tmp_files (audio_raw_filename, verbose_flag=0, dry_run_flag=0):
- global GLOBAL_LOGFILE_NAME
- file_list = ' '.join([GLOBAL_LOGFILE_NAME, 'divx2pass.log', audio_raw_filename ])
- cmd = 'rm -f ' + file_list
- if verbose_flag: print(cmd)
- if not dry_run_flag:
- run(cmd)
- print()
-
-##############################################################################
-# This is the interactive Q&A that is used if a conf file was not given.
-##############################################################################
-def interactive_convert ():
-
- global prompts, prompts_key_order
-
- print(globals()['__doc__'])
- print()
- print("==============================================")
- print(" Enter '?' at any question to get extra help.")
- print("==============================================")
- print()
-
- # Ask for the level of options the user wants.
- # A lot of code just to print a string!
- level_sort = {0:'', 1:'', 2:''}
- for k in prompts:
- level = prompts[k][3]
- if level < 0 or level > 2:
- continue
- level_sort[level] += " " + prompts[k][1] + "\n"
- level_sort_string = "This sets the level for advanced options prompts. Set 0 for simple, 1 for advanced, or 2 for expert.\n"
- level_sort_string += "[0] Basic options:\n" + str(level_sort[0]) + "\n"
- level_sort_string += "[1] Advanced options:\n" + str(level_sort[1]) + "\n"
- level_sort_string += "[2] Expert options:\n" + str(level_sort[2])
- c = input_option("Prompt level (0, 1, or 2)?", "1", level_sort_string)
- max_prompt_level = int(c)
-
- options = {}
- for k in prompts_key_order:
- if k == 'video_aspect_ratio':
- guess_aspect = get_aspect_ratio(options['video_source_filename'])
- options[k] = input_option (prompts[k][1], guess_aspect, prompts[k][2], prompts[k][3], max_prompt_level)
- elif k == 'audio_id':
- aid_list = get_aid_list (options['video_source_filename'])
- default_id = '128'
- if max_prompt_level>=prompts[k][3]:
- if len(aid_list) > 1:
- print("This video has more than one audio stream. The following stream audio IDs were found:")
- for aid in aid_list:
- print(" " + aid)
- default_id = aid_list[0]
- else:
- print("WARNING!")
- print("Rippy was unable to get the list of audio streams from this video.")
- print("If reading directly from a DVD then the DVD device might be busy.")
- print("Using a default setting of stream id 128 (main audio on most DVDs).")
- default_id = '128'
- options[k] = input_option (prompts[k][1], default_id, prompts[k][2], prompts[k][3], max_prompt_level)
- elif k == 'subtitle_id':
- sid_list = get_sid_list (options['video_source_filename'])
- default_id = 'None'
- if max_prompt_level>=prompts[k][3]:
- if len(sid_list) > 0:
- print("This video has one or more subtitle streams. The following stream subtitle IDs were found:")
- for sid in sid_list:
- print(" " + sid)
- #default_id = sid_list[0]
- default_id = prompts[k][0]
- else:
- print("WARNING!")
- print("Unable to get the list of subtitle streams from this video. It may have none.")
- print("Setting default to None.")
- default_id = 'None'
- options[k] = input_option (prompts[k][1], default_id, prompts[k][2], prompts[k][3], max_prompt_level)
- elif k == 'audio_lowpass_filter':
- lowpass_default = "%.1f" % (math.floor(float(options['audio_sample_rate']) / 2.0))
- options[k] = input_option (prompts[k][1], lowpass_default, prompts[k][2], prompts[k][3], max_prompt_level)
- elif k == 'video_bitrate':
- if options['video_length'].lower() == 'none':
- options[k] = input_option (prompts[k][1], '1000', prompts[k][2], prompts[k][3], max_prompt_level)
- else:
- options[k] = input_option (prompts[k][1], prompts[k][0], prompts[k][2], prompts[k][3], max_prompt_level)
- else:
- # don't bother asking for video_target_size or video_bitrate_overhead if video_bitrate was set
- if (k=='video_target_size' or k=='video_bitrate_overhead') and options['video_bitrate']!='calc':
- continue
- # don't bother with crop area if video length is none
- if k == 'video_crop_area' and options['video_length'].lower() == 'none':
- options['video_crop_area'] = 'none'
- continue
- options[k] = input_option (prompts[k][1], prompts[k][0], prompts[k][2], prompts[k][3], max_prompt_level)
-
- #options['video_final_filename'] = options['video_final_filename'] + "." + options['video_container_format']
-
- print("==========================================================================")
- print("Ready to Rippy!")
- print()
- print("The following options will be used:")
- for k,v in options.items():
- print("%27s : %s" % (k, v))
-
- print()
- c = input_option("Continue?", "Y")
- c = c.strip().lower()
- if c[0] != 'y':
- print("Exiting...")
- os._exit(1)
- return options
-
-def clean_options (d):
- '''This validates and cleans up the options dictionary.
- After reading options interactively or from a conf file
- we need to make sure that the values make sense and are
- converted to the correct type.
- 1. Any key with "_flag" in it becomes a boolean True or False.
- 2. Values are normalized ("No", "None", "none" all become "none";
- "Calcluate", "c", "CALC" all become "calc").
- 3. Certain values are converted from string to int.
- 4. Certain combinations of options are invalid or override each other.
- This is a rather annoying function, but then so it most cleanup work.
- '''
- for k in d:
- d[k] = d[k].strip()
- # convert all flag options to 0 or 1
- if '_flag' in k:
- if type(d[k]) is types.StringType:
- if d[k].strip().lower()[0] in 'yt1': #Yes, True, 1
- d[k] = 1
- else:
- d[k] = 0
- d['video_bitrate'] = d['video_bitrate'].lower()
- if d['video_bitrate'][0]=='c':
- d['video_bitrate']='calc'
- else:
- d['video_bitrate'] = int(float(d['video_bitrate']))
- try:
- d['video_target_size'] = int(d['video_target_size'])
- # shorthand magic numbers get automatically expanded
- if d['video_target_size'] == 180:
- d['video_target_size'] = 193536000
- elif d['video_target_size'] == 550:
- d['video_target_size'] = 580608000
- elif d['video_target_size'] == 650:
- d['video_target_size'] = 681984000
- elif d['video_target_size'] == 700:
- d['video_target_size'] = 737280000
- except:
- d['video_target_size'] = 'none'
-
- try:
- d['video_chapter'] = int(d['video_chapter'])
- except:
- d['video_chapter'] = None
-
- try:
- d['subtitle_id'] = int(d['subtitle_id'])
- except:
- d['subtitle_id'] = None
-
- try:
- d['video_bitrate_overhead'] = float(d['video_bitrate_overhead'])
- except:
- d['video_bitrate_overhead'] = -1.0
-
- d['audio_bitrate'] = int(d['audio_bitrate'])
- d['audio_sample_rate'] = int(d['audio_sample_rate'])
- d['audio_volume_boost'] = d['audio_volume_boost'].lower()
- if d['audio_volume_boost'][0]=='n':
- d['audio_volume_boost'] = None
- else:
- d['audio_volume_boost'] = d['audio_volume_boost'].replace('db','')
- d['audio_volume_boost'] = float(d['audio_volume_boost'])
-
-# assert (d['video_bitrate']=='calc' and d['video_target_size']!='none')
-# or (d['video_bitrate']!='calc' and d['video_target_size']=='none')
-
- d['video_scale'] = d['video_scale'].lower()
- if d['video_scale'][0]=='n':
- d['video_scale']='none'
- else:
- al = re.findall("([0-9]+).*?([0-9]+)", d['video_scale'])
- d['video_scale']=al[0][0]+':'+al[0][1]
- d['video_crop_area'] = d['video_crop_area'].lower()
- if d['video_crop_area'][0]=='n':
- d['video_crop_area']='none'
- d['video_length'] = d['video_length'].lower()
- if d['video_length'][0]=='c':
- d['video_length']='calc'
- elif d['video_length'][0]=='n':
- d['video_length']='none'
- else:
- d['video_length'] = int(float(d['video_length']))
- if d['video_length']==0:
- d['video_length'] = 'none'
- assert (not (d['video_length']=='none' and d['video_bitrate']=='calc'))
- return d
-
-def main ():
- try:
- optlist, args = getopt.getopt(sys.argv[1:], 'h?', ['help','h','?'])
- except Exception as e:
- print(str(e))
- exit_with_usage()
- command_line_options = dict(optlist)
- # There are a million ways to cry for help. These are but a few of them.
- if [elem for elem in command_line_options if elem in ['-h','--h','-?','--?','--help']]:
- exit_with_usage(0)
-
- missing = check_missing_requirements()
- if missing is not None:
- print()
- print("==========================================================================")
- print("ERROR!")
- print("Some required external commands are missing.")
- print("please install the following packages:")
- print(str(missing))
- print("==========================================================================")
- print()
- c = input_option("Continue?", "Y")
- c = c.strip().lower()
- if c[0] != 'y':
- print("Exiting...")
- os._exit(1)
-
- if len(args) > 0:
- # cute one-line string-to-dictionary parser (two-lines if you count this comment):
- options = dict(re.findall('([^: \t\n]*)\s*:\s*(".*"|[^ \t\n]*)', file(args[0]).read()))
- options = clean_options(options)
- convert (options)
- else:
- options = interactive_convert ()
- options = clean_options(options)
- convert (options)
- print("# Done!")
-
-if __name__ == "__main__":
- try:
- start_time = time.time()
- print(time.asctime())
- main()
- print(time.asctime())
- print("TOTAL TIME IN MINUTES:", end=' ')
- print((time.time() - start_time) / 60.0)
- except Exception as e:
- tb_dump = traceback.format_exc()
- print("==========================================================================")
- print("ERROR -- Unexpected exception in script.")
- print(str(e))
- print(str(tb_dump))
- print("==========================================================================")
- print("==========================================================================", file=GLOBAL_LOGFILE)
- print("ERROR -- Unexpected exception in script.", file=GLOBAL_LOGFILE)
- print(str(e), file=GLOBAL_LOGFILE)
- print(str(tb_dump), file=GLOBAL_LOGFILE)
- print("==========================================================================", file=GLOBAL_LOGFILE)
- exit_with_usage(3)
-
diff --git a/examples/ssh_session.py b/examples/ssh_session.py
deleted file mode 100755
index f040c5c..0000000
--- a/examples/ssh_session.py
+++ /dev/null
@@ -1,120 +0,0 @@
-#!/usr/bin/env python
-
-'''
- Eric S. Raymond
-
- Greatly modified by Nigel W. Moriarty
- April 2003
-
-PEXPECT LICENSE
-
- This license is approved by the OSI and FSF as GPL-compatible.
- http://opensource.org/licenses/isc-license.txt
-
- Copyright (c) 2012, Noah Spurrier <noah@noah.org>
- PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
- PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
- COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-'''
-
-from __future__ import absolute_import
-
-from pexpect import *
-import os, sys
-import getpass
-import time
-
-
-class ssh_session:
-
- '''Session with extra state including the password to be used.'''
-
- def __init__(self, user, host, password=None, verbose=0):
-
- self.user = user
- self.host = host
- self.verbose = verbose
- self.password = password
- self.keys = [
- 'authenticity',
- 'assword:',
- '@@@@@@@@@@@@',
- 'Command not found.',
- EOF,
- ]
-
- self.f = open('ssh.out','w')
-
- def __repr__(self):
-
- outl = 'class :'+self.__class__.__name__
- for attr in self.__dict__:
- if attr == 'password':
- outl += '\n\t'+attr+' : '+'*'*len(self.password)
- else:
- outl += '\n\t'+attr+' : '+str(getattr(self, attr))
- return outl
-
- def __exec(self, command):
-
- '''Execute a command on the remote host. Return the output.'''
-
- child = spawn(command,
- #timeout=10,
- )
- if self.verbose:
- sys.stderr.write("-> " + command + "\n")
- seen = child.expect(self.keys)
- self.f.write(str(child.before) + str(child.after)+'\n')
- if seen == 0:
- child.sendline('yes')
- seen = child.expect(self.keys)
- if seen == 1:
- if not self.password:
- self.password = getpass.getpass('Remote password: ')
- child.sendline(self.password)
- child.readline()
- time.sleep(5)
- # Added to allow the background running of remote process
- if not child.isalive():
- seen = child.expect(self.keys)
- if seen == 2:
- lines = child.readlines()
- self.f.write(lines)
- if self.verbose:
- sys.stderr.write("<- " + child.before + "|\n")
- try:
- self.f.write(str(child.before) + str(child.after)+'\n')
- except:
- pass
- self.f.close()
- return child.before
-
- def ssh(self, command):
-
- return self.__exec("ssh -l %s %s \"%s\"" \
- % (self.user,self.host,command))
-
- def scp(self, src, dst):
-
- return self.__exec("scp %s %s@%s:%s" \
- % (src, session.user, session.host, dst))
-
- def exists(self, file):
-
- '''Retrieve file permissions of specified remote file.'''
-
- seen = self.ssh("/bin/ls -ld %s" % file)
- if string.find(seen, "No such file") > -1:
- return None # File doesn't exist
- else:
- return seen.split()[0] # Return permission field of listing.
-
diff --git a/examples/sshls.py b/examples/sshls.py
deleted file mode 100755
index 9f751f3..0000000
--- a/examples/sshls.py
+++ /dev/null
@@ -1,84 +0,0 @@
-#!/usr/bin/env python
-
-'''This runs 'ls -l' on a remote host using SSH.
-At the prompts enter hostname, username, and password.
-
-PEXPECT LICENSE
-
- This license is approved by the OSI and FSF as GPL-compatible.
- http://opensource.org/licenses/isc-license.txt
-
- Copyright (c) 2012, Noah Spurrier <noah@noah.org>
- PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
- PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
- COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-'''
-
-from __future__ import print_function
-
-from __future__ import absolute_import
-
-import pexpect
-import getpass, os
-
-
-try:
- raw_input
-except NameError:
- raw_input = input
-
-
-def ssh_command (user, host, password, command):
-
- '''This runs a command on the remote host. This could also be done with the
- pxssh class, but this demonstrates what that class does at a simpler level.
- This returns a pexpect.spawn object. This handles the case when you try to
- connect to a new host and ssh asks you if you want to accept the public key
- fingerprint and continue connecting. '''
-
- ssh_newkey = 'Are you sure you want to continue connecting'
- child = pexpect.spawn('ssh -l %s %s %s'%(user, host, command))
- i = child.expect([pexpect.TIMEOUT, ssh_newkey, 'password: '])
- if i == 0: # Timeout
- print('ERROR!')
- print('SSH could not login. Here is what SSH said:')
- print(child.before, child.after)
- return None
- if i == 1: # SSH does not have the public key. Just accept it.
- child.sendline ('yes')
- child.expect ('password: ')
- i = child.expect([pexpect.TIMEOUT, 'password: '])
- if i == 0: # Timeout
- print('ERROR!')
- print('SSH could not login. Here is what SSH said:')
- print(child.before, child.after)
- return None
- child.sendline(password)
- return child
-
-def main ():
-
- host = raw_input('Hostname: ')
- user = raw_input('User: ')
- password = getpass.getpass('Password: ')
- child = ssh_command (user, host, password, '/bin/ls -l')
- child.expect(pexpect.EOF)
- print(child.before)
-
-if __name__ == '__main__':
-
- try:
- main()
- except Exception as e:
- print(str(e))
- traceback.print_exc()
- os._exit(1)
-