#! /usr/bin/env python
# encoding: utf-8

import sys
mswindows=(sys.platform=="win32")
import os
import types
import traceback
import gc
class CalledProcessError(Exception):
	def __init__(self,returncode,cmd):
		self.returncode=returncode
		self.cmd=cmd
	def __str__(self):
		return"Command '%s' returned non-zero exit status %d"%(self.cmd,self.returncode)
if mswindows:
	import threading
	import msvcrt
	if 0:
		import pywintypes
		from win32api import GetStdHandle,STD_INPUT_HANDLE,STD_OUTPUT_HANDLE,STD_ERROR_HANDLE
		from win32api import GetCurrentProcess,DuplicateHandle,GetModuleFileName,GetVersion
		from win32con import DUPLICATE_SAME_ACCESS,SW_HIDE
		from win32pipe import CreatePipe
		from win32process import CreateProcess,STARTUPINFO,GetExitCodeProcess,STARTF_USESTDHANDLES,STARTF_USESHOWWINDOW,CREATE_NEW_CONSOLE
		from win32event import WaitForSingleObject,INFINITE,WAIT_OBJECT_0
	else:
		from _subprocess import*
		class STARTUPINFO:
			dwFlags=0
			hStdInput=None
			hStdOutput=None
			hStdError=None
			wShowWindow=0
		class pywintypes:
			error=IOError
else:
	import select
	import errno
	import fcntl
	import pickle
__all__=["Popen","PIPE","STDOUT","call","check_call","CalledProcessError"]
try:
	MAXFD=os.sysconf("SC_OPEN_MAX")
except:
	MAXFD=256
try:
	False
except NameError:
	False=0
	True=1
_active=[]
def _cleanup():
	for inst in _active[:]:
		if inst.poll(_deadstate=sys.maxint)>=0:
			try:
				_active.remove(inst)
			except ValueError:
				pass
PIPE=-1
STDOUT=-2
def call(*popenargs,**kwargs):
	return Popen(*popenargs,**kwargs).wait()
def check_call(*popenargs,**kwargs):
	retcode=call(*popenargs,**kwargs)
	cmd=kwargs.get("args")
	if cmd is None:
		cmd=popenargs[0]
	if retcode:
		raise CalledProcessError(retcode,cmd)
	return retcode
def list2cmdline(seq):
	result=[]
	needquote=False
	for arg in seq:
		bs_buf=[]
		if result:
			result.append(' ')
		needquote=(" "in arg)or("\t"in arg)or arg==""
		if needquote:
			result.append('"')
		for c in arg:
			if c=='\\':
				bs_buf.append(c)
			elif c=='"':
				result.append('\\'*len(bs_buf)*2)
				bs_buf=[]
				result.append('\\"')
			else:
				if bs_buf:
					result.extend(bs_buf)
					bs_buf=[]
				result.append(c)
		if bs_buf:
			result.extend(bs_buf)
		if needquote:
			result.extend(bs_buf)
			result.append('"')
	return''.join(result)
