# 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()
	
