Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Regression in atspi branch causes call to Application.windows() to raise RuntimeError #1338

Open
logkirkland opened this issue Sep 20, 2023 · 6 comments · May be fixed by #1342
Open

Regression in atspi branch causes call to Application.windows() to raise RuntimeError #1338

logkirkland opened this issue Sep 20, 2023 · 6 comments · May be fixed by #1342
Labels

Comments

@logkirkland
Copy link

There seems to be a regression in the atspi branch which causes a call to Application.windows() to raise a RuntimeError. The example code works as expected on 0.6.8.

Expected Behavior

[<hwndwrapper.DialogWrapper - 'Untitled - Notepad', Notepad, 1050764>]

Actual Behavior

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\[redacted]\Downloads\venv\lib\site-packages\pywinauto\base_application.py", line 959, in windows
    windows = findwindows.find_elements(**kwargs)
  File "C:\Users\[redacted]\Downloads\venv\lib\site-packages\pywinauto\findwindows.py", line 155, in find_elements
    for key, value in kwargs.items():
RuntimeError: dictionary keys changed during iteration

Steps to Reproduce the Problem

Run the example code in the specified environment.

Short Example of Code to Demonstrate the Problem

import pywinauto
app = pywinauto.Application(backend="win32").start(cmd_line=r"C:\WINDOWS\system32\notepad.exe")
print(app.windows(title_re=".*Notepad.*"))

Specifications

  • Pywinauto version: atspi@bf7f789

  • Python version and bitness: Python 3.8.2, 32-bit

  • Platform and OS:

    Windows info:
    64-bit version
    Edition: Windows 10 Enterprise
    Version: 22H2
    OS build: 19045.3324
    Experience: Windows Feature Experience Pack 1000.19041.1000.0

@junkmd
Copy link
Contributor

junkmd commented Sep 21, 2023

This is similar to #1304.

I don't much use Application or Desktop, so I didn't notice that this could be a regression.
Good point.

Can you create a test in .../pywinauto/unittests/test_application.py that passes in 0.6.8 and fails in atspi@bf7f789?

If possible, it would be desirable to use a test GUI from .../apps instead of notepad.exe, as the names may change depending on the language of the execution environment.

@junkmd
Copy link
Contributor

junkmd commented Sep 22, 2023

I plan to investigate this next week during weekdays and make any necessary changes to the production code or add test code if needed.

However, those who frequently use Application or Desktop might come up with more suitable use cases for testing.

Any opinions would be appreciated.

@junkmd
Copy link
Contributor

junkmd commented Sep 25, 2023

This is not a situation where Application.window "became uncallable" or "lost the ability to take any keyword arguments". Rather, it should be viewed as a situation where "the acceptable keyword arguments have changed".

In #848, significant changes were made where title_re and title were replaced with name_re and name, and tests were also updated in 22ba132.

  • For example...
    • 0.6.8
      def test_window(self):
      """Test that window_() works correctly"""
      app = Application()
      self.assertRaises(AppNotConnected, app.window_, **{'title' : 'not connected'})
      app.start(_notepad_exe())
      self.assertRaises(ValueError, app.windows_, **{'backend' : 'uia'})
      title = app.window_(title = "Untitled - Notepad")
      title_re = app.window_(title_re = "Untitled[ -]+Notepad")
      classname = app.window_(class_name = "Notepad")
      classname_re = app.window_(class_name_re = "Not..ad")
      handle = app.window_(handle = title.handle)
      bestmatch = app.window_(best_match = "Untiotled Notepad")
      self.assertNotEqual(title.handle, None)
      self.assertNotEqual(title.handle, 0)
      self.assertEqual(title.handle, title_re.handle)
      self.assertEqual(title.handle, classname.handle)
      self.assertEqual(title.handle, classname_re.handle)
      self.assertEqual(title.handle, handle.handle)
      self.assertEqual(title.handle, bestmatch.handle)
      app.UntitledNotepad.menu_select("File->Exit")
    • atspi@bf7f789
      def test_window(self):
      """Test that window_() works correctly"""
      app = Application()
      self.assertRaises(AppNotConnected, app.window_, **{'title' : 'not connected'})
      app.start(_notepad_exe())
      self.assertRaises(ValueError, app.windows_, **{'backend' : 'uia'})
      title = app.window(name="Untitled - Notepad")
      title_re = app.window(name_re="Untitled[ -]+Notepad")
      classname = app.window(class_name="Notepad")
      classname_re = app.window(class_name_re="Not..ad")
      handle = app.window(handle=title.handle)
      bestmatch = app.window(best_match="Untiotled Notepad")
      self.assertNotEqual(title.handle, None)
      self.assertNotEqual(title.handle, 0)
      self.assertEqual(title.handle, title_re.handle)
      self.assertEqual(title.handle, classname.handle)
      self.assertEqual(title.handle, classname_re.handle)
      self.assertEqual(title.handle, handle.handle)
      self.assertEqual(title.handle, bestmatch.handle)
      app.UntitledNotepad.menu_select("File->Exit")

@vasily-v-ryabov
Should we consider adding a workaround for developers who were previously using title_re or title?
Edited: I think I found the possible cause of the problem.

@junkmd
Copy link
Contributor

junkmd commented Sep 25, 2023

It might be necessary to have a warning message conveying that "argument names should be updated to the new ones" as well.

@junkmd
Copy link
Contributor

junkmd commented Sep 25, 2023

I didn't notice it just by looking at Application, but while looking at the findwindows side, I think I found the possible cause of the problem.

There is an implementation in find_windows that swaps keywords based on *ElementInfo.renamed_props, but it seems to not be working correctly.

I'm considering making changes to the production code and adding tests, and if it seems to work well, I'll submit a PR.

junkmd added a commit to junkmd/pywinauto that referenced this issue Sep 25, 2023
`Application.windows` and `findwindows.find_windows` can now accept keys
specified in `*ElementInfo.renamed_props`.
@junkmd
Copy link
Contributor

junkmd commented Sep 25, 2023

I'd also like to mention that backward compatibility was restored in #1253.

junkmd added a commit to junkmd/pywinauto that referenced this issue Sep 26, 2023
`Application.window` and `findwindows.find_elements` can now accept keys
specified in `*ElementInfo.renamed_props`
@junkmd junkmd added the bug label Sep 27, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
2 participants