allwright 0.2.0__tar.gz → 0.2.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. {allwright-0.2.0 → allwright-0.2.2}/PKG-INFO +1 -1
  2. {allwright-0.2.0 → allwright-0.2.2}/allwright/__init__.py +4 -0
  3. {allwright-0.2.0 → allwright-0.2.2}/allwright/_bootstrap.py +1 -1
  4. {allwright-0.2.0 → allwright-0.2.2}/allwright/_desktop.py +110 -4
  5. {allwright-0.2.0 → allwright-0.2.2}/allwright/_hooks.py +3 -0
  6. {allwright-0.2.0 → allwright-0.2.2}/allwright/client.py +2 -0
  7. {allwright-0.2.0 → allwright-0.2.2}/allwright/proto/core/v1/context.proto +7 -0
  8. {allwright-0.2.0 → allwright-0.2.2}/allwright/proto/surfaces/desktop/v1/desktop.proto +23 -0
  9. {allwright-0.2.0 → allwright-0.2.2}/allwright.egg-info/PKG-INFO +1 -1
  10. {allwright-0.2.0 → allwright-0.2.2}/pyproject.toml +1 -1
  11. {allwright-0.2.0 → allwright-0.2.2}/README.md +0 -0
  12. {allwright-0.2.0 → allwright-0.2.2}/allwright/_browser.py +0 -0
  13. {allwright-0.2.0 → allwright-0.2.2}/allwright/_config.py +0 -0
  14. {allwright-0.2.0 → allwright-0.2.2}/allwright/_locator.py +0 -0
  15. {allwright-0.2.0 → allwright-0.2.2}/allwright/_mobile.py +0 -0
  16. {allwright-0.2.0 → allwright-0.2.2}/allwright/_mobile_selectors.py +0 -0
  17. {allwright-0.2.0 → allwright-0.2.2}/allwright/_page.py +0 -0
  18. {allwright-0.2.0 → allwright-0.2.2}/allwright/_proto.py +0 -0
  19. {allwright-0.2.0 → allwright-0.2.2}/allwright/_runtime.py +0 -0
  20. {allwright-0.2.0 → allwright-0.2.2}/allwright/_selectors.py +0 -0
  21. {allwright-0.2.0 → allwright-0.2.2}/allwright/_transport.py +0 -0
  22. {allwright-0.2.0 → allwright-0.2.2}/allwright/_types.py +0 -0
  23. {allwright-0.2.0 → allwright-0.2.2}/allwright/_web_locators.py +0 -0
  24. {allwright-0.2.0 → allwright-0.2.2}/allwright/proto/core/v1/common.proto +0 -0
  25. {allwright-0.2.0 → allwright-0.2.2}/allwright/proto/core/v1/surface.proto +0 -0
  26. {allwright-0.2.0 → allwright-0.2.2}/allwright/proto/engine/v1/engine.proto +0 -0
  27. {allwright-0.2.0 → allwright-0.2.2}/allwright/proto/surfaces/mobile/v1/mobile.proto +0 -0
  28. {allwright-0.2.0 → allwright-0.2.2}/allwright/proto/surfaces/web/v1/web.proto +0 -0
  29. {allwright-0.2.0 → allwright-0.2.2}/allwright.egg-info/SOURCES.txt +0 -0
  30. {allwright-0.2.0 → allwright-0.2.2}/allwright.egg-info/dependency_links.txt +0 -0
  31. {allwright-0.2.0 → allwright-0.2.2}/allwright.egg-info/requires.txt +0 -0
  32. {allwright-0.2.0 → allwright-0.2.2}/allwright.egg-info/top_level.txt +0 -0
  33. {allwright-0.2.0 → allwright-0.2.2}/setup.cfg +0 -0
  34. {allwright-0.2.0 → allwright-0.2.2}/tests/test_accessibility_snapshot.py +0 -0
  35. {allwright-0.2.0 → allwright-0.2.2}/tests/test_capture.py +0 -0
  36. {allwright-0.2.0 → allwright-0.2.2}/tests/test_dialogs.py +0 -0
  37. {allwright-0.2.0 → allwright-0.2.2}/tests/test_hooks.py +0 -0
  38. {allwright-0.2.0 → allwright-0.2.2}/tests/test_pointer_actions.py +0 -0
  39. {allwright-0.2.0 → allwright-0.2.2}/tests/test_web_locators.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: allwright
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: High-level Python client for the allwright engine
5
5
  Requires-Python: >=3.10
