pyautoassist 0.1.0__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.
- pyautoassist-0.1.0/.gitignore +39 -0
- pyautoassist-0.1.0/PKG-INFO +245 -0
- pyautoassist-0.1.0/README.md +209 -0
- pyautoassist-0.1.0/examples/demo.py +545 -0
- pyautoassist-0.1.0/pyautoassist/__init__.py +464 -0
- pyautoassist-0.1.0/pyautoassist/_impl/__init__.py +0 -0
- pyautoassist-0.1.0/pyautoassist/_impl/_defaults.py +6 -0
- pyautoassist-0.1.0/pyautoassist/_impl/automagic.py +639 -0
- pyautoassist-0.1.0/pyautoassist/_impl/backend.py +208 -0
- pyautoassist-0.1.0/pyautoassist/_impl/element.py +281 -0
- pyautoassist-0.1.0/pyautoassist/_impl/fuzzy.py +75 -0
- pyautoassist-0.1.0/pyautoassist/_impl/locator.py +435 -0
- pyautoassist-0.1.0/pyautoassist/_impl/selector.py +282 -0
- pyautoassist-0.1.0/pyautoassist/_impl/types.py +113 -0
- pyautoassist-0.1.0/pyautoassist/_impl/visualize.py +394 -0
- pyautoassist-0.1.0/pyautoassist/_impl/wait.py +97 -0
- pyautoassist-0.1.0/pyautoassist/_impl/window.py +149 -0
- pyautoassist-0.1.0/pyautoassist/backends/__init__.py +0 -0
- pyautoassist-0.1.0/pyautoassist/backends/linux_backend.py +258 -0
- pyautoassist-0.1.0/pyautoassist/backends/macos_backend.py +329 -0
- pyautoassist-0.1.0/pyautoassist/backends/windows_backend.py +983 -0
- pyautoassist-0.1.0/pyautoassist/recorder/__init__.py +0 -0
- pyautoassist-0.1.0/pyautoassist/recorder/cli.py +162 -0
- pyautoassist-0.1.0/pyautoassist/recorder/event_recorder.py +459 -0
- pyautoassist-0.1.0/pyautoassist/recorder/region_selector.py +162 -0
- pyautoassist-0.1.0/pyautoassist/recorder/screen_capture.py +252 -0
- pyautoassist-0.1.0/pyautoassist/recorder/video_writer.py +123 -0
- pyautoassist-0.1.0/pyproject.toml +46 -0
- pyautoassist-0.1.0/tests/__init__.py +1 -0
- pyautoassist-0.1.0/tests/conftest.py +6 -0
- pyautoassist-0.1.0/tests/mock_backend.py +229 -0
- pyautoassist-0.1.0/tests/test_automagic.py +70 -0
- pyautoassist-0.1.0/tests/test_element.py +142 -0
- pyautoassist-0.1.0/tests/test_event_recorder.py +369 -0
- pyautoassist-0.1.0/tests/test_fuzzy.py +114 -0
- pyautoassist-0.1.0/tests/test_imports.py +144 -0
- pyautoassist-0.1.0/tests/test_locator.py +189 -0
- pyautoassist-0.1.0/tests/test_region_selector.py +72 -0
- pyautoassist-0.1.0/tests/test_screen_capture.py +198 -0
- pyautoassist-0.1.0/tests/test_selector.py +123 -0
- pyautoassist-0.1.0/tests/test_text_locator.py +405 -0
- pyautoassist-0.1.0/tests/test_video_writer.py +140 -0
- pyautoassist-0.1.0/tests/test_visualize.py +218 -0
- pyautoassist-0.1.0/tests/test_wait.py +77 -0
- pyautoassist-0.1.0/tests/test_window.py +107 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# Distribution / packaging
|
|
7
|
+
build/
|
|
8
|
+
dist/
|
|
9
|
+
*.egg-info/
|
|
10
|
+
*.egg
|
|
11
|
+
.eggs/
|
|
12
|
+
|
|
13
|
+
# Virtual environments
|
|
14
|
+
.venv/
|
|
15
|
+
venv/
|
|
16
|
+
env/
|
|
17
|
+
|
|
18
|
+
# IDE / Editor
|
|
19
|
+
.vscode/
|
|
20
|
+
.idea/
|
|
21
|
+
*.swp
|
|
22
|
+
*.swo
|
|
23
|
+
*~
|
|
24
|
+
|
|
25
|
+
# OS files
|
|
26
|
+
.DS_Store
|
|
27
|
+
Thumbs.db
|
|
28
|
+
Desktop.ini
|
|
29
|
+
|
|
30
|
+
# Testing
|
|
31
|
+
.pytest_cache/
|
|
32
|
+
.coverage
|
|
33
|
+
htmlcov/
|
|
34
|
+
|
|
35
|
+
# Environment
|
|
36
|
+
.env
|
|
37
|
+
|
|
38
|
+
# Misc
|
|
39
|
+
*.log
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: pyautoassist
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Playwright-style desktop automation with native OS accessibility backends
|
|
5
|
+
Author: pyautoassist contributors
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Keywords: accessibility,automation,desktop,playwright,pyautogui,pywinauto,uia
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
17
|
+
Classifier: Topic :: Software Development :: Testing
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Provides-Extra: dev
|
|
20
|
+
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
|
|
21
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
22
|
+
Provides-Extra: linux
|
|
23
|
+
Requires-Dist: pygobject>=3.48; extra == 'linux'
|
|
24
|
+
Provides-Extra: macos
|
|
25
|
+
Requires-Dist: pyobjc>=10.0; extra == 'macos'
|
|
26
|
+
Provides-Extra: recorder
|
|
27
|
+
Requires-Dist: mss>=9.0; extra == 'recorder'
|
|
28
|
+
Requires-Dist: opencv-python>=4.8; extra == 'recorder'
|
|
29
|
+
Requires-Dist: pillow>=10.0; extra == 'recorder'
|
|
30
|
+
Provides-Extra: visualize
|
|
31
|
+
Requires-Dist: matplotlib>=3.7; extra == 'visualize'
|
|
32
|
+
Requires-Dist: networkx>=3.0; extra == 'visualize'
|
|
33
|
+
Provides-Extra: windows
|
|
34
|
+
Requires-Dist: comtypes>=1.4; extra == 'windows'
|
|
35
|
+
Description-Content-Type: text/markdown
|
|
36
|
+
|
|
37
|
+
# pyautoassist
|
|
38
|
+
|
|
39
|
+
**Playwright-style desktop automation with native OS accessibility backends.**
|
|
40
|
+
|
|
41
|
+
pyautoassist brings the developer experience of Playwright to desktop automation.
|
|
42
|
+
No more `time.sleep()`. No more fragile coordinate-based clicking.
|
|
43
|
+
Just explicit locators, native auto-waiting, and real OS accessibility APIs.
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
import pyautoassist
|
|
47
|
+
|
|
48
|
+
app = pyautoassist.using_backend()
|
|
49
|
+
|
|
50
|
+
# XPath-style locators targeting OS accessibility properties
|
|
51
|
+
app.locator("//Button[@Name='Submit']").click()
|
|
52
|
+
app.locator("//Edit[@AutomationId='email-input']").fill("Hello World")
|
|
53
|
+
|
|
54
|
+
# CSS-style shorthand
|
|
55
|
+
app.locator("button.submit-btn").click()
|
|
56
|
+
app.locator("edit-text#main-input").fill("Hello")
|
|
57
|
+
|
|
58
|
+
# Auto-waiting: no time.sleep() needed
|
|
59
|
+
app.locator("//Button[@Name='Save']").click() # waits until clickable
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Why pyautoassist?
|
|
63
|
+
|
|
64
|
+
| Feature | pyautogui | pywinauto | pyautoassist |
|
|
65
|
+
|---------|-----------|-----------|-----------|
|
|
66
|
+
| Locator style | Coordinates/fragile selectors | Custom syntax | CSS/XPath-style |
|
|
67
|
+
| Auto-waiting | None | Basic | Full (Playwright-style) |
|
|
68
|
+
| OS backend | Screen capture | Win32 COM | Native UIA/AX/AT-SPI |
|
|
69
|
+
| Codegen recorder | No | No | Yes (`pyautoassist record`) |
|
|
70
|
+
| Cross-platform | Yes | Windows only | Windows/macOS/Linux |
|
|
71
|
+
|
|
72
|
+
## Installation
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
# Core (auto-detects platform)
|
|
76
|
+
pip install pyautoassist
|
|
77
|
+
|
|
78
|
+
# Platform-specific extras
|
|
79
|
+
pip install pyautoassist[windows] # Windows UIA
|
|
80
|
+
pip install pyautoassist[macos] # macOS Accessibility
|
|
81
|
+
pip install pyautoassist[linux] # Linux AT-SPI2
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Quick Start
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
import pyautoassist
|
|
88
|
+
|
|
89
|
+
# Create an automation session
|
|
90
|
+
app = pyautoassist.using_backend()
|
|
91
|
+
|
|
92
|
+
# Find a window
|
|
93
|
+
notepad = app.open("Notepad")
|
|
94
|
+
|
|
95
|
+
# Use locators (auto-waits for element)
|
|
96
|
+
app.locator("//Edit").fill("Hello, pyautoassist!")
|
|
97
|
+
|
|
98
|
+
# Chain locators within elements
|
|
99
|
+
notepad.locator("//MenuItem[@Name='File']").click()
|
|
100
|
+
notepad.locator("//MenuItem[@Name='Save']").click()
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Selectors
|
|
104
|
+
|
|
105
|
+
### XPath Style
|
|
106
|
+
|
|
107
|
+
Target elements by their OS accessibility properties:
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
# By control type and name
|
|
111
|
+
app.locator("//Button[@Name='Submit']")
|
|
112
|
+
app.locator("//Edit[@Name='Username']")
|
|
113
|
+
|
|
114
|
+
# By AutomationId (most reliable)
|
|
115
|
+
app.locator("//Button[@AutomationId='btn-submit']")
|
|
116
|
+
app.locator("//Edit[@AutomationId='email-input']")
|
|
117
|
+
|
|
118
|
+
# By ClassName
|
|
119
|
+
app.locator("//Pane[@ClassName='Notepad']")
|
|
120
|
+
|
|
121
|
+
# Chained: nested elements
|
|
122
|
+
app.locator("//Pane[@ClassName='Notepad']//Button[@Name='File']")
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### CSS Style
|
|
126
|
+
|
|
127
|
+
Shorthand selectors for quick access:
|
|
128
|
+
|
|
129
|
+
```python
|
|
130
|
+
# Type + ID (AutomationId)
|
|
131
|
+
app.locator("button#submit-btn")
|
|
132
|
+
|
|
133
|
+
# Type + class (ClassName)
|
|
134
|
+
app.locator("button.submit")
|
|
135
|
+
|
|
136
|
+
# Type + attribute
|
|
137
|
+
app.locator('button[name="OK"]')
|
|
138
|
+
|
|
139
|
+
# Child combinator
|
|
140
|
+
app.locator("pane > button")
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Supported Control Types
|
|
144
|
+
|
|
145
|
+
`button`, `edit`/`edit-text`/`textbox`, `pane`, `window`/`dialog`,
|
|
146
|
+
`menu`, `menuitem`, `checkbox`, `radio`/`radiobutton`,
|
|
147
|
+
`combobox`/`dropdown`, `list`, `listitem`, `tree`, `treeitem`,
|
|
148
|
+
`toolbar`, `tab`, `tabitem`, `image`, `hyperlink`, `slider`,
|
|
149
|
+
`progressbar`, `scrollbar`, `group`, `tooltip`, `statusbar`,
|
|
150
|
+
`header`, `separator`, `document`, `dataitem`, `custom`
|
|
151
|
+
|
|
152
|
+
## Auto-Waiting
|
|
153
|
+
|
|
154
|
+
Every action on a Locator automatically waits for the element to be ready:
|
|
155
|
+
|
|
156
|
+
```python
|
|
157
|
+
# Waits up to 30s for the button to exist, be visible, and be enabled
|
|
158
|
+
app.locator("//Button[@Name='Submit']").click()
|
|
159
|
+
|
|
160
|
+
# Custom timeout
|
|
161
|
+
app.locator("//Button[@Name='Submit']").with_timeout(5000).click()
|
|
162
|
+
|
|
163
|
+
# Wait for specific states
|
|
164
|
+
app.locator("//Button[@Name='Loading']").visible().click()
|
|
165
|
+
app.locator("//Edit[@Name='Email']").enabled().click()
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Element Actions
|
|
169
|
+
|
|
170
|
+
```python
|
|
171
|
+
el = app.locator("//Button[@Name='Submit']")
|
|
172
|
+
|
|
173
|
+
el.click() # Left click
|
|
174
|
+
el.double_click() # Double click
|
|
175
|
+
el.right_click() # Context menu
|
|
176
|
+
el.fill("text") # Set value (input fields)
|
|
177
|
+
el.type_text("text") # Type character by character
|
|
178
|
+
el.clear() # Clear input
|
|
179
|
+
el.select_option(label="Option 1") # Dropdown selection
|
|
180
|
+
el.focus() # Move keyboard focus
|
|
181
|
+
el.hover() # Move mouse to element
|
|
182
|
+
el.press_key("Enter") # Send key press
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Window Management
|
|
186
|
+
|
|
187
|
+
```python
|
|
188
|
+
# List all windows
|
|
189
|
+
for w in app.get_windows():
|
|
190
|
+
print(f"{w.title} (PID: {w.pid})")
|
|
191
|
+
|
|
192
|
+
# Find by title
|
|
193
|
+
notepad = app.find_window(title="Notepad")
|
|
194
|
+
notepad.focus()
|
|
195
|
+
notepad.move(100, 100)
|
|
196
|
+
notepad.resize(800, 600)
|
|
197
|
+
notepad.close()
|
|
198
|
+
|
|
199
|
+
# Find by PID
|
|
200
|
+
window = app.find_window(pid=12345)
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## Codegen Recorder
|
|
204
|
+
|
|
205
|
+
Generate automation code by clicking around:
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
# Start recording (Windows)
|
|
209
|
+
pyautoassist record
|
|
210
|
+
|
|
211
|
+
# Save to file
|
|
212
|
+
pyautoassist record --output recorded.py
|
|
213
|
+
|
|
214
|
+
# Specify backend
|
|
215
|
+
pyautoassist record --backend macos
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
The recorder hooks into OS mouse events, inspects the accessibility tree
|
|
219
|
+
at each click location, and prints pyautoassist-style code in real time.
|
|
220
|
+
|
|
221
|
+
## Architecture
|
|
222
|
+
|
|
223
|
+
```
|
|
224
|
+
pyautoassist/
|
|
225
|
+
__init__.py # Public API
|
|
226
|
+
_impl/
|
|
227
|
+
pyautoassist.py # Main entry point (pyautoassist class)
|
|
228
|
+
locator.py # Playwright-style Locator with auto-wait
|
|
229
|
+
element.py # Element wrapper with actions
|
|
230
|
+
window.py # Window management
|
|
231
|
+
selector.py # CSS/XPath-style selector engine
|
|
232
|
+
wait.py # Auto-wait polling loop
|
|
233
|
+
types.py # Data types and enums
|
|
234
|
+
backend.py # Abstract backend interface
|
|
235
|
+
backends/
|
|
236
|
+
windows_backend.py # Windows UIA (UIA3 COM API)
|
|
237
|
+
macos_backend.py # macOS AXUIElement (PyObjC)
|
|
238
|
+
linux_backend.py # Linux AT-SPI2 (GObject)
|
|
239
|
+
recorder/
|
|
240
|
+
cli.py # Codegen CLI tool
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
## License
|
|
244
|
+
|
|
245
|
+
MIT
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
# pyautoassist
|
|
2
|
+
|
|
3
|
+
**Playwright-style desktop automation with native OS accessibility backends.**
|
|
4
|
+
|
|
5
|
+
pyautoassist brings the developer experience of Playwright to desktop automation.
|
|
6
|
+
No more `time.sleep()`. No more fragile coordinate-based clicking.
|
|
7
|
+
Just explicit locators, native auto-waiting, and real OS accessibility APIs.
|
|
8
|
+
|
|
9
|
+
```python
|
|
10
|
+
import pyautoassist
|
|
11
|
+
|
|
12
|
+
app = pyautoassist.using_backend()
|
|
13
|
+
|
|
14
|
+
# XPath-style locators targeting OS accessibility properties
|
|
15
|
+
app.locator("//Button[@Name='Submit']").click()
|
|
16
|
+
app.locator("//Edit[@AutomationId='email-input']").fill("Hello World")
|
|
17
|
+
|
|
18
|
+
# CSS-style shorthand
|
|
19
|
+
app.locator("button.submit-btn").click()
|
|
20
|
+
app.locator("edit-text#main-input").fill("Hello")
|
|
21
|
+
|
|
22
|
+
# Auto-waiting: no time.sleep() needed
|
|
23
|
+
app.locator("//Button[@Name='Save']").click() # waits until clickable
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Why pyautoassist?
|
|
27
|
+
|
|
28
|
+
| Feature | pyautogui | pywinauto | pyautoassist |
|
|
29
|
+
|---------|-----------|-----------|-----------|
|
|
30
|
+
| Locator style | Coordinates/fragile selectors | Custom syntax | CSS/XPath-style |
|
|
31
|
+
| Auto-waiting | None | Basic | Full (Playwright-style) |
|
|
32
|
+
| OS backend | Screen capture | Win32 COM | Native UIA/AX/AT-SPI |
|
|
33
|
+
| Codegen recorder | No | No | Yes (`pyautoassist record`) |
|
|
34
|
+
| Cross-platform | Yes | Windows only | Windows/macOS/Linux |
|
|
35
|
+
|
|
36
|
+
## Installation
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# Core (auto-detects platform)
|
|
40
|
+
pip install pyautoassist
|
|
41
|
+
|
|
42
|
+
# Platform-specific extras
|
|
43
|
+
pip install pyautoassist[windows] # Windows UIA
|
|
44
|
+
pip install pyautoassist[macos] # macOS Accessibility
|
|
45
|
+
pip install pyautoassist[linux] # Linux AT-SPI2
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Quick Start
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
import pyautoassist
|
|
52
|
+
|
|
53
|
+
# Create an automation session
|
|
54
|
+
app = pyautoassist.using_backend()
|
|
55
|
+
|
|
56
|
+
# Find a window
|
|
57
|
+
notepad = app.open("Notepad")
|
|
58
|
+
|
|
59
|
+
# Use locators (auto-waits for element)
|
|
60
|
+
app.locator("//Edit").fill("Hello, pyautoassist!")
|
|
61
|
+
|
|
62
|
+
# Chain locators within elements
|
|
63
|
+
notepad.locator("//MenuItem[@Name='File']").click()
|
|
64
|
+
notepad.locator("//MenuItem[@Name='Save']").click()
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Selectors
|
|
68
|
+
|
|
69
|
+
### XPath Style
|
|
70
|
+
|
|
71
|
+
Target elements by their OS accessibility properties:
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
# By control type and name
|
|
75
|
+
app.locator("//Button[@Name='Submit']")
|
|
76
|
+
app.locator("//Edit[@Name='Username']")
|
|
77
|
+
|
|
78
|
+
# By AutomationId (most reliable)
|
|
79
|
+
app.locator("//Button[@AutomationId='btn-submit']")
|
|
80
|
+
app.locator("//Edit[@AutomationId='email-input']")
|
|
81
|
+
|
|
82
|
+
# By ClassName
|
|
83
|
+
app.locator("//Pane[@ClassName='Notepad']")
|
|
84
|
+
|
|
85
|
+
# Chained: nested elements
|
|
86
|
+
app.locator("//Pane[@ClassName='Notepad']//Button[@Name='File']")
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### CSS Style
|
|
90
|
+
|
|
91
|
+
Shorthand selectors for quick access:
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
# Type + ID (AutomationId)
|
|
95
|
+
app.locator("button#submit-btn")
|
|
96
|
+
|
|
97
|
+
# Type + class (ClassName)
|
|
98
|
+
app.locator("button.submit")
|
|
99
|
+
|
|
100
|
+
# Type + attribute
|
|
101
|
+
app.locator('button[name="OK"]')
|
|
102
|
+
|
|
103
|
+
# Child combinator
|
|
104
|
+
app.locator("pane > button")
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Supported Control Types
|
|
108
|
+
|
|
109
|
+
`button`, `edit`/`edit-text`/`textbox`, `pane`, `window`/`dialog`,
|
|
110
|
+
`menu`, `menuitem`, `checkbox`, `radio`/`radiobutton`,
|
|
111
|
+
`combobox`/`dropdown`, `list`, `listitem`, `tree`, `treeitem`,
|
|
112
|
+
`toolbar`, `tab`, `tabitem`, `image`, `hyperlink`, `slider`,
|
|
113
|
+
`progressbar`, `scrollbar`, `group`, `tooltip`, `statusbar`,
|
|
114
|
+
`header`, `separator`, `document`, `dataitem`, `custom`
|
|
115
|
+
|
|
116
|
+
## Auto-Waiting
|
|
117
|
+
|
|
118
|
+
Every action on a Locator automatically waits for the element to be ready:
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
# Waits up to 30s for the button to exist, be visible, and be enabled
|
|
122
|
+
app.locator("//Button[@Name='Submit']").click()
|
|
123
|
+
|
|
124
|
+
# Custom timeout
|
|
125
|
+
app.locator("//Button[@Name='Submit']").with_timeout(5000).click()
|
|
126
|
+
|
|
127
|
+
# Wait for specific states
|
|
128
|
+
app.locator("//Button[@Name='Loading']").visible().click()
|
|
129
|
+
app.locator("//Edit[@Name='Email']").enabled().click()
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Element Actions
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
el = app.locator("//Button[@Name='Submit']")
|
|
136
|
+
|
|
137
|
+
el.click() # Left click
|
|
138
|
+
el.double_click() # Double click
|
|
139
|
+
el.right_click() # Context menu
|
|
140
|
+
el.fill("text") # Set value (input fields)
|
|
141
|
+
el.type_text("text") # Type character by character
|
|
142
|
+
el.clear() # Clear input
|
|
143
|
+
el.select_option(label="Option 1") # Dropdown selection
|
|
144
|
+
el.focus() # Move keyboard focus
|
|
145
|
+
el.hover() # Move mouse to element
|
|
146
|
+
el.press_key("Enter") # Send key press
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Window Management
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
# List all windows
|
|
153
|
+
for w in app.get_windows():
|
|
154
|
+
print(f"{w.title} (PID: {w.pid})")
|
|
155
|
+
|
|
156
|
+
# Find by title
|
|
157
|
+
notepad = app.find_window(title="Notepad")
|
|
158
|
+
notepad.focus()
|
|
159
|
+
notepad.move(100, 100)
|
|
160
|
+
notepad.resize(800, 600)
|
|
161
|
+
notepad.close()
|
|
162
|
+
|
|
163
|
+
# Find by PID
|
|
164
|
+
window = app.find_window(pid=12345)
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Codegen Recorder
|
|
168
|
+
|
|
169
|
+
Generate automation code by clicking around:
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
# Start recording (Windows)
|
|
173
|
+
pyautoassist record
|
|
174
|
+
|
|
175
|
+
# Save to file
|
|
176
|
+
pyautoassist record --output recorded.py
|
|
177
|
+
|
|
178
|
+
# Specify backend
|
|
179
|
+
pyautoassist record --backend macos
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
The recorder hooks into OS mouse events, inspects the accessibility tree
|
|
183
|
+
at each click location, and prints pyautoassist-style code in real time.
|
|
184
|
+
|
|
185
|
+
## Architecture
|
|
186
|
+
|
|
187
|
+
```
|
|
188
|
+
pyautoassist/
|
|
189
|
+
__init__.py # Public API
|
|
190
|
+
_impl/
|
|
191
|
+
pyautoassist.py # Main entry point (pyautoassist class)
|
|
192
|
+
locator.py # Playwright-style Locator with auto-wait
|
|
193
|
+
element.py # Element wrapper with actions
|
|
194
|
+
window.py # Window management
|
|
195
|
+
selector.py # CSS/XPath-style selector engine
|
|
196
|
+
wait.py # Auto-wait polling loop
|
|
197
|
+
types.py # Data types and enums
|
|
198
|
+
backend.py # Abstract backend interface
|
|
199
|
+
backends/
|
|
200
|
+
windows_backend.py # Windows UIA (UIA3 COM API)
|
|
201
|
+
macos_backend.py # macOS AXUIElement (PyObjC)
|
|
202
|
+
linux_backend.py # Linux AT-SPI2 (GObject)
|
|
203
|
+
recorder/
|
|
204
|
+
cli.py # Codegen CLI tool
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## License
|
|
208
|
+
|
|
209
|
+
MIT
|