Description: Port to Python 3 and wxPython 4
Author: Scott Talbert <swt@techie.net>

--- a/AboutWindow.py
+++ b/AboutWindow.py
@@ -1,5 +1,5 @@
-import wx
-import os, os.path, sys, cStringIO
+import wx, wx.adv
+import os, os.path, sys, io
 
 
 """
@@ -106,20 +106,20 @@
 		font3 = wx.Font(12, wx.NORMAL, wx.NORMAL, wx.NORMAL)
 		text2.SetFont(font2)
 		text3.SetFont(font3)
-		url = wx.HyperlinkCtrl(self, -1, "code.google.com/p/gitso", "http://code.google.com/p/gitso")
+		url = wx.adv.HyperlinkCtrl(self, -1, "code.google.com/p/gitso", "http://code.google.com/p/gitso")
 		
 		data = open(os.path.join(paths['main'], 'icon.png'), "rb").read()
-		stream = cStringIO.StringIO(data)
-		img = wx.ImageFromStream(stream)
+		stream = io.BytesIO(data)
+		img = wx.Image(stream)
 		img.Rescale(150, 150)
-		bmp = wx.BitmapFromImage(img)
+		bmp = wx.Bitmap(img)
 		image1 = wx.StaticBitmap(self, -1, bmp)
 		
 		## Buttons ##
 		ok = wx.Button(self, wx.ID_OK, "OK")
 		self.SetDefaultItem(ok)
 		ok.SetFocus()
-		wx.EVT_BUTTON(self, wx.ID_OK, self.CloseAbout)
+		ok.Bind(wx.EVT_BUTTON, self.CloseAbout)
 		
 		## Sizers ##
 		topsizer = wx.BoxSizer(wx.VERTICAL);
--- a/ArgsParser.py
+++ b/ArgsParser.py
@@ -1,4 +1,4 @@
-#! /usr/bin/env python
+#! /usr/bin/env python3
 
 """
 Gisto - Gitso is to support others
@@ -60,10 +60,10 @@
 			if sys.argv[i] == '--help': # --help
 				self.HelpMenu()
 			elif sys.argv[i] == '--version': # --version
-				print "Gitso 0.6  -- Copyright 2007 - 2010 Aaron Gerber and Derek Buranen."
+				print("Gitso 0.6  -- Copyright 2007 - 2010 Aaron Gerber and Derek Buranen.")
 				exit(0)
 			elif sys.argv[i] == '--dev': # --dev
-				print "Running in 'Development Mode'"
+				print("Running in 'Development Mode'")
 				self.paths['mode'] = 'dev'
 				if sys.platform == "darwin":
 					if not os.path.exists('build/OSXvnc'):
@@ -86,25 +86,25 @@
 					self.paths['copyright'] = os.path.join(sys.path[0], 'COPYING')
 
 			elif sys.argv[i] == '--listen': # --listen
-				if self.paths['connect'] <> "":
-					print "Error: --connect and --listen can not be used at the same time."
+				if self.paths['connect'] != "":
+					print("Error: --connect and --listen can not be used at the same time.")
 					self.HelpMenu()
 				self.paths['listen'] = True
 
 			elif sys.argv[i] == '--connect': # --connect
 				i = i + 1
 				if i >= len(sys.argv):
-					print "Error: No IP or domain name given."
+					print("Error: No IP or domain name given.")
 					self.HelpMenu()
 
 				if self.paths['listen']:
-					print "Error: --connect and --listen can not be used at the same time."
+					print("Error: --connect and --listen can not be used at the same time.")
 					self.HelpMenu()
 				
-				if sys.argv[i][0] + sys.argv[i][1] <> "--":
+				if sys.argv[i][0] + sys.argv[i][1] != "--":
 					self.paths['connect'] = sys.argv[i]
 				else:
-					print "Error: '" + sys.argv[i] + "' is not a valid host with '--connect'."
+					print("Error: '" + sys.argv[i] + "' is not a valid host with '--connect'.")
 					self.HelpMenu()
 
 			elif sys.argv[i] == '--low-colors': # --low-colors
@@ -113,17 +113,17 @@
 			elif sys.argv[i] == '--list': # --list
 				i = i + 1
 				if i >= len(sys.argv):
-					print "Error: No List file given."
+					print("Error: No List file given.")
 					self.HelpMenu()
 				
-				if sys.argv[i][0] + sys.argv[i][1] <> "--":
+				if sys.argv[i][0] + sys.argv[i][1] != "--":
 					self.paths['list'] = self.getHosts(sys.argv[i])
 				else:
-					print "Error: '" + sys.argv[i] + "' is not a valid list with '--list'."
+					print("Error: '" + sys.argv[i] + "' is not a valid list with '--list'.")
 					self.HelpMenu()
 
 			else:
-				print "Error: '" + sys.argv[i] + "' is not a valid argument."
+				print("Error: '" + sys.argv[i] + "' is not a valid argument.")
 				self.HelpMenu()
 
 			i = i + 1
@@ -131,7 +131,7 @@
 		if sys.platform == "darwin":
 				self.paths['preferences'] = os.path.join(os.path.expanduser("~"), "Library", "Application Support", "Gitso")
 				if os.path.exists(self.paths['preferences']) != True:
-						os.makedirs(self.paths['preferences'], 0700)
+						os.makedirs(self.paths['preferences'], 0o700)
 				self.paths['preferences'] = os.path.join(self.paths['preferences'], "hosts")
 		elif sys.platform == "win32":
 				self.paths['preferences'] = os.path.join(os.getenv('USERPROFILE'), "gitso-hosts")
@@ -140,15 +140,15 @@
 
 	#Help Menu
 	def HelpMenu(self):
-		print "Usage: " + os.path.basename(sys.argv[0]) + " [OPTION]"
-		print "   OPTIONS"
-		print "   --dev\t\tSet self.paths for development."
-		print "   --listen\t\tListen for incoming connections."
-		print "   --connect {IP|DN}\tConnects to host (support giver)."
-		print "   --list {URL|FILE}\tAlternative Support list."
-		print "   --low-colors\t\tUse 8bit colors (for slow connections). Linux only."
-		print "   --version\t\tThe current Gitso version."
-		print "   --help\t\tThis Menu."
+		print("Usage: " + os.path.basename(sys.argv[0]) + " [OPTION]")
+		print("   OPTIONS")
+		print("   --dev\t\tSet self.paths for development.")
+		print("   --listen\t\tListen for incoming connections.")
+		print("   --connect {IP|DN}\tConnects to host (support giver).")
+		print("   --list {URL|FILE}\tAlternative Support list.")
+		print("   --low-colors\t\tUse 8bit colors (for slow connections). Linux only.")
+		print("   --version\t\tThe current Gitso version.")
+		print("   --help\t\tThis Menu.")
 		exit(1)
 	
 	def GetPaths(self):
--- a/ConnectionWindow.py
+++ b/ConnectionWindow.py
@@ -1,4 +1,4 @@
-#! /usr/bin/env python
+#! /usr/bin/env python3
 
 """
 Gisto - Gitso is to support others
@@ -24,7 +24,7 @@
 """
 
 import wx
-import os, sys, signal, os.path, time, thread, re
+import os, sys, signal, os.path, time, _thread as thread, re
 import AboutWindow, GitsoThread
 
 class ConnectionWindow(wx.Frame):
@@ -61,7 +61,7 @@
 			xval1 = 180
 			xval2 = 265
 		
-		wx.Frame.__init__(self, parent, wx.ID_ANY, title, size=(height,width), style=wx.DEFAULT_FRAME_STYLE & ~ (wx.RESIZE_BORDER | wx.RESIZE_BOX | wx.MAXIMIZE_BOX))
+		wx.Frame.__init__(self, parent, wx.ID_ANY, title, size=(height,width), style=wx.DEFAULT_FRAME_STYLE & ~ (wx.RESIZE_BORDER | wx.MAXIMIZE_BOX))
 		self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
 		
 		if sys.platform == 'win32':
@@ -74,10 +74,10 @@
 		#Buttons
 		self.connectButton = wx.Button(self, 10, "Start", wx.Point(xval1, 81))
 		self.connectButton.SetDefault()
-		wx.EVT_BUTTON(self, 10, self.ConnectSupport)
+		self.connectButton.Bind(wx.EVT_BUTTON, self.ConnectSupport)
 		self.stopButton = wx.Button(self, wx.ID_STOP, "", wx.Point(xval2, 81))
 		self.stopButton.Enable(False)
-		wx.EVT_BUTTON(self, wx.ID_STOP, self.KillPID)
+		self.stopButton.Bind(wx.EVT_BUTTON, self.KillPID)
 		
 		# Radio Boxes
 		self.rb1 = wx.RadioButton(self, -1, 'Get Help', (10, 15), style=wx.RB_GROUP)
@@ -114,23 +114,23 @@
 		editMenu.Append(11, "&Cut\tCtrl+X", "Cut IP Address")
 		editMenu.Append(12, "&Copy\tCtrl+C", "Copy IP Address")
 		editMenu.Append(wx.ID_PASTE, "&Paste\tCtrl+V", "Paste IP Address")
