Some time ago I wrote a simple Tic-tac-toe game in Python (2.7), multiplayer version with server script (thread per connection) and client script. Now I want to extend client with gtk. I would like this to be an example of the use of decorators. Client script works in such a way that it retrieves data through the prompt. I want to write a script with will be something like a patch for client (just decorate clients functions, call new gtk-client script and wallah). I thought to do it that way:
This is my idea to control client script by gtk interface, but I came across some problems:
Edit: Ok, I found a solution. I will create decorator who will overwrite raw_input() function (monkey pathing). It should look like this:
It looks like a good solution, but here is my another problem. My gtk-client calls thread (run_game()). If I do not use thread.join(), my thread is blocked in execution or print function can't print whole data to console. If I use thread.join() that creates a conflict, because thread waits for data in queue. Example test codes:
gtk-client.py
import gtk
import client as cliApp
from threading import Thread
from Queue import Queue
# gtk stuff etc...
# lets say it is called on y_button_click, part of GameGtk class
def y_button_click(self, widget):
cliApp.q.put('test msg')
# lets say that it is called in x_button_click
@run_game_decorator(func):
def wrapper(*args):
# some connecting/logging stuff
cliApp.q = Queue()
t = Thread(target = cliApp.test)
t.start()
# t.join() - worked until I added q.get() to new raw_input()
return wrapper
# gtk still working after this function
client.py
def new_raw_input(label):
print label
return q.get()
def test():
print 'Thread start'
raw_input = new_raw_input
a = raw_input("Type something: ")
print a
print 'Thread finished'
In this case my thread prints only 'Thread start'. How to handle this problem?
Ok, finally I found solution for all my problems. To simulate user input to raw_input() just change function funcionality (monkey patching) as shown in question, edited section.
Regarding to print errors in console - I resolvet it by adding sys.stdout.flush() to flush buffers (explained here), and waiting for thread after putting data to queue.
gtk-client.py
import gtk
import client as cliApp
from threading import Thread
from Queue import Queue
from time import sleep
import sys
# gtk stuff etc...
# lets say it is called on y_button_click, part of GameGtk class
def y_button_click(self, widget):
cliApp.q.put('test msg')
self.t.join()
# lets say that it is called in x_button_click
@run_game_decorator(func):
def wrapper(*args):
# some connecting/logging stuff
cliApp.q = Queue()
gtkWindow.t = Thread(target = cliApp.test)
gtkWindow.t.start()
sleep(0.1)
sys.stdout.flusch()
return wrapper
# gtk still working after this function