class Popen(object):
	def __init__(self,args,bufsize=0,executable=None,stdin=None,stdout=None,stderr=None,preexec_fn=None,close_fds=False,shell=False,cwd=None,env=None,universal_newlines=False,startupinfo=None,creationflags=0):
		_cleanup()
		self._child_created=False
		if not isinstance(bufsize,(int,long)):
			raise TypeError("bufsize must be an integer")
		if mswindows:
			if preexec_fn is not None:
				raise ValueError("preexec_fn is not supported on Windows platforms")
			if close_fds:
				raise ValueError("close_fds is not supported on Windows platforms")
		else:
			if startupinfo is not None:
				raise ValueError("startupinfo is only supported on Windows platforms")
			if creationflags!=0:
				raise ValueError("creationflags is only supported on Windows platforms")
		self.stdin=None
		self.stdout=None
		self.stderr=None
		self.pid=None
		self.returncode=None
		self.universal_newlines=universal_newlines
		(p2cread,p2cwrite,c2pread,c2pwrite,errread,errwrite)=self._get_handles(stdin,stdout,stderr)
		self._execute_child(args,executable,preexec_fn,close_fds,cwd,env,universal_newlines,startupinfo,creationflags,shell,p2cread,p2cwrite,c2pread,c2pwrite,errread,errwrite)
		if mswindows:
			if stdin is None and p2cwrite is not None:
				os.close(p2cwrite)
				p2cwrite=None
			if stdout is None and c2pread is not None:
				os.close(c2pread)
				c2pread=None
			if stderr is None and errread is not None:
				os.close(errread)
				errread=None
		if p2cwrite:
			self.stdin=os.fdopen(p2cwrite,'wb',bufsize)
		if c2pread:
			if universal_newlines:
				self.stdout=os.fdopen(c2pread,'rU',bufsize)
			else:
				self.stdout=os.fdopen(c2pread,'rb',bufsize)
		if errread:
			if universal_newlines:
				self.stderr=os.fdopen(errread,'rU',bufsize)
			else:
				self.stderr=os.fdopen(errread,'rb',bufsize)
	def _translate_newlines(self,data):
		data=data.replace("\r\n","\n")
		data=data.replace("\r","\n")
		return data
	def __del__(self,sys=sys):
		if not self._child_created:
			return
		self.poll(_deadstate=sys.maxint)
		if self.returncode is None and _active is not None:
			_active.append(self)
	def communicate(self,input=None):
		if[self.stdin,self.stdout,self.stderr].count(None)>=2:
			stdout=None
			stderr=None
			if self.stdin:
				if input:
					self.stdin.write(input)
				self.stdin.close()
			elif self.stdout:
				stdout=self.stdout.read()
			elif self.stderr:
				stderr=self.stderr.read()
			self.wait()
			return(stdout,stderr)
		return self._communicate(input)
	if mswindows:
		def _get_handles(self,stdin,stdout,stderr):
			if stdin is None and stdout is None and stderr is None:
				return(None,None,None,None,None,None)
			p2cread,p2cwrite=None,None
			c2pread,c2pwrite=None,None
			errread,errwrite=None,None
			if stdin is None:
				p2cread=GetStdHandle(STD_INPUT_HANDLE)
			if p2cread is not None:
				pass
			elif stdin is None or stdin==PIPE:
				p2cread,p2cwrite=CreatePipe(None,0)
				p2cwrite=p2cwrite.Detach()
				p2cwrite=msvcrt.open_osfhandle(p2cwrite,0)
			elif isinstance(stdin,int):
				p2cread=msvcrt.get_osfhandle(stdin)
			else:
				p2cread=msvcrt.get_osfhandle(stdin.fileno())
			p2cread=self._make_inheritable(p2cread)
			if stdout is None:
				c2pwrite=GetStdHandle(STD_OUTPUT_HANDLE)
			if c2pwrite is not None:
				pass
			elif stdout is None or stdout==PIPE:
				c2pread,c2pwrite=CreatePipe(None,0)
				c2pread=c2pread.Detach()
				c2pread=msvcrt.open_osfhandle(c2pread,0)
			elif isinstance(stdout,int):
				c2pwrite=msvcrt.get_osfhandle(stdout)
			else:
				c2pwrite=msvcrt.get_osfhandle(stdout.fileno())
			c2pwrite=self._make_inheritable(c2pwrite)
			if stderr is None:
				errwrite=GetStdHandle(STD_ERROR_HANDLE)
			if errwrite is not None:
				pass
			elif stderr is None or stderr==PIPE:
				errread,errwrite=CreatePipe(None,0)
				errread=errread.Detach()
				errread=msvcrt.open_osfhandle(errread,0)
			elif stderr==STDOUT:
				errwrite=c2pwrite
			elif isinstance(stderr,int):
				errwrite=msvcrt.get_osfhandle(stderr)
			else:
				errwrite=msvcrt.get_osfhandle(stderr.fileno())
			errwrite=self._make_inheritable(errwrite)
			return(p2cread,p2cwrite,c2pread,c2pwrite,errread,errwrite)
		def _make_inheritable(self,handle):
			return DuplicateHandle(GetCurrentProcess(),handle,GetCurrentProcess(),0,1,DUPLICATE_SAME_ACCESS)
		def _find_w9xpopen(self):
			w9xpopen=os.path.join(os.path.dirname(GetModuleFileName(0)),"w9xpopen.exe")
			if not os.path.exists(w9xpopen):
				w9xpopen=os.path.join(os.path.dirname(sys.exec_prefix),"w9xpopen.exe")
				if not os.path.exists(w9xpopen):
					raise RuntimeError("Cannot locate w9xpopen.exe, which is needed for Popen to work with your shell or platform.")
			return w9xpopen
		def _execute_child(self,args,executable,preexec_fn,close_fds,cwd,env,universal_newlines,startupinfo,creationflags,shell,p2cread,p2cwrite,c2pread,c2pwrite,errread,errwrite):
			if not isinstance(args,types.StringTypes):
				args=list2cmdline(args)
			if startupinfo is None:
				startupinfo=STARTUPINFO()
			if None not in(p2cread,c2pwrite,errwrite):
				startupinfo.dwFlags|=STARTF_USESTDHANDLES
				startupinfo.hStdInput=p2cread
				startupinfo.hStdOutput=c2pwrite
				startupinfo.hStdError=errwrite
			if shell:
				startupinfo.dwFlags|=STARTF_USESHOWWINDOW
				startupinfo.wShowWindow=SW_HIDE
				comspec=os.environ.get("COMSPEC","cmd.exe")
				args=comspec+" /c "+args
				if(GetVersion()>=0x80000000L or os.path.basename(comspec).lower()=="command.com"):
					w9xpopen=self._find_w9xpopen()
					args='"%s" %s'%(w9xpopen,args)
					creationflags|=CREATE_NEW_CONSOLE
			try:
				hp,ht,pid,tid=CreateProcess(executable,args,None,None,1,creationflags,env,cwd,startupinfo)
			except pywintypes.error,e:
				raise WindowsError(*e.args)
			self._child_created=True
			self._handle=hp
			self.pid=pid
			ht.Close()
			if p2cread is not None:
				p2cread.Close()
			if c2pwrite is not None:
				c2pwrite.Close()
			if errwrite is not None:
				errwrite.Close()
		def poll(self,_deadstate=None):
			if self.returncode is None:
				if WaitForSingleObject(self._handle,0)==WAIT_OBJECT_0:
					self.returncode=GetExitCodeProcess(self._handle)
			return self.returncode
		def wait(self):
			if self.returncode is None:
				obj=WaitForSingleObject(self._handle,INFINITE)
				self.returncode=GetExitCodeProcess(self._handle)
			return self.returncode
		def _readerthread(self,fh,buffer):
			buffer.append(fh.read())
		def _communicate(self,input):
			stdout=None
			stderr=None
			if self.stdout:
				stdout=[]
				stdout_thread=threading.Thread(target=self._readerthread,args=(self.stdout,stdout))
				stdout_thread.setDaemon(True)
				stdout_thread.start()
			if self.stderr:
				stderr=[]
				stderr_thread=threading.Thread(target=self._readerthread,args=(self.stderr,stderr))
				stderr_thread.setDaemon(True)
				stderr_thread.start()
			if self.stdin:
				if input is not None:
					self.stdin.write(input)
				self.stdin.close()
			if self.stdout:
				stdout_thread.join()
			if self.stderr:
				stderr_thread.join()
			if stdout is not None:
				stdout=stdout[0]
			if stderr is not None:
				stderr=stderr[0]
			if self.universal_newlines and hasattr(file,'newlines'):
				if stdout:
					stdout=self._translate_newlines(stdout)
				if stderr:
					stderr=self._translate_newlines(stderr)
			self.wait()
			return(stdout,stderr)
	else:
		def _get_handles(self,stdin,stdout,stderr):
			p2cread,p2cwrite=None,None
			c2pread,c2pwrite=None,None
			errread,errwrite=None,None
			if stdin is None:
				pass
			elif stdin==PIPE:
				p2cread,p2cwrite=os.pipe()
			elif isinstance(stdin,int):
				p2cread=stdin
			else:
				p2cread=stdin.fileno()
			if stdout is None:
				pass
			elif stdout==PIPE:
				c2pread,c2pwrite=os.pipe()
			elif isinstance(stdout,int):
				c2pwrite=stdout
			else:
				c2pwrite=stdout.fileno()
			if stderr is None:
				pass
			elif stderr==PIPE:
				errread,errwrite=os.pipe()
			elif stderr==STDOUT:
				errwrite=c2pwrite
			elif isinstance(stderr,int):
				errwrite=stderr
			else:
				errwrite=stderr.fileno()
			return(p2cread,p2cwrite,c2pread,c2pwrite,errread,errwrite)
		def _set_cloexec_flag(self,fd):
			try:
				cloexec_flag=fcntl.FD_CLOEXEC
			except AttributeError:
				cloexec_flag=1
			old=fcntl.fcntl(fd,fcntl.F_GETFD)
			fcntl.fcntl(fd,fcntl.F_SETFD,old|cloexec_flag)
		def _close_fds(self,but):
			for i in xrange(3,MAXFD):
				if i==but:
					continue
				try:
					os.close(i)
				except:
					pass
		def _execute_child(self,args,executable,preexec_fn,close_fds,cwd,env,universal_newlines,startupinfo,creationflags,shell,p2cread,p2cwrite,c2pread,c2pwrite,errread,errwrite):
			if isinstance(args,types.StringTypes):
				args=[args]
			else:
				args=list(args)
			if shell:
				args=["/bin/sh","-c"]+args
			if executable is None:
				executable=args[0]
			errpipe_read,errpipe_write=os.pipe()
			self._set_cloexec_flag(errpipe_write)
			gc_was_enabled=gc.isenabled()
			gc.disable()
			try:
				self.pid=os.fork()
			except:
				if gc_was_enabled:
					gc.enable()
				raise
			self._child_created=True
			if self.pid==0:
				try:
					if p2cwrite:
						os.close(p2cwrite)
					if c2pread:
						os.close(c2pread)
					if errread:
						os.close(errread)
					os.close(errpipe_read)
					if p2cread:
						os.dup2(p2cread,0)
					if c2pwrite:
						os.dup2(c2pwrite,1)
					if errwrite:
						os.dup2(errwrite,2)
					if p2cread and p2cread not in(0,):
						os.close(p2cread)
					if c2pwrite and c2pwrite not in(p2cread,1):
						os.close(c2pwrite)
					if errwrite and errwrite not in(p2cread,c2pwrite,2):
						os.close(errwrite)
					if close_fds:
						self._close_fds(but=errpipe_write)
					if cwd is not None:
						os.chdir(cwd)
					if preexec_fn:
						apply(preexec_fn)
					if env is None:
						os.execvp(executable,args)
					else:
						os.execvpe(executable,args,env)
				except:
					exc_type,exc_value,tb=sys.exc_info()
					exc_lines=traceback.format_exception(exc_type,exc_value,tb)
					exc_value.child_traceback=''.join(exc_lines)
					os.write(errpipe_write,pickle.dumps(exc_value))
				os._exit(255)
			if gc_was_enabled:
				gc.enable()
			os.close(errpipe_write)
			if p2cread and p2cwrite:
				os.close(p2cread)
			if c2pwrite and c2pread:
				os.close(c2pwrite)
			if errwrite and errread:
				os.close(errwrite)
			data=os.read(errpipe_read,1048576)
			os.close(errpipe_read)
			if data!="":
				os.waitpid(self.pid,0)
				child_exception=pickle.loads(data)
				raise child_exception
		def _handle_exitstatus(self,sts):
			if os.WIFSIGNALED(sts):
				self.returncode=-os.WTERMSIG(sts)
			elif os.WIFEXITED(sts):
				self.returncode=os.WEXITSTATUS(sts)
			else:
				raise RuntimeError("Unknown child exit status!")
		def poll(self,_deadstate=None):
			if self.returncode is None:
				try:
					pid,sts=os.waitpid(self.pid,os.WNOHANG)
					if pid==self.pid:
						self._handle_exitstatus(sts)
				except os.error:
					if _deadstate is not None:
						self.returncode=_deadstate
			return self.returncode
		def wait(self):
			if self.returncode is None:
				pid,sts=os.waitpid(self.pid,0)
				self._handle_exitstatus(sts)
			return self.returncode
		def _communicate(self,input):
			read_set=[]
			write_set=[]
			stdout=None
			stderr=None
			if self.stdin:
				self.stdin.flush()
				if input:
					write_set.append(self.stdin)
				else:
					self.stdin.close()
			if self.stdout:
				read_set.append(self.stdout)
				stdout=[]
			if self.stderr:
				read_set.append(self.stderr)
				stderr=[]
			input_offset=0
			while read_set or write_set:
				rlist,wlist,xlist=select.select(read_set,write_set,[])
				if self.stdin in wlist:
					bytes_written=os.write(self.stdin.fileno(),buffer(input,input_offset,512))
					input_offset+=bytes_written
					if input_offset>=len(input):
						self.stdin.close()
						write_set.remove(self.stdin)
				if self.stdout in rlist:
					data=os.read(self.stdout.fileno(),1024)
					if data=="":
						self.stdout.close()
						read_set.remove(self.stdout)
					stdout.append(data)
				if self.stderr in rlist:
					data=os.read(self.stderr.fileno(),1024)
					if data=="":
						self.stderr.close()
						read_set.remove(self.stderr)
					stderr.append(data)
			if stdout is not None:
				stdout=''.join(stdout)
			if stderr is not None:
				stderr=''.join(stderr)
			if self.universal_newlines and hasattr(file,'newlines'):
				if stdout:
					stdout=self._translate_newlines(stdout)
				if stderr:
					stderr=self._translate_newlines(stderr)
			self.wait()
			return(stdout,stderr)

