# cmdserver.py

# Demo code that is not Pythonwin related, but too good to throw away...

import win32api
import sys
from pywin.framework import winout

import thread, sys

import traceback

class ThreadWriter:
	"Assign an instance to sys.stdout for per-thread printing objects - Courtesy Guido!"
	def __init__(self):
		"Constructor -- initialize the table of writers"
		self.writers = {}
		self.origStdOut = None
	def register(self, writer):
		"Register the writer for the current thread"
		self.writers[thread.get_ident()] = writer
		if self.origStdOut is None:
			self.origStdOut = sys.stdout
			sys.stdout = self		

	def unregister(self):
		"Remove the writer for the current thread, if any"
		try:
			del self.writers[thread.get_ident()]
		except KeyError:
			pass
		if len(self.writers)==0:
			sys.stdout = self.origStdOut
			self.origStdOut = None

	def getwriter(self):
		"Return the current thread's writer, default sys.stdout"
		try:
			return self.writers[thread.get_ident()]
		except KeyError:
			return self.origStdOut

	def write(self, str):
		"Write to the current thread's writer, default sys.stdout"
		self.getwriter().write(str)

def Test():
	num=1
	while num<1000:
		print 'Hello there no ' + str(num)
		win32api.Sleep(50)
		num = num + 1

class flags:
	SERVER_BEST = 0
	SERVER_IMMEDIATE = 1
	SERVER_THREAD = 2
	SERVER_PROCESS = 3
	
def StartServer( cmd, title=None, bCloseOnEnd=0, serverFlags = flags.SERVER_BEST ):
	out = winout.WindowOutput( title, None, winout.flags.WQ_IDLE )
	if not title:
		title=cmd
	out.Create(title)
#	ServerThread((out, cmd, title, bCloseOnEnd))
#	out = sys.stdout
	thread.start_new_thread( ServerThread, (out, cmd, title, bCloseOnEnd) )

def ServerThread(myout, cmd, title, bCloseOnEnd):
	try:
		writer.register(myout)
		print 'Executing "%s"\n' % cmd
		bOK = 1
		try:
			import __main__
			exec (cmd+'\n', __main__.__dict__)
		except:
			bOK = 0
		if bOK:
			print "Command terminated without errors."
		else:
			t, v, tb = sys.exc_info()
			print t, ': ', v
			traceback.print_tb(tb)
			tb = None # prevent a cycle
			print "Command terminated with an unhandled exception"
		writer.unregister()
		if bOK and bCloseOnEnd:
			myout.frame.DestroyWindow()

	# Unhandled exception of any kind in a thread kills the gui!
	except:
		t, v, tb = sys.exc_info()
		print t, ': ', v
		traceback.print_tb(tb)
		tb = None
		print "Thread failed"

# assist for reloading (when debugging) - use only 1 tracer object,
# else a large chain of tracer objects will exist.
#try:
#	writer
#except NameError:
#	writer=ThreadWriter()
if __name__=='__main__':
	import demoutils
	demoutils.NotAScript()
	