6
6
  Description-Content-Type: text/markdown
@@ -11,6 +11,8 @@ from .client import (
11
11
  AndroidDevice,
12
12
  NativeApp,
13
13
  AndroidApp,
14
+ DesktopApp,
15
+ DesktopWindow,
14
16
  DesktopMacConnectOptions,
15
17
  DesktopMacLaunchOptions,
16
18
  MacApp,
@@ -81,6 +83,8 @@ __all__ = [
81
83
  "AndroidDevice",
82
84
  "NativeApp",
83
85
  "AndroidApp",
86
+ "DesktopApp",
87
+ "DesktopWindow",
84
88
  "DesktopMacConnectOptions",
85
89
  "DesktopMacLaunchOptions",
86
90
  "MacApp",
@@ -25,7 +25,7 @@ ALLWRIGHT_HOME_ENV_VAR = "ALLWRIGHT_HOME"
25
25
  ALLWRIGHT_REPOSITORY_ENV_VAR = "ALLWRIGHT_REPOSITORY"
26
26
  ALLWRIGHT_VERSION_ENV_VAR = "ALLWRIGHT_VERSION"
27
27
  DEFAULT_RELEASE_REPOSITORY = "allwright-dev/allwright"
28
- DEFAULT_RELEASE_VERSION = "0.2.0"
28
+ DEFAULT_RELEASE_VERSION = "0.2.2"
29
29
 
30
30
  _bootstrap_lock = threading.Lock()
31
31
  _managed_server: subprocess.Popen[bytes] | None = None
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  import threading
4
4
 
5
+ from ._hooks import Hook, HookType
5
6
  from ._mobile import NativeApp, NativeLocator
6
7
  from ._proto import engine_pb2
7
8
  from ._transport import RuntimeClient, StreamHandle
@@ -26,12 +27,117 @@ class DesktopMacLaunchOptions:
26
27
  self.timeout_ms = timeout_ms
27
28
 
28
29
 
29
- MacApp = NativeApp
30
30
  MacLocator = NativeLocator
31
- WindowsApp = NativeApp
32
31
  WindowsLocator = NativeLocator
33
32
 
34
33
 
34
+ class DesktopWindow(NativeApp):
35
+ def __init__(self, runtime: RuntimeClient, surface_session_id: str, session_id: str,
36
+ window_id: str, title: str, is_main: bool) -> None:
37
+ super().__init__(runtime, surface_session_id, session_id)
38
+ self.window_id, self.title, self.is_main = window_id, title, is_main
39
+
40
+ def close(self) -> None:
41
+ with self._lock:
42
+ handle = self._ensure_handle()
43
+ self._ensure_open()
44
+ handle.send(engine_pb2.ContextSessionCommand(
45
+ surface_session_id=self._surface_session_id,
46
+ context_session_id=self._session_id,
47
+ close_desktop_window=engine_pb2.CloseDesktopWindowCommand(),
48
+ ))
49
+ while True:
50
+ event = handle.recv("close desktop window")
51
+ kind = event.WhichOneof("event")
52
+ if kind == "desktop_window_closed" and event.desktop_window_closed.window_id == self.window_id:
53
+ self._closed = True
54
+ return
55
+ if kind == "error":
56
+ raise AllwrightError(event.error.message)
57
+
58
+
59
+ class DesktopApp(NativeApp):
60
+ def windows(self) -> list[DesktopWindow]:
61
+ with self._lock:
62
+ handle = self._ensure_handle()
63
+ self._ensure_open()
64
+ handle.send(engine_pb2.ContextSessionCommand(
65
+ surface_session_id=self._surface_session_id,
66
+ context_session_id=self._session_id,
67
+ list_desktop_windows=engine_pb2.ListDesktopWindowsCommand(),
68
+ ))
69
+ while True:
70
+ event = handle.recv("list desktop windows")
71
+ kind = event.WhichOneof("event")
72
+ if kind == "desktop_windows_resolved":
73
+ return [self._window(result) for result in event.desktop_windows_resolved.windows]
74
+ if kind == "error":
75
+ raise AllwrightError(event.error.message)
76
+
77
+ def main_window(self) -> DesktopWindow:
78
+ for window in self.windows():
79
+ if window.is_main:
80
+ return window
81
+ raise AllwrightError("desktop application does not currently expose a main window")
82
+
83
+ def register_hook(self, hook_type: HookType):
84
+ if hook_type.name != "window":
85
+ return super().register_hook(hook_type)
86
+ with self._lock:
87
+ handle = self._ensure_handle()
88
+ self._ensure_open()
89
+ handle.send(engine_pb2.ContextSessionCommand(
90
+ surface_session_id=self._surface_session_id,
91
+ context_session_id=self._session_id,
92
+ register_hook=engine_pb2.RegisterHookCommand(
93
+ desktop_window=engine_pb2.RegisterDesktopWindowHook()
94
+ ),
95
+ ))
96
+ while True:
97
+ event = handle.recv("register desktop window hook")
98
+ kind = event.WhichOneof("event")
99
+ if kind == "hook_registered":
100
+ return Hook(self, event.hook_registered.hook_id, hook_type)
101
+ if kind == "error":
102
+ raise AllwrightError(event.error.message)
103
+
104
+ def _wait_for_hook(self, hook_id, hook_type, options):
105
+ if hook_type.name != "window":
106
+ return super()._wait_for_hook(hook_id, hook_type, options)
107
+ from ._runtime import retry_options
108
+
109
+ with self._lock:
110
+ handle = self._ensure_handle()
111
+ self._ensure_open()
112
+ handle.send(engine_pb2.ContextSessionCommand(
113
+ surface_session_id=self._surface_session_id,
114
+ context_session_id=self._session_id,
115
+ wait_for_hook=engine_pb2.WaitForHookCommand(
116
+ hook_id=hook_id,
117
+ retry_options=retry_options(getattr(options, "timeout_ms", None)),
118
+ ),
119
+ ))
120
+ while True:
121
+ event = handle.recv("wait for desktop window hook")
122
+ kind = event.WhichOneof("event")
123
+ if kind == "hook_completed" and event.hook_completed.hook_id == hook_id:
124
+ if event.hook_completed.WhichOneof("result") != "desktop_window":
125
+ raise AllwrightError("desktop window hook returned an invalid result")
126
+ return self._window(event.hook_completed.desktop_window.window)
127
+ if kind == "error":
128
+ raise AllwrightError(event.error.message)
129
+
130
+ def _window(self, result) -> DesktopWindow:
131
+ if not result.context_session_id or not result.window_id:
132
+ raise AllwrightError("desktop window result is missing its context or window id")
133
+ return DesktopWindow(self._runtime, self._surface_session_id, result.context_session_id,
134
+ result.window_id, result.title, result.is_main)
135
+
136
+
137
+ MacApp = DesktopApp
138
+ WindowsApp = DesktopApp
139
+
140
+
35
141
  class MacDesktop:
36
142
  def __init__(
37
143
  self,
@@ -47,7 +153,7 @@ class MacDesktop:
47
153
  self._closed = False
48
154
  self._session_id = session_id
49
155
  self._surface_session_id = surface_session_id
50
- self._app = NativeApp(runtime, surface_session_id, initial_app_session_id)
156
+ self._app = DesktopApp(runtime, surface_session_id, initial_app_session_id)
51
157
 
52
158
  @property
53
159
  def session_id(self) -> str:
@@ -73,7 +179,7 @@ class MacDesktop:
73
179
  event = self._stream.recv("receive macOS app launch event")
74
180
  match event.WhichOneof("event"):
75
181
  case "desktop_app_launched":
76
- self._app = NativeApp(
182
+ self._app = DesktopApp(
77
183
  self._runtime,
78
184
  self._surface_session_id,
79
185
  event.desktop_app_launched.app_session_id,
@@ -4,6 +4,7 @@ from dataclasses import dataclass
4
4
  from typing import TYPE_CHECKING, Generic, Iterable, TypeVar
5
5
 
6
6
  if TYPE_CHECKING:
7
+ from ._desktop import DesktopWindow
7
8
  from ._page import Page
8
9
  from ._types import CommandOptions
9
10
 
@@ -80,12 +81,14 @@ class _Hooks:
80
81
  new_page: HookType[Page]
81
82
  file_chooser: HookType[FileChooser]
82
83
  download: HookType[Download]
84
+ window: HookType[DesktopWindow]
83
85
 
84
86
  def __init__(self) -> None:
85
87
  self.dialog = HookType("dialog")
86
88
  self.new_page = HookType("new_page")
87
89
  self.file_chooser = HookType("file_chooser")
88
90
  self.download = HookType("download")
91
+ self.window = HookType("window")
89
92
 
90
93
 
91
94
  hooks = _Hooks()
@@ -22,6 +22,8 @@ from ._mobile import (
22
22
  mobile,
23
23
  )
24
24
  from ._desktop import (
25
+ DesktopApp,
26
+ DesktopWindow,
25
27
  DesktopMacConnectOptions,
26
28
  DesktopMacLaunchOptions,
27
29
  MacApp,
@@ -6,6 +6,7 @@ option java_package = "dev.allwright.engine.v1";
6
6
  option java_multiple_files = true;
7
7
 
8
8
  import "core/v1/common.proto";
9
+ import "surfaces/desktop/v1/desktop.proto";
9
10
  import "surfaces/mobile/v1/mobile.proto";
10
11
  import "surfaces/web/v1/web.proto";
11
12
 
@@ -40,6 +41,8 @@ message ContextSessionCommand {
40
41
  ResolveFrameCommand resolve_frame = 26;
41
42
  CaptureCommand capture = 27;
42
43
  HandleDialogCommand handle_dialog = 28;
44
+ ListDesktopWindowsCommand list_desktop_windows = 29;
45
+ CloseDesktopWindowCommand close_desktop_window = 30;
43
46
  }
44
47
  }
45
48
 
@@ -82,6 +85,8 @@ message ContextSessionEvent {
82
85
  FrameResolvedEvent frame_resolved = 28;
83
86
  CaptureResolvedEvent capture_resolved = 29;
84
87
  DialogHandledEvent dialog_handled = 30;
88
+ DesktopWindowsResolvedEvent desktop_windows_resolved = 31;
89
+ DesktopWindowClosedEvent desktop_window_closed = 32;
85
90
  }
86
91
  }
87
92
 
@@ -109,6 +114,7 @@ message RegisterHookCommand {
109
114
  RegisterMobileFileChooserHook mobile_file_chooser = 4;
110
115
  RegisterMobileDownloadHook mobile_download = 5;
111
116
  RegisterDialogHook dialog = 6;
117
+ RegisterDesktopWindowHook desktop_window = 7;
112
118
  }
113
119
  }
114
120
 
@@ -131,6 +137,7 @@ message HookCompletedEvent {
131
137
  MobileFileChooserHookResult mobile_file_chooser = 5;
132
138
  MobileDownloadHookResult mobile_download = 6;
133
139
  DialogHookResult dialog = 7;
140
+ DesktopWindowHookResult desktop_window = 8;
134
141
  }
135
142
  }
136
143
 
@@ -39,3 +39,26 @@ message DesktopAppLaunchedEvent {
39
39
  string app_id = 2;
40
40
  string note = 3;
41
41
  }
42
+
43
+ message ListDesktopWindowsCommand {}
44
+ message CloseDesktopWindowCommand {}
45
+ message RegisterDesktopWindowHook {}
46
+
47
+ message DesktopWindowInfo {
48
+ string context_session_id = 1;
49
+ string window_id = 2;
50
+ string title = 3;
51
+ bool is_main = 4;
52
+ }
53
+
54
+ message DesktopWindowsResolvedEvent {
55
+ repeated DesktopWindowInfo windows = 1;
56
+ }
57
+
58
+ message DesktopWindowClosedEvent {
59
+ string window_id = 1;
60
+ }
61
+
62
+ message DesktopWindowHookResult {
63
+ DesktopWindowInfo window = 1;
64
+ }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: allwright
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: High-level Python client for the allwright engine
5
5
  Requires-Python: >=3.10
6
6
  Description-Content-Type: text/markdown
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "allwright"
3
- version = "0.2.0"
3
+ version = "0.2.2"
4
4
  description = "High-level Python client for the allwright engine"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes