pywinauto find an exact tray item - python

I'm trying to create an automated GUI test framework for a desktop application and I am using pywinauto for this.
My problem is that even using SWAPY and Winspector I still have problems detecting the tray area and finding my app there.
I have tried everything from the current documentation and also tried the Volume example from the web to no success.
from pywinauto import taskbar
sti = taskbar.SystemTrayIcons.WrapperObject()
print 'Clicking ', sti.Button(0).info.text
sti.Button(0).Click()
Technically the only thing i need is finding the exact position of the tray icon and executing a click on it to bring up a menu.
pywinauto has some functions related to the taskbar but i wasn't able to get them to work.
Could anybody give me any ideas on how to do this?
EDIT
I tried your idea Vasily but I am getting this error:
import pywinauto
from pywinauto import taskbar
app = pywinauto.application.Application()
app.start_('C:\Program Files (x86)\MyApp.exe')
w_handle = pywinauto.findwindows.find_windows(title=u'MyApp')[0]
window = app.window_(handle=w_handle)
texts = taskbar.SystemTrayIcons.Texts()
print texts
and the traceback:
Traceback (most recent call last):
File "C:/Users/nicolae.farcas/Desktop/pywinauto_c1.py", line 9, in <module>
texts = taskbar.SystemTrayIcons.Texts()
File "C:\Python27\lib\site-packages\pywinauto\controls\common_controls.py", line 1932, in Texts
btn_text = self.GetButton(i).text
File "C:\Python27\lib\site-packages\pywinauto\controls\common_controls.py", line 1914, in GetButton
button.idCommand)
RuntimeError: GetButtonInfo failed for button with command id 0
I'm using Windows 7 Pro x64 right now but I need this to also run on 8, 8.1 and 10 (I can drop 10 since I imagine support for it is still behind)

If you use pywinauto 0.5.1, please call taskbar.SystemTrayIcons.Texts() and then copy corresponding text to the following call:
taskbar.ClickSystemTrayIcon('button text', exact=True, double=True)
For hidden area use ClickHiddenSystemTrayIcon(...).
Also please note that popup menu belongs to your application process. So you need to connect to the application and call app.PopupMenu.MenuItem('item name').Click() or ClickInput().
If it doesn't work, please provide error output and OS version.
EDIT:
(comment about Python 32/64 bit problem)
Ideal way is running taskbar specific code in 64-bit Python and then launching 32-bit Python for separate app specific script. It's not so convenient but should work.

Related

What causes this Attribute Error encountered when implementing LangChain's OpenAI LLM wrapper?

This is my first post here. I'm building a Python window application with PyQt5 that implements interactions with the OpenAI completions endpoint. So far, any code that I've written myself has performed fine, and I was reaching the point where I wanted to start implementing long-term memory for conversational interactions. I started by just running my own chain of prompts for categorizing and writing topical subjects and summaries to text files, but I decided it best to try exploring open source options to see how the programming community is managing things. This led me to LangChain, which seems to have some popular support behind it and already implements many features that I intend.
However, I have not had even the tiniest bit of success with it yet. Even the most simple examples don't perform, regardless of what context I'm implementing it in (within a class, outside a class, in an asynchronous loop, to the console, to my text browsers within the main window, whatever) I always get the same error message.
The simplest possible example:
import os
from langchain.llms import OpenAI
from local import constants #For API key
os.environ["OPENAI_API_KEY"] = constants.OPENAI_API_KEY
davinci = OpenAI(model_name= 'text-davinci-003', verbose=True, temperature=0.6)
text = "Write me a story about a guy who is frustrated with Python."
print("Prompt: " + text)
print(davinci(text))
It capably instantiates the wrapper and prints the prompt to the console, but at any point a command is sent through the wrapper's functions to receive generated text, it encounters this AttributeError.
Here is the traceback:
Traceback (most recent call last):
File "D:\Dropbox\Pycharm Projects\workspace\main.py", line 16, in <module>
print(davinci(text))
File "D:\Dropbox\Pycharm Projects\workspace\venv\lib\site-packages\langchain\llms\base.py", line 255, in __call__
return self.generate([prompt], stop=stop).generations[0][0].text
File "D:\Dropbox\Pycharm Projects\workspace\venv\lib\site-packages\langchain\llms\base.py", line 128, in generate
raise e
File "D:\Dropbox\Pycharm Projects\workspace\venv\lib\site-packages\langchain\llms\base.py", line 125, in generate
output = self._generate(prompts, stop=stop)
File "D:\Dropbox\Pycharm Projects\workspace\venv\lib\site-packages\langchain\llms\openai.py", line 259, in _generate
response = self.completion_with_retry(prompt=_prompts, **params)
File "D:\Dropbox\Pycharm Projects\workspace\venv\lib\site-packages\langchain\llms\openai.py", line 200, in completion_with_retry
retry_decorator = self._create_retry_decorator()
File "D:\Dropbox\Pycharm Projects\workspace\venv\lib\site-packages\langchain\llms\openai.py", line 189, in _create_retry_decorator
retry_if_exception_type(openai.error.Timeout)
AttributeError: module 'openai.error' has no attribute 'Timeout'
I don't expect that there is a fault in the LangChain library, because it seems like nobody else has experienced this problem. I imagine I may have some dependency issue? Or I do notice that others using the LangChain library are doing so in a notebook development environment, and my lack of familiarity in that regard is making me overlook some fundamental expectation of the library's use?
Any advice is welcome! Thanks!
What I tried: I initially just replaced my own function for managing calls to the completion endpoint with one that issued the calls through LangChain's llm wrapper. I expected it to work as easily as my own code had, but I received that error. I then stripped everything apart layer by layer attempting to instantiate the wrapper at every scope of the program, then I attempted to make the calls in an asynchronous function through a loop that waited to completion, and no matter what, I always get that same error message.
I think it might be something about your current installed versions of Python, OpenAI, and/or LangChain. Maybe try using a newer version of Python and OpenAI. I'm new to Python and these things but hopefully I could help.