-		wx.EVT_MENU(self, 11, self.SetClipboard)
-		wx.EVT_MENU(self, 12, self.SetClipboard)
-		wx.EVT_MENU(self, wx.ID_PASTE, self.GetClipboard)
+		editMenu.Bind(wx.EVT_MENU, self.SetClipboard, id=11)
+		editMenu.Bind(wx.EVT_MENU, self.SetClipboard, id=12)
+		editMenu.Bind(wx.EVT_MENU, self.GetClipboard, id=wx.ID_PASTE)
 		
 		fileMenu.Append(13, "&Clear History", "Clear History")
 		if sys.platform == 'darwin':
 			fileMenu.Append(wx.ID_ABOUT, "&About", "About Gitso")
-			wx.EVT_MENU(self, wx.ID_ABOUT, self.ShowAbout)
+			fileMenu.Bind(wx.EVT_MENU, self.ShowAbout, id=wx.ID_ABOUT)
 		else:       
 			fileMenu.Append(wx.ID_EXIT, "&Quit\tCtrl+Q", "Quit Gitso")
-			wx.EVT_MENU(self, wx.ID_EXIT, self.OnCloseWindow)
+			fileMenu.Bind(wx.EVT_MENU, self.OnCloseWindow, id=wx.ID_EXIT)
 		
 		helpMenu = wx.Menu()
 		helpMenu.Append(wx.ID_ABOUT, "&About", "About Gitso")
-		wx.EVT_MENU(self, wx.ID_ABOUT, self.ShowAbout)
+		helpMenu.Bind(wx.EVT_MENU, self.ShowAbout, id=wx.ID_ABOUT)
 		
-		wx.EVT_MENU(self, 13, self.clearHistory)
+		helpMenu.Bind(wx.EVT_MENU, self.clearHistory, id=13)
 		
 		menuBar.Append(fileMenu, "&File")
 		menuBar.Append(editMenu, "&Edit")
@@ -155,7 +155,7 @@
 			self.rb2.Value = True
 			self.RadioToggle(None)
 			self.ConnectSupport(None)
-		elif self.paths['connect'] <> "":
+		elif self.paths['connect'] != "":
 			self.rb1.Value = True
 			self.RadioToggle(None)
 			self.hostField.Value = self.paths['connect']
@@ -281,7 +281,7 @@
 		@author: Derek Buranen
 		@author: Aaron Gerber
 		"""
-		if self.thread <> None:
+		if self.thread != None:
 			self.thread.kill()
 			# If you don't wait 0.5+ seconds, the interface won't reload and it'll freeze.
 			# Possibly on older systems you should wait longer, it works fine on mine...
@@ -322,7 +322,7 @@
 			handle = open(file, 'a')
 			handle.write(", %s" % host)
 			handle.close()
-                else:
+		else:
 			handle = open(file, 'w')
 			handle.write("%s" % host)
 			handle.close()
--- a/Gitso.py
+++ b/Gitso.py
@@ -1,4 +1,4 @@
-#! /usr/bin/env python
+#! /usr/bin/env python3
 
 """
 Gisto - Gitso is to support others
@@ -30,7 +30,7 @@
 	# If we're on Snow Leopard, we want to use Python 2.5 until we figure out what Apple's doing with 2.6
 	ver = platform.mac_ver()
 
-	if re.match('10\.5', ver[0]) <> None:
+	if re.match('10\.5', ver[0]) != None:
 		"""
 		sys.path.append('/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python26.zip')
 		sys.path.append('/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5')
@@ -45,7 +45,7 @@
 		sys.path.append('/System/Library/Frameworks/Python.framework/Versions/2.5/Extras/lib/python/PyObjC')
 		"""
 		sys.path.append('/System/Library/Frameworks/Python.framework/Versions/2.5/Extras/lib/python/wx-2.8-mac-unicode')
-	elif re.match('10\.6', ver[0]) <> None:
+	elif re.match('10\.6', ver[0]) != None:
 		sys.path.append('/System/Library/Frameworks/Python.framework/Versions/2.6/Extras/lib/python/wx-2.8-mac-unicode')
 
 import wx
--- a/GitsoThread.py
+++ b/GitsoThread.py
@@ -1,4 +1,4 @@
-#! /usr/bin/env python
+#! /usr/bin/env python3
 
 """
 Gisto - Gitso is to support others
@@ -48,7 +48,7 @@
 		
 		@author: Aaron Gerber
 		"""
-		if self.host <> "":
+		if self.host != "":
 			# Get Help
 			self.pid = self.process.getSupport(self.host)
 			time.sleep(.5)
@@ -73,7 +73,7 @@
 				self.window.setMessage("Could not start server.", False)
 				self.error = True
 
-		print "GitsoThread.run(pid: " + str(self.pid) + ") running..."
+		print("GitsoThread.run(pid: " + str(self.pid) + ") running...")
 
 		while(self.running and self.checkStatus()):
 			time.sleep(.2)
