Pytest plugin opening GUI - python

I am trying to create a py.test plugin to reproduce Pydev for Eclipse behaviour, that you can see on the image below:
Basically, the idea would be to open an empty window during the call to pytest_sessionstart(), to fill it (update list of tests and progress bar) with objects returned by pytest_runtest_makereport(), and to close it with pytest_unconfigure().
I tried to achieve this with Tkinter, by using the following code:
import Tkinter
def pytest_sessionstart(session):
print "Tests are starting"
Tkinter.Tk().mainloop()
print "The window was opened" # This step is never reached
When running the tests, it prints the first sentence, opens the window but doesn't come back to py.test until we close the window.
If I remove the call to mainloop(), the window is opened but instantly destroyed.
I also tried to open the window in a separate thread by doing:
t = threading.Thread(target=Tkinter.Tk().mainloop())
but without success. Anyway, the threading option doesn't seem very good as Tkinter has to run in the main thread, which is not possible in the case of a py.test plugin.
So, does any of you have an idea about how to solve this problem? The only requirement is to keep py.test.
Thank you in advance :)

Tkinter.Tk().mainloop() is a while True loop. You won't be getting out of it. There are two ways to solve your problem in my opinion:
Use pytest inside Tkinter app. You can invoke pytest within the tkinter code like this.
Use pytest in different thread and pipe the output of pytest to Tkinter app.

Related

Tkinter Toplevel window and multiple workspaces - place window in originating linux workspace

I run this on Debian Gnome, but I think this is relevant for most UNIX distributions and interfaces:
from time import sleep
from Tkinter import Tk,Toplevel
tk=Tk()
def run():
sleep(3)
Toplevel(tk)
run()
In Gnome, running this and switching a workspace will cause the Toplevel window to appear in your current workspace, instead of the one that actually runs the command. Is there a way to fix this so the new window appears where the command runs? If this is a Gnome specific thing let me know and I'll amend the question and tags.
To be clear: I have an app that can pop these windows up on it's own while working - and I'm doing other things. The sleep in the above is there to emulate that.
This makes sense it would work this way, but I'm wondering if there is any easy bypass? I have an application using Toplevels as "patience, running" windows, and it's annoying when they appear in different workspaces.

Python Tkinter to run subprocess on a different thread to avoid non-responding GUI

I've been fighting with Tkinter for a while now and have exhausted most the resources I have for referencing this. I've found a couple similar topics here but none quite bring me to where I need to be.
I've got a long running (not long actually, it only takes 10-12 secs) python script that silently install an application using subprocess from the CLI. Subprocess worked and it successfully installed the application, however, the GUI locks (i.e hangs/freeze) after the execution (and the program no longer run the succeeding code). I know I have to use threading here but I've already tried using it to no avail.
As part of my learning process, I cloned a repo from Github and modify it to run on Windows (since it only run in MAC platform) and planning to extend it, and this is the part where I got stucked. This is my first time to use TKinter and I apologize if I have missed something stupid or not asked the question in the right way. Hope you can help me and thank you in advance for the assistance.
Code can be found on this link.
You have defined a button
installButton = Button(bottomFrame, text=installButtonTxt,
command=on_install_thread, width=9)
with command handler
def on_install_thread():
...
loop_thread = threading.Thread(target=on_install_button_active,
args=['button', 'model', itemSelectCount])
and the target for thread on_install_button_active.
Then
def on_install_button_active(button, model, selectcount):
...
# Reset install status
installStatus = 'complete'
# Remove Cancel Button
cancelButton.destroy()
# Activate Install/Done button and menus
installButton.configure(state=NORMAL)
# menuControl('normal')
refreshGui(mainWindow)
It looks like there is code at the end of on_install_button_active that involves Tkinter
widgets. Calling tkinter methods from other threads seems to be unreliable, for example 1.
It is possible to define virtual events
def renderMainWindow():
...
mainWindow.bind('<<InstallComplete>>', on_install_complete)
def on_install_complete():
cancelButton.destroy()
installButton.configure(state=NORMAL)
def on_install_button_active(button, model, selectcount):
...
# Reset install status
installStatus = 'complete'
mainWindow.event_generate('<<InstallComplete>>', when='tail')
If there are other calls in that thread that involve Tkinter widgets, it might be better to remove them.
I was able to resolved problems with my GUI by using mtTkinter and by referring to this post.