How can I fix AttributeError in Manim Hello World program?

I am attempting to write a Hello World program in Manim.
I have installed Manim and its prerequisite programs, and can run the sample code from the command prompt as intended. This sample code operates in an unusual way; the user issues a command specifying not only a .py file, but also a single class within it, and Python executes the class definition code, seemingly without instantiating the class.
Now I'm trying to write a standalone .py file that works by instantiating a class when run (I am running it in Visual Studio Community 2019), rather than requiring external commands.
I have checked many of the Similar Questions, but unfortunately, they are all about Hello World programs in general, even spanning many non-Python languages.
I found a few AttributeError: '____' object has no attribute '____' questions in search, including this helpful explanation (https://stackoverflow.com/a/8696339/2364796), but nothing that seems to apply to the code I've explicitly written.
I also checked in IRC, and it was suggested that the problem is triggered within the imported code. However, the same code functions properly when imported into the sample, so I must be working with it incorrectly.
This is the current code for my Hello World program.
from manimlib.imports import *
class GreetingScript(Scene):
def construct(self):
characters = TextMobject("Hello World!")
self.add(characters)
scene1 = Scene()
readthrough = GreetingScript(scene1)
This is the error message produced by the above code.
Media will be stored in ./media\. You can change this behavior by writing a
diff
erent directory to media_dir.txt.
Traceback (most recent call last):
File "C:\Users\Admin\Documents\Visual Studio
2019\Projects\PythonApplication1\
PythonApplication1\PythonApplication1.py", line 8, in <module>
scene1 = Scene()
File "C:\Users\Admin\PortableApps\manim-0.1.5\manimlib\scene\scene.py",
line 3
7, in __init__
self, **self.file_writer_config,
File "C:\Users\Admin\PortableApps\manim-
0.1.5\manimlib\scene\scene_file_writer
.py", line 44, in __init__
self.init_output_directories()
File "C:\Users\Admin\PortableApps\manim-
0.1.5\manimlib\scene\scene_file_writer
.py", line 49, in init_output_directories
output_directory = self.output_directory or
self.get_default_output_director
y()
File "C:\Users\Admin\PortableApps\manim-
0.1.5\manimlib\scene\scene_file_writer
.py", line 80, in get_default_output_directory
filename = os.path.basename(self.input_file_path)
AttributeError: 'SceneFileWriter' object has no attribute 'input_file_path'
Press any key to continue . . .
I would expect the output of the program to be a display of the text "Hello World!" but the actual output is AttributeError: 'SceneFileWriter' object has no attribute 'input_file_path' accompanied by the rest of the above message.
The best way to solve this problem is to remove the code that creates the scene1 object. To make this code work, it is required to implement only the source of your scene class, and you can generate the scene using:
$ python -m manim -p /path/to/source.py GreetingScript
The -p flag means to open the video after rendering the scene. I hope this can help on your issue.
from big_ol_pile_of_manim_imports import *
class makeText(Scene):
def construct(self):
#######Code#######
#Making text
first_line = TextMobject("Manim is fun")
second_line = TextMobject("and useful")
final_line = TextMobject("Hope you like it too!", color=BLUE)
color_final_line = TextMobject("Hope you like it too!")
#Coloring
color_final_line.set_color_by_gradient(BLUE,PURPLE)
#Position text
second_line.next_to(first_line, DOWN)
#Showing text
self.wait(1)
self.play(Write(first_line), Write(second_line))
self.wait(1)
self.play(FadeOut(second_line), ReplacementTransform(first_line, final_line))
self.wait(1)
self.play(Transform(final_line, color_final_line))
self.wait(2)
have you tried something?

How to debug PyQt5 appcrash on exit

I have been developing a PyQt5 software for a while now. I have managed to package my Python 3 PyQt5 software with py2exe fine in past with everything working perfectly.
However, now I have encountered an issue where the packaged exe-program will crash when user exits. More specifically I get APPCRASH with following details
Problem signature:
Problem Event Name: APPCRASH
Application Name: Sotilasmatrikkelit.exe
Application Version: 0.0.0.0
Application Timestamp: 54467a51
Fault Module Name: PyQt5.QtCore.pyd
Fault Module Version: 0.0.0.0
Fault Module Timestamp: 549be77e
Exception Code: c0000005
Exception Offset: 0010c185
OS Version: 6.1.7601.2.1.0.256.4
Locale ID: 1035
Additional Information 1: 0a9e
Additional Information 2: 0a9e372d3b4ad19135b953a78882e789
Additional Information 3: 0a9e
Additional Information 4: 0a9e372d3b4ad19135b953a78882e789
I never get this crash when running the software from Pycharm during the development. Any idea of how to debug this or what could be the cause in general?
I suspect this might have something to do with memory management (that PyQt doesn't delete all the resources properly on exit and therefore segfaults) but does anyone have any good suggestions to figure out the exact problem without better debug information? Should I try to do some kind of cleanup on exit? Atm I start the software like this:
def start():
import sys
app = QApplication(sys.argv)
fixingtool = Mainwindow(app)
fixingtool.show()
sys.exit(app.exec_())
Additional investigation seems to suggest that I get Access Violation which is caused by C++ null-pointer. Sounds scary since I don't know too much of PyQt debugging. Anyway, I found an area on my businesslogic code which if removed will remove the problem. However, this code has nothing to do with PyQt and is just regular Python code and shouldn't differ in any way. Strangest part is that if I remove certain functions from the code, problem disappears even though functions are not called during runtime meaning that just importing the file with those functions cause the problem. Below is a code sample:
import re
from books.karelians.extraction.extractors.baseExtractor import BaseExtractor
from books.karelians.extraction.extractionExceptions import *
from books.karelians.extraction.extractors.dateExtractor import DateExtractor
from shared import textUtils
from books.karelians.extractionkeys import KEYS
from interface.valuewrapper import ValueWrapper
from shared import regexUtils
from books.karelians.extraction.extractors.professionextractor import ProfessionExtractor
class SpouseExtractor(BaseExtractor):
def extract(self, text, entry):
super(SpouseExtractor, self).extract(text)
self.entry = entry
self.PATTERN = r"Puol\.?(?P<spousedata>[A-ZÄ-Öa-zä-ö\s\.,\d-]*)(?=(Lapset|poika|tytär|asuinp))"
self.NAMEPATTERN = r"(?P<name>^[\w\s\.-]*)"
self.OPTIONS = (re.UNICODE | re.IGNORECASE) #TODO: TRY IGNORE CASE?
self.REQUIRES_MATCH_POSITION = False
self.SUBSTRING_WIDTH = 100
self.hasSpouse = False
self.spouseName = ""
self.profession = {KEYS["profession"] : ValueWrapper("")}
self.initVars(text)
self._findSpouse(text)
return self._constructReturnDict()
def initVars(self,text):
pass
def _findSpouse(self, text):
try:
self.foundSpouse = regexUtils.safeSearch(self.PATTERN, text, self.OPTIONS)
self.hasSpouse = True
self._findSpouseName(self.foundSpouse.group("spousedata"))
self._setFinalMatchPosition()
except regexUtils.RegexNoneMatchException:
pass
def _findSpouseName(self, text):
try:
name = regexUtils.safeSearch(self.NAMEPATTERN, text, self.OPTIONS)
self.spouseName = name.group("name").strip()
self._findProfession(text[name.end():])
except regexUtils.RegexNoneMatchException:
self.errorLogger.logError(SpouseNameException.eType, self.currentChild)
def _findProfession(self, text):
professionExt = ProfessionExtractor(self.entry, self.errorLogger, self.xmlDocument)
professionExt.setDependencyMatchPositionToZero()
self.profession = professionExt.extract(text, self.entry)
def _setFinalMatchPosition(self):
#Dirty fix for inaccuracy in positions which would screw the Location extraction
self.matchFinalPosition = self.foundSpouse.end() + self.matchStartPosition - 4
def _constructReturnDict(self):
print(self.profession)
return {KEYS["spouse"]: ValueWrapper({ KEYS["hasSpouse"]: ValueWrapper(self.hasSpouse),KEYS["spouseName"]: ValueWrapper(self.spouseName), KEYS["spouseProfession"]: ValueWrapper(self.profession[KEYS["profession"]].value) })}
Here if I remove or comment away all functions "initVars()" program exits properly. What gives?
This isn't really a solution to a problem itself but I'm leaving this here in case someone encounters a similar issue.
Today I decided to try cx_freeze instead of py2exe figuring that maybe the problem is with py2exe since the whole issue is not happening when running the application with normal python interpreter.
Turns out I was right and problem seemed to magically disappear after I packaged the app using cx_freeze instead of py2exe. I didn't do any changes to code. Someone more knowledgeable than me about how py2exe and cx_freeze work might be able to explain the difference. My wild guess is that for some reason the exiting from the Python interpreter is not handled perfectly in py2exe case somehow messing the end garbage cleanup. I have no idea if this is py2exe's or my fault by not configuring py2exe properly.
In any case I'm happy it works now since yesterday was a really frustrating day.

Pythondialog: Unable to retrieve the version of the dialog-like backend

Minimal code example, run on OSX and Python 3:
#! /usr/bin/env python3
from dialog import Dialog
d = Dialog(dialog="dialog")
sel = d.menu("Test",
choices=[ ("FooTag", "Foo", False, "FooHelp"),
("BarTag", "Bar", True, "BarHelp")]
)
I get the error message:
Traceback (most recent call last):
File "./test.py", line 5, in <module>
d = Dialog(dialog="dialog")
File "/usr/local/lib/python3.3/site-packages/dialog.py", line 1371, in __init__
self.backend_version())
File "/usr/local/lib/python3.3/site-packages/dialog.py", line 2012, in backend_version
"{1!r}".format(self._dialog_prg, output))
dialog.UnableToRetrieveBackendVersion: Unable to retrieve the version of the dialog-like backend: unable to parse the output of '/usr/local/bin/dialog --print-version': ''
However, dialog reports correctly:
> dialog --print-version
Version: 1.1-20100428
>
Nothing changes, if I use the absolut path /usr/local/bin/dialog. I guess, it is an install problem, but I've no clue.
As you have found yourself, the problem is caused by the fact that your dialog program prints its version on stdout whereas more recent versions print it on stderr. So, the string pythondialog tries to parse as a version number is empty in such a case.
pythondialog 3.2.2rc1 (latest release at the time of this writing) detects this situation and automatically reruns dialog --stdout --print-version, making sure this time to read from dialog's stdout stream. Since this is only done once at Dialog instance creation (the backend version being cached), the impact of this workaround is minimal.
It is better than your solution (passing use_stdout=True to the Dialog constructor), because it allows the rest of pythondialog to use dialog's stderr stream normally: the use of --stdout is only limited to retrieving the version of dialog. On the contrary, the solution you found will pass --stdout to all dialog calls which, according to the dialog(1) manual page, may fail "depending on the platform and your environment".
Had you reported this problem on the pythondialog issue tracker or mailing list, the workaround I mentioned here would certainly have been implemented earlier...
Your example with little fixes for on my computer (i changed False to 'False'). Your issue is that version is not matched against regex. This is code from pythondialog:
mo = self._print_version_cre.match(output)
if mo:
return mo.group("version")
else:
raise UnableToRetrieveBackendVersion(
"unable to parse the output of '{0} --print-version': "
"{1!r}".format(self._dialog_prg, output))
#this is located upper
_print_version_cre = re.compile(r"^Version:[ \t]+(?P<version>.+?)[ \t]*$", re.MULTILINE)
I've tested your version with this regexp and it matched on my computer, but I guess you have other version of pythondialog. So check _print_version_cre in your dialog.py and try to much with dialog version.
I found the solution myself:
dialog in OSX reports to stdout, not stderr.
By using
d = Dialog(dialog="dialog", use_stdout=True)
I get the expected result.

Qt Clipboard operation does not work in tests on OSX

I have a widget where the mac shortcut Command+C works well interactively, and the content is correctly stored in the clipboard.
I am trying to implement the same behavior in the unittests. It works on other platforms, but not on Mac.
expected_clipboard = "whatever"
self._widget.show()
Test.processEvents()
QtTest.QTest.keyClick(self._widget, QtCore.Qt.Key_C, QtCore.Qt.ControlModifier)
Test.processEvents()
current_clipboard= QtGui.qApp.clipboard().text()
self.assertEqual(current_clipboard, expected_clipboard) # Fails.
According to the Qt documentation, ControlModifier is the proper corresponding entity for Command on Mac. I also tried MetaModifier just out of curiosity, but it doesn't work.
The action is correctly attached with the following code
self._action = QtGui.QAction('text', self)
action.connect(self._action, QtCore.SIGNAL('triggered()'), self.copyAction)
self._action.setShortcut(QtGui.QKeySequence.Copy)
self.addAction(self._action)
Qt 4.8 latest, osx 10.8.
Ok, the problem is that the window must be visible, raised and activated, otherwise OSX does not deliver events. Just call widget.raise_() and widget.activateWindow()

Categories