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

Add interfaces for extension authoring #232

Merged
merged 54 commits into from
Nov 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
dbcc090
initial work to enable extensions
spyoungtech Aug 22, 2023
06a38f8
fix typing import for python<3.10
spyoungtech Aug 23, 2023
47c3b64
prevent merging duplicate methods
spyoungtech Aug 23, 2023
8e38afa
cleanup
spyoungtech Aug 23, 2023
71cb07b
new message identification
spyoungtech Aug 25, 2023
ae954ef
use Critical on daemon thread
spyoungtech Aug 25, 2023
52c1877
extension documentation
spyoungtech Aug 25, 2023
8327cb0
notes
spyoungtech Aug 25, 2023
be14d1c
update tests
spyoungtech Aug 25, 2023
e3b66b1
prepare 1.4.0rc1
spyoungtech Aug 25, 2023
92c0c77
add stacklevel to warnings
spyoungtech Aug 25, 2023
09bc676
extension registry cleanup
spyoungtech Aug 30, 2023
3eba8b8
better error messages
spyoungtech Aug 30, 2023
aa6afec
fix extension tests
spyoungtech Aug 30, 2023
b532594
[WIP] initial v2 work
spyoungtech Sep 18, 2023
2d7db7a
double timeout for double the tests
spyoungtech Sep 18, 2023
1a5f2f3
upgrade binary requirement
spyoungtech Sep 18, 2023
dfed662
fix v1 bug in edge case in listing window controls
spyoungtech Sep 19, 2023
bc672e9
v2 - fix uses of ErrorLevel from v1
spyoungtech Sep 19, 2023
5bc8d17
set constant script for v2
spyoungtech Sep 19, 2023
dcc1e36
Add #Requires directive to daemon scripts
spyoungtech Sep 19, 2023
2a4bdd1
fix error message
spyoungtech Sep 19, 2023
71a0362
fix error message
spyoungtech Sep 19, 2023
5b0ccaf
Add stack to error message in v2
spyoungtech Sep 19, 2023
f6c42f3
misc fixes from warnings
spyoungtech Sep 19, 2023
a45e10d
fix controlsend arg order, fix script tests for not found window
spyoungtech Sep 19, 2023
41d4e2f
v2 window functionality
spyoungtech Sep 19, 2023
5def14e
v2 hotkeys
spyoungtech Sep 19, 2023
19500a9
remove debug print
spyoungtech Sep 19, 2023
9170f9e
fix base64 encoding ; versioned extensions
spyoungtech Sep 20, 2023
39669b7
fix base64 decoding for hotkey scripts
spyoungtech Sep 20, 2023
2054def
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 20, 2023
c6741d8
add project urls
spyoungtech Sep 20, 2023
6c5d33e
add AutoHotkey version autodetection
spyoungtech Sep 20, 2023
dce2eaf
support v2 default install location
spyoungtech Sep 20, 2023
fe0a755
document v2 support
spyoungtech Sep 20, 2023
7153972
set binary extra to 2023.9.0
spyoungtech Sep 20, 2023
2d70afb
preload crypt32
spyoungtech Sep 21, 2023
becba02
fix ControlSend in v2
spyoungtech Sep 21, 2023
f442c56
move version resolution into the engine
spyoungtech Sep 21, 2023
ad0f221
use variadic calls
spyoungtech Sep 21, 2023
32e9e9f
extension documentation and tests
spyoungtech Sep 21, 2023
5e4a5bc
more extension documentation
spyoungtech Sep 24, 2023
c5898ab
more extension documentation
spyoungtech Sep 24, 2023
67d2432
extension compatibility checks
spyoungtech Sep 24, 2023
c833587
fix python3.8 compatibility in tests
spyoungtech Sep 24, 2023
d634432
1.4.0rc2 :package:
spyoungtech Sep 24, 2023
1fcce26
fix bug in win_get_position
spyoungtech Sep 28, 2023
f63d062
initial generic version typing
spyoungtech Sep 29, 2023
89b3a86
Merge pull request #239 from spyoungtech/v2
spyoungtech Nov 11, 2023
f7fbbe7
[pre-commit.ci] pre-commit autoupdate
pre-commit-ci[bot] Nov 13, 2023
360ccbf
Merge pull request #238 from spyoungtech/pre-commit-ci-update-config
spyoungtech Nov 22, 2023
5e35f63
update actions
spyoungtech Nov 23, 2023
ea22dcc
coveralls parallel
spyoungtech Nov 23, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
- name: build
shell: bash
run: |
python -m pip install --upgrade wheel setuptools build unasync tokenize-rt
python -m pip install --upgrade wheel setuptools build
python -m build
- name: Release PyPI
shell: bash
Expand Down
16 changes: 14 additions & 2 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,28 @@ jobs:
python -m pip install -r requirements-dev.txt
python -m pip install .
python -m pip install tox
python -m pip install ahk-binary
python -m pip install "ahk-binary==2023.9.0"
- name: Test with coverage/pytest
timeout-minutes: 5
timeout-minutes: 10
env:
PYTHONUNBUFFERED: "1"
run: |
tox -e py
- name: Coveralls
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
COVERALLS_PARALLEL: "true"
COVERALLS_SERVICE_JOB_ID: ${{ github.run_id }}
run: |
pip install --upgrade coveralls
coveralls --service=github
finish:
runs-on: ubuntu-latest
needs: build
steps:
- name: finish coveralls
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
pip install --upgrade coveralls
coveralls --service=github --finish
8 changes: 4 additions & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ repos:
files: ^(ahk/daemon\.ahk|ahk/_constants\.py)

- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
rev: v4.5.0
hooks:
- id: mixed-line-ending
args: ["-f", "lf"]
Expand All @@ -31,7 +31,7 @@ repos:
- id: trailing-whitespace
- id: double-quote-string-fixer
- repo: https://github.com/psf/black
rev: '23.9.1'
rev: '23.11.0'
hooks:
- id: black
args:
Expand All @@ -40,12 +40,12 @@ repos:
- "120"
exclude: ^(ahk/_sync/.*\.py)
- repo: https://github.com/asottile/reorder-python-imports
rev: v3.10.0
rev: v3.12.0
hooks:
- id: reorder-python-imports

- repo: https://github.com/pre-commit/mirrors-mypy
rev: 'v1.5.1'
rev: 'v1.7.0'
hooks:
- id: mypy
args:
Expand Down
12 changes: 12 additions & 0 deletions _set_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@
with open('ahk/templates/hotkeys.ahk') as hotkeyfile:
hotkey_script = hotkeyfile.read()

with open('ahk/templates/daemon-v2.ahk') as fv2:
daemon_script_v2 = fv2.read()

with open('ahk/templates/hotkeys-v2.ahk') as hotkeyfilev2:
hotkey_script_v2 = hotkeyfilev2.read()

GIT_EXECUTABLE = shutil.which('git')

if not GIT_EXECUTABLE:
Expand All @@ -22,6 +28,12 @@

HOTKEYS_SCRIPT_TEMPLATE = r"""{hotkey_script}
"""

DAEMON_SCRIPT_V2_TEMPLATE = r"""{daemon_script_v2}
"""