How to get cmd in Tkinter widget

I'm creating Tkinter GUI and want to add windows CMD into tkinter widget. I would like to use console to connect to database. I did some research and found only pyconsole module, but with some bugs:
cls is not going to do what you expect;
edit is not going to show an editor (try start edit instead);
prompt anything fails too;
the color command is not implemented;
the great ^C isn't supported too (it actually copies text, instead of interrupting a process).
Especially ^C command ommited is huge limitation for sql scripts i want to run.
I'm able to open console like this:
Popen(["cmd.exe"], creationflags=CREATE_NEW_CONSOLE)
But with this approach I don't know how to interact with the GUI (is it even possible?)
Also my Text widget can read output from command line, but I need to also write in that command line, not just read it...
Is there a possibility to get regular CMD into Tkinter widget, which will react with the rest of widgets in GUI?
Desired behaviour would be CMD console on the right side as you can see on picture below (in tkinter window), that would interact with the Listbox on the left. I'm not looking for exact code (that's why no my code stated here), but method/solution how to put CMD into tkinter.
Photo:
Thanks
Honza
I think you can use an Entry to input the commands you want to execute.
Then you can use subprocess.run and subprocess.Popen to execute the commands, and a Text or even better a tkinter.scrolledtext.ScrolledText widget to show the results.

Can I safely use a thread to call a script from a Tkinter application with subprocess.call?

So I have a Tkinter application that I use at work. I wrote another Tkinter application that I wanted to call from the main Tkinter application. I know that Tkinter isn't 'thread safe', but I'm not 100% sure what that means. Does it mean that it can 'work', but it isn't guaranteed to work as written? Or should it just not work at all?
The reason I ask is because when I run the code below(self.thread_easy_imaging() is triggered by a filemenu option), it works just fine. So far I haven't encountered any issues and both GUIs are operational so far as I can tell. Is this because I'm using subprocess.call to call the script? I'm having a hard time wrapping my head around this because I know you can't use thread in a Tkinter app to do something like run a function while still being able to use buttons in the GUI, but for some reason when I use a thread to call the script with subprocess.call it does it just fine. When I wrote it, I assumed it wouldn't work, but for some odd reason it does. Here is an example of the code I'm using:
def thread_easy_imaging(self):
thread.start_new_thread(self.start_easy_imaging, ('EASY-IMAGING-1', 0))
def start_easy_imaging(self, thread_name, delay):
time.sleep(delay) #have to have args for some reason? I just did a delay of 0 seconds so I could use the tuple.
subprocess.call(['c:/python27/python.exe', 'EasyImaging.py'])
self.thread_easy_imaging()
I have only used this on a windows machine, but I'm guessing that it should work on any OS.
Edit: The scripts don't have to interact at all, I just want to add my other GUI application into the filemenu so I can call it as a separate application. If needed, I'll just use a Toplevel widget to recreate the application I want to call because it won't muck up the main thread at all.
Thanks in advance!

Locking PC in Python on Ubuntu

i'm doing application that locks the PC using pyGtk, but i have a problem, when i click on the ok button the function of the button should get the time from the textbox, hide the window then sleep for a while, and at last lock the pc using a bash command. but it just don't hide.
and here is the complete program
Provided you are using Gnome on Ubuntu
import os
os.system('gnome-screensaver-command –-lock')
Is there any reason for the main class to be a thread? I would make it just a normal class, which would be a lot easier to debug. The reason its not working is that all gtk related stuff must happen in the gtk thread, so do all widget method calls like this: gobject.idle_add(widget.method_name). So to hide the password window: gobject.idle_add(self.pwdWindow.hide)
You'll have to import gobject first of course (You might need to install it first).
EDIT: I don't think that that was your problem, either way I edited your program a lot, here is the modified code.

Categories

Resources