Created
June 9, 2014 19:22
-
-
Save harlowja/b0b6e2590bf140c6f792 to your computer and use it in GitHub Desktop.
Remote tox tester
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import argparse | |
import getpass | |
import os | |
import select | |
import socket | |
import sys | |
import tarfile | |
import tempfile | |
import threading | |
import time | |
import fcntl | |
from fcntl import F_GETFL, F_SETFL | |
from os import O_NONBLOCK | |
import six | |
import plumbum | |
from plumbum import local | |
from plumbum.path import utils | |
DEF_VENV = 'py27' | |
def read_write(read_from, write_where, chunk_size=128): | |
while True: | |
try: | |
data = os.read(read_from.fileno(), chunk_size) | |
if len(data): | |
write_where.write(data) | |
write_where.flush() | |
else: | |
break | |
except OSError: | |
break | |
def spinning_cursor(): | |
while True: | |
for ch in '|/-\\': | |
yield ch | |
def runner(cmd, args): | |
p = cmd.popen(args=tuple(args)) | |
flags = fcntl.fcntl(p.stdout, F_GETFL) | |
fcntl.fcntl(p.stdout, F_SETFL, flags | O_NONBLOCK) | |
flags = fcntl.fcntl(p.stderr, F_GETFL) | |
fcntl.fcntl(p.stderr, F_SETFL, flags | O_NONBLOCK) | |
inputs = [p.stdout, p.stderr] | |
inputs_outputs = { | |
p.stdout: sys.stdout, | |
p.stderr: sys.stderr, | |
} | |
spinner = spinning_cursor() | |
while p.poll() == None: | |
i_ready, o_ready, e_ready = select.select(inputs, [], [], 0.05) | |
for s in i_ready: | |
read_write(s, inputs_outputs[s]) | |
sys.stdout.write(spinner.next()) | |
sys.stdout.flush() | |
time.sleep(0.1) | |
sys.stdout.write('\b') | |
# Ensure everything is read (just incase). | |
for (innie, outtie) in six.iteritems(inputs_outputs): | |
read_write(innie, outtie) | |
return p.returncode | |
def main(): | |
parser = argparse.ArgumentParser() | |
parser.add_argument("-v", "--verbose", | |
help="increase output verbosity", | |
action="store_true", default=False) | |
default_source_dir = os.getcwd() | |
parser.add_argument("-d", "--directory", | |
help="test directory" | |
" (default: %s)" % default_source_dir, | |
action="store", default=default_source_dir, | |
metavar="DIR") | |
default_hostname = socket.gethostname() | |
parser.add_argument("--host", | |
help="remote test" | |
" host (default: %s)" % default_hostname, | |
action="store", metavar="HOST", | |
default=default_hostname) | |
default_user = getpass.getuser() | |
parser.add_argument("-u", "--user", | |
help="remote test" | |
" user (default: %s)" % default_user, | |
action="store", metavar="USER", default=default_user) | |
parser.add_argument("--venv", | |
help="remote test" | |
" venv (default: %s)" % DEF_VENV, | |
action="store", metavar="VENV", | |
default=DEF_VENV) | |
default_test_dir = os.path.expanduser("~/.testing") | |
parser.add_argument("--path", | |
help="remote test" | |
" path (default: %s)" % default_test_dir, | |
action="store", metavar="DIR", | |
default=default_test_dir) | |
args = parser.parse_args() | |
src_path = args.directory | |
src = local.path(src_path) | |
user = args.user | |
host = args.host | |
path = args.path | |
if not os.path.exists(os.path.join(src_path, "tox.ini")): | |
print("No tox.ini file available. This will not end well.") | |
return 1 | |
print("-" * 70) | |
print("Connecting to %s@%s..." % (user, host)) | |
with plumbum.SshMachine(host=host, user=user) as m: | |
with tempfile.NamedTemporaryFile(suffix=".%s.tar" % src.basename) as fh: | |
tarball = tarfile.open(fileobj=fh, mode='w') | |
try: | |
print("Tarring up %s -> %s..." % (src, fh.name)) | |
for (dirpath, dirnames, filenames) in os.walk(src_path): | |
for name in filenames: | |
path = os.path.join(dirpath, name) | |
if not path.startswith(src_path): | |
print("Invalid path '%s' found" % (path)) | |
return 1 | |
arcname = path[len(src_path):] | |
if args.verbose: | |
print('Adding %s as %s' % (path, arcname)) | |
tarball.add(path, arcname=arcname) | |
finally: | |
tarball.close() | |
fh.flush() | |
mk = m['mkdir'] | |
base = m.path(args.path) | |
if not base.exists: | |
mk("-p", base) | |
target = base / src.basename | |
if target.exists: | |
print("Removing old %s..." % (target)) | |
rm = m['rm'] | |
rm("-rf", target) | |
mk("-p", target) | |
tar_target = target / os.path.split(fh.name)[1] | |
print("Copying %s to %s..." % (fh.name, tar_target)) | |
utils.copy(fh.name, tar_target) | |
with m.cwd(target): | |
print("Extracting %s..." % (tar_target)) | |
e = m['tar'] | |
e('-xf', tar_target.basename) | |
print('Running tox with venv %s...' % (args.venv)) | |
print("-" * 70) | |
with m.cwd(target): | |
tox_args = ["-e%s" % args.venv] | |
if args.verbose: | |
tox_args.append("-v") | |
rc = runner(m['tox'], tox_args) | |
return rc | |
if __name__ == '__main__': | |
sys.exit(main()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment