ahk icon indicating copy to clipboard operation
ahk copied to clipboard

AHKExecutionException is raised with ahk.active_window

Open michaelmesser opened this issue 10 months ago • 3 comments

describe your issue

ahk.active_window

file.python-ahk-3w1o_2fn.ahk (534) : [WinGetID] output := WinGetID(title, text, extitle, extext)
file.python-ahk-3w1o_2fn.ahk (534) : [AHKWinGetID] output := WinGetID(title, text, extitle, extext)
file.pyresp := %func_name%(argsArray*)
> Auto-execute

Unsure how to consistently reproduce. The stack track is all I have.

ahk.version

2.0.11

AutoHotkey version

v2

Code to reproduce the issue


Traceback/Error message

Traceback (most recent call last):
  File "file.py", line 104, in infer_active_path
    if ahk.active_window is None:
       ^^^^^^^^^^^^^^^^^
  File "file.py", line 819, in active_window
    return self.get_active_window()
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "file.py", line 810, in get_active_window
    return self.win_get(
           ^^^^^^^^^^^^^
  File "file.py", line 1762, in win_get
    resp = self._transport.function_call('AHKWinGetID', args, blocking=blocking, engine=self)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "file.py", line 531, in function_call
    return self.send(request, engine=engine)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "file.py", line 744, in send
    return response.unpack()  # type: ignore
           ^^^^^^^^^^^^^^^^^
  File "file.py", line 216, in unpack
    raise self._exception_type(s)
ahk.exceptions.AHKExecutionException: Error occurred in WinGetID (line 534). The error message was: Target window not found.. Specifically: A
Stack:
file.python-ahk-3w1o_2fn.ahk (534) : [WinGetID] output := WinGetID(title, text, extitle, extext)
file.python-ahk-3w1o_2fn.ahk (534) : [AHKWinGetID] output := WinGetID(title, text, extitle, extext)
file.pyresp := %func_name%(argsArray*)
> Auto-execute

michaelmesser avatar Jan 30 '25 23:01 michaelmesser

Hmm. This might happen if there is no window active. Though, I think I might infer that your expectation is that, in this case, it should return None rather than raise an exception. I believe that's the behavior when using AHK v1 and what the type hints suggest should happen.

It is noted, however, in the README under Differences when using AutoHotkey v1 vs AutoHotkey v2:

Functions that find and return windows will often raise an exception rather than returning None (as in AutoHotkey v2, a TargetError is thrown in most cases where the window or control cannot be found)

But perhaps it would be better if we made some changes to smooth over the differences between V1 and V2. The question is just whether V1 should adopt the V2 behavior or the other way around. Up to this point, I've allowed them to differ in this behavior and maybe keeping it that way is OK, too.

In the case of an error being thrown, however, if that's an expected behavior, I would probably want to raise a specific exception, rather than the generalized AHKExecutionException as another possible enhancement.

spyoungtech avatar Jan 31 '25 03:01 spyoungtech

Your explanation makes sense. Would it be possible to split this into separate ahkv1 and ahkv2 packages with future dev happening in ahkv2? Having functions behave differently with v1 and v2 is extremely confusing. Ideally each package would match the corresponding ahk API.

michaelmesser avatar Jan 31 '25 17:01 michaelmesser

Hmm. I'll take it under consideration, but I probably would not split this package up.

It is worth mentioning that you can specify the version of AHK to use explicitly.

For example:

ahk = AHK(version='v1')

This is used by the typing system to try and help project the correct expectations depending on the version of AHK you use.

For example, the win_get method is type hinted to hint the appropriate return types in each version of AHK.

Consider the following code:

from ahk import AHK

ahkv1 = AHK(version='v1')
ahkv2 = AHK(version='v2')

winv1 = ahkv1.win_get(title='foo')  # v1 can return None or a Window
winv2 = ahkv2.win_get(title='bar')  # v2 will only return a Window or error out

reveal_type(winv1)
reveal_type(winv2)

Type checkers like mypy or those used by your IDE should be able to infer the correct return types in this situation.

$ mypy t.py
# ...
t.py:10: note: Revealed type is "Union[ahk._sync.window.Window, None]"
t.py:11: note: Revealed type is "ahk._sync.window.Window"

Though, I'm sure there are areas in which this needs improvement, which I'll prioritize fixing as issues are reported.

Maybe to make this easier, I could split out separate classes for each version of AHK. Though, the API for both versions is soooo close, I'd really prefer to just either smooth over the behavior differences or type hint them appropriately.

spyoungtech avatar Feb 01 '25 00:02 spyoungtech