Here is the question: How can I define an event that is occurring whenever a widget's function is not being called?
Or, wow can I periodically update an stringVar in tkinter(Example, updating time on a clock)? Particularly, the variable is changing based off of data scraped from the web, some applications I'm looking at are; stock tickers, weather indicators, home security systems, and monitoring sensors that report via web.
So far, the only thing I can think of is to create a function who's last call triggers an event that calls the function again. In this case, I couldn't find a standard event that looked suitable, so I would have to define one, but I'm not too familiar with doing this yet, and furthermore, I would like to avoid this if there is a simpler way.
Sources I've been using to research this project,
www.automatetheboringstuff.com ... thank you Al Sweigart, this has been an excellent resource.
"Tkinter GUI Application Development Blueprints" by Bhaskar Chaudhary
"Tkinter GUI Development Hotshot: Develop Exciting and Engaging GUI Applications in Python and Tkinter by Working on 10 Real-world Applications" by Chaudhary, Bhaskar
Here is the code I've come up with so far.
from tkinter import *
import requests
import bs4
root = Tk()
svar1 = StringVar() #string variable to display data in the Entry Widget.
button1 = Button(root, text="What time is it?") #Button to be clicked to call a function, I don't want a button in the final product.
label1 = Label(root, text="Time From Google") #this snippet pulls the current time from google.
entry2 = Entry(root, textvariable = svar2)
def gettimefromGoogle():
site1 = requests.get("the url for a google search of 'what time is it right now?'")
if not site1.status_code ==200: # make sure site loaded, if not, did you replace the code in the previous line?
print('Time to play dino game!! ;)')
return
site1soup = bs4.BeautifulSoup(site1.text)
elems = site1soup.select('div')
time = elems[29].getText() #when I created the program, element 29 seemed to have the right data
time = time.replace(" ('your time zone') Time in 'your city', 'your state'",'') #for code to work, you'll have to replace the '' with your own info.
svar1.set(time)
site1= 1 #reassign the namespace, just to save space since Beautiful Soup objects can be quite large.
entry1 = Entry(root, textvariable = svar1, command=gettimefromGoogle)
button1.bind("<Button-1>",gettimefromGoogle) #this is where it would be nice to have an action that calls the function at a periodic interval, say every 10 seconds or so.
button1.grid(row=3,column=2) #currently, the button displays the time when clicked.
label1.grid(row=1,column=2)
entry1.grid(row=2,column=2, columnspan=4)
root.mainloop()`
Related
I have a Python/PyQt application that loads many file references into memory and informs the user of information (text) within each file. It even allow the user to open an editor (vim in my case) using Popen. I would like the program, which lists all the files it opened in a QTreeView, to mark a checkbox in a column with the mtime if newer then the start of the application. I know how to get the mtime of a file. What I want to do is know if the file has been updated (modified - Windows OS) and change the checkbox state to reflect the fact that the file is now modified (dirty). It seems to me that I could do this by running a separate Thread (or QDialog with nothing displayed?) But this would require a process to continually be doing a getmtime on a list of files and communicating with the MainWindow. It could be that the polling loop has some sleep in it so as to not take up too many cycles, but this presents other issues. I would really like it for the OS to emit a file_change, but I do not think that is a likely solution. Any thoughts?
There's watchdog, which monitors for filesystem changes on a few platforms, including windows.
If you want to do it yourself, the mechanism in use here, for the non-polling monitoring on windows, is the ReadDirectoryChangesW API function
Alternatively, there's the FindFirstChangeNotification API call, which is a bit less complicated for some use cases.
Here is a good write up about using all of these routines on windows, in python.
The suggestion to use FindFirstChange from otherchirps sent me in the direction I was looking for. My end answer was to use QFileSystemWatcher from PyQt4. This provided the features I wanted and closer integration with Qt. The following is an example of how to watch files, and directories using QFileSystemWatcher. Now I can extend the paths/files to check and ask which ones are being monitored. This lacks a lot of error checking, but it is a stub to start work from.
import sys
from PyQt4 import QtCore
from PyQt4 import QtGui
from os import curdir
class MainWindow(QtGui.QMainWindow):
path_Sig = QtCore.SIGNAL('pathsAdd()')
def __init__(self):
super(MainWindow, self).__init__()
self.path = ['./test.dat', 'local1.bdf', 'Sub/sub1.bdf']
button = QtGui.QPushButton('Paths')
self.label = QtGui.QLabel(curdir)
widget = QtGui.QWidget()
layout = QtGui.QVBoxLayout(widget)
layout.addWidget(button)
layout.addWidget(self.label)
self.setCentralWidget(widget)
self.connect(button, QtCore.SIGNAL('clicked()'), self.setPaths)
#QtCore.pyqtSlot(list)
def setPaths(self):
self.emit(QtCore.SIGNAL('path_Sig'), self.path)
self.myPaths(self.path)
#QtCore.pyqtSlot(list)
def myPaths(self, path_list):
self.label.setText(str().join(path_list))
#QtCore.pyqtSlot("QString")
def dirChanged(self, results):
self.label.setText("Dir {} changed".format(results))
#QtCore.pyqtSlot("QString")
def fileChanged(self, results):
self.label.setText("File {} changed".format(results))
class FileWatcher(QtCore.QFileSystemWatcher):
these_Sig = QtCore.SIGNAL('myPaths()')
def __init__(self, paths=None):
super(FileWatcher, self).__init__()
try:
self.addPaths(paths)
except:
self.addPath(curdir)
#QtCore.pyqtSlot()
def filesReport(self):
self.emit(QtCore.SIGNAL('these_Sig'), self.files())
#QtCore.pyqtSlot(list)
def pathsAdd(self, path_list):
self.addPaths(path_list)
self.filesReport()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
app.setApplicationName('FileWatcherDemo')
window = MainWindow()
window.show()
filewatcher = FileWatcher()
QtCore.QObject.connect(filewatcher, QtCore.SIGNAL('directoryChanged(QString)'), window, QtCore.SLOT('dirChanged(QString)'))
QtCore.QObject.connect(filewatcher, QtCore.SIGNAL('fileChanged(QString)'), window, QtCore.SLOT('fileChanged(QString)'))
QtCore.QObject.connect(filewatcher, QtCore.SIGNAL('these_Sig'), window.myPaths)
QtCore.QObject.connect(window, QtCore.SIGNAL('path_Sig'), filewatcher.pathsAdd)
sys.exit(app.exec_())
Newbie here, running scrapy in windows. How to avoid showing the extracted links and crawled items in the command window? I found comments in the "parse" section on this linkhttp://doc.scrapy.org/en/latest/topics/commands.html, not sure if it's relevant and how to apply it if so. Here is more detail with part of the code, starting from my second Ajax request (In the first Ajax request, the callback function is "first_json_response":
def first_json_response(self, response):
try:
data = json.loads(response.body)
meta = {'results': data['results']}
yield Request(url=url, callback=self.second_json_response,headers={'x-requested-with': 'XMLHttpRequest'}, meta = meta)
def second_json_response(self, response):
meta = response.meta
try:
data2 = json.loads(response.body)
...
The "second_json_response" is to retrieve the response from the requested result in first_json_response, as well as to load the new requested data. "meta" and "data" are then both used to define items that need to be crawled. Currently, the meta and links are shown in the windows terminal where I submitted my code. I guess it is taking up some extra time for computer to show them on the screen, and thus want them to disappear. I hope by running scrapy on a kinda-of batch mode will speed up my lengthy crawling process.
Thanks! I really appreciate your comment and suggestion!
From scrapy documentation:
"You can set the log level using the –loglevel/-L command line option, or using the LOG_LEVEL setting."
So append to your scray crawl etc command -loglevel='ERROR' . That should make all the info disappear from your command line, but I don't think this will speed things much.
In your pipelines.py file, try using something like:
import json
class JsonWriterPipeline(object):
def __init__(self):
self.file = open('items.jl', 'wb')
def process_item(self, item, spider):
line = json.dumps(dict(item)) + "\n"
self.file.write(line)
return item
This way, when you yield an item from your spider class, it will print it out to items.jl.
Hope that helps.
I'm new in Frameworks like Bottle and working through the Documentation/Tutorial.
Now I got a Problem with the Template-Engine:
I have a file called index.tpl in my folder views. (it's plain html)
When I use the following Code, it works to display my html:
from bottle import Bottle, SimpleTemplate, run, template
app = Bottle()
#app.get('/')
def index():
return template('index')
run(app, debug=True)
Now I want to implement this engine in my project and dont want to use template()
I want to use it as it stands in the documentation, like:
tpl = SimpleTemplate('index')
#app.get('/')
def index():
return tpl.render()
But if I do so, the Browser shows me just a white page with the word
index
written, instead of loading the template.
In the documentation, there is no further information on how I use this OO approach.
I just couldn't figure out why this happens and how I have to do it right...
Here's a nice, simple solution in the spirit of your original question:
tpl = SimpleTemplate(name='views/index.tpl') # note the change here
#app.get('/')
def index():
return tpl.render()
I recorded some test cases with CUIT in VS2010. Everything worked fine the day before. So, today I run again, all the test failed, with the warning: The following element is no longer available ... and I got the exception : Can't perform "Click" on the hidden control, which is not true because all the controls are not hidden. I tried on the other machine, and they failed as well.
Does anyone know why it happens? Is it because of the web application for something else? Please help, thanks.
PS: So I tried to record a new test with the same controls that said "hidden controls", and the new test worked!? I don't understand why.
EDIT
The warning "The following element blah blah ..." appears when I tried to capture an element or a control while recording. The source code of the button is said 'hidden'
public HtmlImage UIAbmeldenImage
{
get
{
if ((this.mUIAbmeldenImage == null))
{
this.mUIAbmeldenImage = new HtmlImage(this);
#region Search Criteria
this.mUIAbmeldenImage.SearchProperties[HtmlImage.PropertyNames.Id] = null;
this.mUIAbmeldenImage.SearchProperties[HtmlImage.PropertyNames.Name] = null;
this.mUIAbmeldenImage.SearchProperties[HtmlImage.PropertyNames.Alt] = "abmelden";
this.mUIAbmeldenImage.FilterProperties[HtmlImage.PropertyNames.AbsolutePath] = "/webakte-vnext/content/apps/Ordner/images/logOut.png";
this.mUIAbmeldenImage.FilterProperties[HtmlImage.PropertyNames.Src] = "http://localhost/webakte-vnext/content/apps/Ordner/images/logOut.png";
this.mUIAbmeldenImage.FilterProperties[HtmlImage.PropertyNames.LinkAbsolutePath] = "/webakte-vnext/e.consult.9999/webakte/logout/index";
this.mUIAbmeldenImage.FilterProperties[HtmlImage.PropertyNames.Href] = "http://localhost/webakte-vnext/e.consult.9999/webakte/logout/index";
this.mUIAbmeldenImage.FilterProperties[HtmlImage.PropertyNames.Class] = null;
this.mUIAbmeldenImage.FilterProperties[HtmlImage.PropertyNames.ControlDefinition] = "alt=\"abmelden\" src=\"http://localhost/web";
this.mUIAbmeldenImage.FilterProperties[HtmlImage.PropertyNames.TagInstance] = "1";
this.mUIAbmeldenImage.WindowTitles.Add("Akte - Test Akte Coded UI VS2010");
#endregion
}
return this.mUIAbmeldenImage;
}
}
Although I am running Visual Studio 2012, I find it odd that we started experiencing the same problem on the same day, I can not see any difference in the DOM for the Coded UI Tests I have for my web page, but for some reason VS is saying the control is hidden and specifies the correct ID of the element it is looking for (I verified that the ID is still the same one). I even tried to re-record the action, because I assumed that something must have changed, but I get the same error.
Since this sounds like the same problem, occurring at the same time I am thinking this might be related to some automatic update? That's my best guess at the moment, I am going to look into it, I will update my post if I figure anything out.
EDIT
I removed update KB2870699, which removes some voulnerability in IE, this fixed the problems I was having with my tests. This update was added on the 12. september, so it fits. Hope this helps you. :)
https://connect.microsoft.com/VisualStudio/feedback/details/800953/security-update-kb2870699-for-ie-breaks-existing-coded-ui-tests#tabs
Official link to get around the problem :
http://blogs.msdn.com/b/visualstudioalm/archive/2013/09/17/coded-ui-mtm-issues-on-internet-explorer-with-kb2870699.aspx
The problem is more serious than that! In my case I can't even record new Coded UI Tests. After I click in any Hyper Link of any web page of my application the coded UI test builder cannot record that click "The following element is no longer available....".
Apparently removing the updates, as said by AdrianHHH do the trick!
Shut down VS2010, launch it again "Run as administrator".
There may be a field in the SearchProperties (or possible the FilterProperties) that has a value set by the web site, or that represents some kind of window ID on your desktop. Another possibility is that the web page title changes from day to day or visit to visit. Different executions of the browser or different visits to the web page(s) create different values. Removing these values from the SearchProperties (or FilterProperties) or changing the check for the title from an equals to a contains for a constant part of the title should fix the problem. Coded UI often searches for more values than the minimum set needed.
Compare the search properties etc for the same control in the two recorded tests.
Update based extra detail given in the comments:
I solved a similar problem as follows. I copied property code similar to that shown in your question into a method that called FindMatchingControls. I checked how many controls were returned, in my case up to 3. I examined various properties of the controls found, by writing lots of text to a debug file. In my case I found that the Left and Top properties were negative for the unwanted, ie hidden, controls.
For your code rather than just using the UIAbmeldenImage property, you might call the method below. Change an expression such as
HtmlImage im = UIMap.abc.def.UIAbmeldenImage;
to be
HtmlImage im = FindHtmlHyperLink(UIMap.abc.def);
Where the method is:
public HtmlImage FindHtmlHyperLink(HtmlDocument doc)
{
HtmlImage myImage = new HtmlImage(doc);
myImage.SearchProperties[HtmlImage.PropertyNames.Id] = null;
myImage.SearchProperties[HtmlImage.PropertyNames.Name] = null;
myImage.SearchProperties[HtmlImage.PropertyNames.Alt] = "abmelden";
myImage.FilterProperties[HtmlImage.PropertyNames.AbsolutePath] = "/webakte-vnext/content/apps/Ordner/images/logOut.png";
myImage.FilterProperties[HtmlImage.PropertyNames.Src] = "http://localhost/webakte-vnext/content/apps/Ordner/images/logOut.png";
myImage.FilterProperties[HtmlImage.PropertyNames.LinkAbsolutePath] = "/webakte-vnext/e.consult.9999/webakte/logout/index";
myImage.FilterProperties[HtmlImage.PropertyNames.Href] = "http://localhost/webakte-vnext/e.consult.9999/webakte/logout/index";
myImage.FilterProperties[HtmlImage.PropertyNames.Class] = null;
myImage.FilterProperties[HtmlImage.PropertyNames.ControlDefinition] = "alt=\"abmelden\" src=\"http://localhost/web";
myImage.FilterProperties[HtmlImage.PropertyNames.TagInstance] = "1";
myImage.WindowTitles.Add("Akte - Test Akte Coded UI VS2010");
UITestControlCollection controls = myImage.FindMatchingControls();
if (controls.Count > 1)
{
foreach (UITestControl con in controls)
{
if ( con.Left < 0 || con.Top < 0 )
{
// Not on display, ignore it.
}
else
{
// Select this one and break out of the loop.
myImage = con as HtmlImage;
break;
}
}
}
return myImage;
}
Note that the above code has not been compiled or tested, it should be taken as ideas not as the final code.
I had the same problem on VS 2012. As a workaround, you can remove that step, and re-record it again. That usually works.
One of the biggest problem while analyzing the Coded UI test failures is that the error stack trace indicates the line of code which might be completely unrelated to the actual cause of failure.
I would suggest you to enable HTML logging in your tests - this will display step by step details of how Coded UI tried to execute the tests - with screenshots of your application. It will also highlight the control in red which Coded UI is trying to search/operate upon.This is very beneficial in troubleshooting the actual cause of test failures.
To enable tracing you can just add the below code to your app.config file --
i am trying to use the reminder api but with no luck. The code that i use to create the reminder is located below. The thing that happens is that the reminder is not triggered until i add another reminder, att this point the old reminder goes of immediately. I guess this code does not say much as it is almost copy pasted from Microsoft's tutorial on reminders. however i do not know where the problem could be otherwise (i will post other code snippets if you have suggestions where the problem may lie)
Reminder notification = new Reminder(""+uniqueId);
notification.Title = "Title";
notification.Content = "Content";
notification.BeginTime = DateTime.Now.AddSeconds(10);
notification.RecurrenceType = RecurrenceInterval.None;
notification.NavigationUri = new Uri("/MyPage.xaml?id=" + uniqueId, UriKind.Relative);
// Register the reminder with the system.
ScheduledActionService.Add(notification);
Ok there was nothing wrong with the code. The emulators system time was set to automatic but was somehow going 20 min wrong which led to strange behaviour. After setting time manually it works as expected.