@@ -123,19 +123,19 @@
 		connection = []
 		listen = []
 		if sys.platform == 'darwin' or re.match('(?:open|free|net)bsd|linux',sys.platform):
-			if self.host <> "":
+			if self.host != "":
 				connection = os.popen('LANG=C netstat -an | grep 5500 | grep ESTABLISHED').readlines()
 			else:
 				listen = os.popen('LANG=C netstat -an | grep 5500 | grep LISTEN').readlines()
 		elif sys.platform == 'win32':
 			#XP PRO only -- Need to fix the case where there is no process, it'll still return 1 line.
 			#info = os.popen('WMIC PROCESS ' + str(self.pid) + ' get Processid').readlines()
-			if self.host <> "":
+			if self.host != "":
 				connection = os.popen('netstat -a | find "ESTABLISHED" | find "5500"').readlines()
 			else:
 				listen = os.popen('netstat -a | find "LISTEN" | find "5500"').readlines()
 		else:
-			print 'Platform not detected'
+			print('Platform not detected')
 		
 		if len(connection) == 0 and len(listen) == 0:
 			return False
@@ -153,17 +153,17 @@
 			if self.window.enablePMP:
 				if action == 'request':
 					lifetime = 3600
-					print "Request port 5500 (NAT-PMP)."
+					print("Request port 5500 (NAT-PMP).")
 				else:
 					lifetime = 0
-					print "Give up port 5500 (NAT-PMP)."
+					print("Give up port 5500 (NAT-PMP).")
 		
 				pubpriv_port = int(5500)
 				protocol = NATPMP.NATPMP_PROTOCOL_TCP
 				
 				try:
 					gateway = NATPMP.get_gateway_addr()
-					print NATPMP.map_port(protocol, pubpriv_port, pubpriv_port, lifetime, gateway_ip=gateway)
+					print(NATPMP.map_port(protocol, pubpriv_port, pubpriv_port, lifetime, gateway_ip=gateway))
 				except:
-					print "Warning: Unable to automap port."
+					print("Warning: Unable to automap port.")
 
--- a/NATPMP.py
+++ b/NATPMP.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 """NAT-PMP client library
 
@@ -368,5 +368,5 @@
 if __name__ == "__main__":
     addr = get_public_address()
     map_resp = map_tcp_port(62001, 62001)
-    print addr
-    print map_resp.__dict__
+    print(addr)
+    print(map_resp.__dict__)
--- a/Processes.py
+++ b/Processes.py
@@ -1,4 +1,4 @@
-#! /usr/bin/env python
+#! /usr/bin/env python3
 
 """
 Gisto - Gitso is to support others
@@ -46,8 +46,8 @@
 			time.sleep(3)
 		elif sys.platform == 'win32':
 			import subprocess
-                        self.returnPID = subprocess.Popen(['WinVNC.exe'])
-			print "Launched WinVNC.exe, waiting to run -connect command..."
+			self.returnPID = subprocess.Popen(['WinVNC.exe'])
+			print("Launched WinVNC.exe, waiting to run -connect command...")
 			import time
 			time.sleep(3)
 			
@@ -56,7 +56,7 @@
 			else:
 				subprocess.Popen(['WinVNC.exe', '-connect', '%s' % host])
 		else:
-			print 'Platform not detected'
+			print('Platform not detected')
 		return self.returnPID
 	
 	def giveSupport(self):
@@ -79,7 +79,7 @@
 			else:
 				self.returnPID = subprocess.Popen(['vncviewer.exe', '-listen'])
 		else:
-			print 'Platform not detected'
+			print('Platform not detected')
 		return self.returnPID
 
 	def KillPID(self):
@@ -90,7 +90,7 @@
 		@author: Aaron Gerber
 		"""
 		if self.returnPID != 0:
-			print "Processes.KillPID(" + str(self.returnPID) + ")"
+			print("Processes.KillPID(" + str(self.returnPID) + ")")
 			if sys.platform == 'win32':
 				import win32api
 				PROCESS_TERMINATE = 1
--- a/arch/linux/gitso
+++ b/arch/linux/gitso
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 import sys, os, wx
 sys.path.append(os.path.join(sys.path[0], '..', 'share', 'gitso'))
@@ -6,7 +6,7 @@
 from Gitso import ConnectionWindow, ArgsParser
 
 if __name__ == "__main__":
-	app = wx.PySimpleApp()
+	app = wx.App()
 	args = ArgsParser.ArgsParser()
 	ConnectionWindow.ConnectionWindow(None, -1, "Gitso", args.GetPaths())
 	app.MainLoop()