HOTKEYS_SCRIPT_V2_TEMPLATE = r"""{hotkey_script_v2}
"""
'''

with open('ahk/_constants.py', encoding='utf-8') as f:
Expand Down
2 changes: 1 addition & 1 deletion ahk/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
'MsgBoxModality',
]

_global_instance: Optional[AHK] = None
_global_instance: Optional[AHK[None]] = None


def __getattr__(name: str) -> Any:
Expand Down
247 changes: 207 additions & 40 deletions ahk/_async/engine.py

Large diffs are not rendered by default.

325 changes: 191 additions & 134 deletions ahk/_async/transport.py

Large diffs are not rendered by default.

34 changes: 21 additions & 13 deletions ahk/_async/window.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from typing import Sequence
from typing import Tuple
from typing import TYPE_CHECKING
from typing import TypeVar
from typing import Union

from ahk.message import Position
Expand Down Expand Up @@ -45,16 +46,18 @@ class WindowNotFoundException(Exception):
'Use of the {0} property setter is not supported in the async API. Use the set_{0} instead.'
)

T_EngineVersion = TypeVar('T_EngineVersion', bound=Optional[Literal['v1', 'v2']])


class AsyncWindow:
def __init__(self, engine: AsyncAHK, ahk_id: str):
self._engine: AsyncAHK = engine
def __init__(self, engine: AsyncAHK[T_EngineVersion], ahk_id: str):
self._engine: AsyncAHK[T_EngineVersion] = engine
if not ahk_id:
raise ValueError(f'Invalid ahk_id: {ahk_id!r}')
self._ahk_id: str = ahk_id

def __repr__(self) -> str:
return f'<{self.__class__.__qualname__} ahk_id={self._ahk_id}>'
return f'<{self.__class__.__qualname__} ahk_id={self._ahk_id!r}>'

def __eq__(self, other: object) -> bool:
if not isinstance(other, AsyncWindow):
Expand Down Expand Up @@ -302,17 +305,20 @@ def always_on_top(self, toggle: Literal['On', 'Off', 'Toggle', 1, -1, 0]) -> Any

# fmt: off
@overload
async def send(self, keys: str) -> None: ...
async def send(self, keys: str, control: str = '') -> None: ...
@overload
async def send(self, keys: str, *, blocking: Literal[False]) -> AsyncFutureResult[None]: ...
async def send(self, keys: str, control: str = '', *, blocking: Literal[False]) -> AsyncFutureResult[None]: ...
@overload
async def send(self, keys: str, *, blocking: Literal[True]) -> None: ...
async def send(self, keys: str, control: str = '', *, blocking: Literal[True]) -> None: ...
@overload
async def send(self, keys: str, *, blocking: bool = True) -> Union[None, AsyncFutureResult[None]]: ...
async def send(self, keys: str, control: str = '', *, blocking: bool = True) -> Union[None, AsyncFutureResult[None]]: ...
# fmt: on
async def send(self, keys: str, *, blocking: bool = True) -> Union[None, AsyncFutureResult[None]]:
async def send(
self, keys: str, control: str = '', *, blocking: bool = True
) -> Union[None, AsyncFutureResult[None]]:
return await self._engine.control_send(
keys=keys,
control=control,
title=f'ahk_id {self._ahk_id}',
blocking=blocking,
detect_hidden_windows=True,
Expand Down Expand Up @@ -378,10 +384,12 @@ async def get_position(self, *, blocking: Literal[False]) -> AsyncFutureResult[O
@overload
async def get_position(self, *, blocking: Literal[True]) -> Position: ...
@overload
async def get_position(self, *, blocking: bool = True) -> Union[Position, AsyncFutureResult[Optional[Position]]]: ...
async def get_position(self, *, blocking: bool = True) -> Union[Position, AsyncFutureResult[Optional[Position]], AsyncFutureResult[Position]]: ...
# fmt: on
async def get_position(self, *, blocking: bool = True) -> Union[Position, AsyncFutureResult[Optional[Position]]]:
resp = await self._engine.win_get_position(
async def get_position(
self, *, blocking: bool = True
) -> Union[Position, AsyncFutureResult[Optional[Position]], AsyncFutureResult[Position]]:
resp = await self._engine.win_get_position( # type: ignore[misc] # this appears to be a mypy bug
title=f'ahk_id {self._ahk_id}',
blocking=blocking,
detect_hidden_windows=True,
Expand Down Expand Up @@ -649,11 +657,11 @@ async def move(
)

@classmethod
async def from_pid(cls, engine: AsyncAHK, pid: int) -> Optional[AsyncWindow]:
async def from_pid(cls, engine: AsyncAHK[Any], pid: int) -> Optional[AsyncWindow]:
return await engine.win_get(title=f'ahk_pid {pid}')

@classmethod
async def from_mouse_position(cls, engine: AsyncAHK) -> Optional[AsyncWindow]:
async def from_mouse_position(cls, engine: AsyncAHK[Any]) -> Optional[AsyncWindow]:
return await engine.win_get_from_mouse_position()


Expand Down
Loading
Loading