#! /usr/bin/python import socket import subprocess import errno import sys import os import os.path import json import traceback import shlex import struct import threading import Queue import * from ArgParser def usage(): print "usage 1: ./exporter.py [--port/-p wrapper_communication_port] [--type/-t (1,3)] [--scale/-s skeletal_scale] [--base/-b base_dir] input_files..." print " Exports the given file(s) with the given settings" print print "usage 2: ./exporter.py [--port/-p wrapper_communication_port] [--base/-b base_dir] -" print " Reads commands (everything after --port in usage 1) as lines from stdin" print print "usage 3: ./export.py --help|-h" print " Shows this help message" if "-h" in sys.argv or "--help" in sys.argv: usage() sys.exit(0) (err, args) = ArgParser().parse_args(sys.argv[1:]) if err is not None: print err usage() sys.exit(2) from_stdin = False if "-" in args["input"]: from_stdin = True if len(args["input"]) > 1 or "type" in args or "scale" in args: print "If reading from stdin ('-') is specified, no other input may be given" usage() sys.exit(2) if not len(args["input"]): usage() sys.exit(0) port = args["port"] if "port" in args else 7890 def make_base_job_args(args): return {"type": args["type"] if "type" in args else 1, \ "scale": args["scale"] if "scale" in args else 1} class Job: next_id = 0 def __init__(self, input, type = 1, scale = 1, base = None): if not os.path.isfile(input): raise Exception("Failed: couldn't open " + input) self.id = next_id next_id += 1 self.input = abspath(input) self.base = base if base is not None else os.path.split(input)[0] if not file_in_path(self.input, self.base): raise Exception("Failed: " + input + " is not in base dir " + self.base) self.type = type self.scale = scale self.done = False def send_msg(conn, msg): data = json.dumps(msg) datalen = struct.pack(">H", len(data)) conn.send(datalen) conn.send(data) conn = None while conn is None and g.returncode is None: try: (conn, _) = s.accept() except socket.timeout, e: pass except e: print e s.close() g.wait() sys.exit(1) g.poll() jobs = {} if conn: conn.setblocking(False) if from_stdin: pass else: base_args = make_base_job_args(args) for i in args["input"]: try: job = Job(base_args, input = i) jobs[job.id] = job except Exception, e: print e def handle_command(msg_str): global quit msg = json.loads(msg_str) if "command" in msg: cmd = msg["command"] if cmd == "exit": quit = True if cmd == "print" and "string" in msg: sys.stdout.write(msg["string"]) sys.stdout.flush() if cmd == "done" and "job_num" in msg: job_num = int(cmd["job_num"]) if job_num == num_jobs_sent: quit = True buf = "" quit = False while g.returncode is None: try: d = conn.recv(4096) if len(d): buf += d if len(buf) >= 2: buf_len = struct.unpack_from(">H", buf, 0)[0] if len(buf) >= 2 + buf_len: msg = buf[2:2+buf_len] buf = buf[2+buf_len:] handle_command(msg) except socket.error, e: if e.args[0] == errno.EWOULDBLOCK or e.args[0] == errno.EAGAIN: pass else: print e quit = True if not quit and from_stdin and stdin_q.qsize(): line = stdin_q.get() if line == "": quit = True else: parts = shlex.split(line) (err, line_args) = ArgParser.parse_args(parts) if err is not None: print err else: base_args= make_base_job_args(line_args) for i in line_args["input"]: send_job(conn, base_cmd, i) if quit: send_msg(conn, {"command":"quit"}) conn.close() s.close() g.kill() sys.exit(1) g.poll() if (conn): conn.close() s.close()