Metadata-Version: 2.5
Name: pyautoassist
Version: 0.1.1
Summary: Playwright-style desktop automation with native OS accessibility backends
Author: pyautoassist contributors
License-Expression: MIT
Keywords: accessibility,automation,desktop,playwright,pyautogui,pywinauto,uia
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Software Development :: Testing
Requires-Python: >=3.10
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Provides-Extra: linux
Requires-Dist: pygobject>=3.48; extra == 'linux'
Provides-Extra: macos
Requires-Dist: pyobjc>=10.0; extra == 'macos'
Provides-Extra: recorder
Requires-Dist: mss>=9.0; extra == 'recorder'
Requires-Dist: opencv-python>=4.8; extra == 'recorder'
Requires-Dist: pillow>=10.0; extra == 'recorder'
Provides-Extra: visualize
Requires-Dist: matplotlib>=3.7; extra == 'visualize'
Requires-Dist: networkx>=3.0; extra == 'visualize'
Provides-Extra: windows
Requires-Dist: comtypes>=1.4; extra == 'windows'
Description-Content-Type: text/markdown

# pyautoassist

**Playwright-style desktop automation with native OS accessibility backends.**

pyautoassist brings the developer experience of Playwright to desktop automation.
No more `time.sleep()`. No more fragile coordinate-based clicking.
Just explicit locators, native auto-waiting, and real OS accessibility APIs.

```python
import pyautoassist

app = pyautoassist.using_backend()

# XPath-style locators targeting OS accessibility properties
app.locator("//Button[@Name='Submit']").click()
app.locator("//Edit[@AutomationId='email-input']").fill("Hello World")

# CSS-style shorthand
app.locator("button.submit-btn").click()
app.locator("edit-text#main-input").fill("Hello")

# Auto-waiting: no time.sleep() needed
app.locator("//Button[@Name='Save']").click()  # waits until clickable
```

## Why pyautoassist?

| Feature | pyautogui | pywinauto | pyautoassist |
|---------|-----------|-----------|-----------|
| Locator style | Coordinates/fragile selectors | Custom syntax | CSS/XPath-style |
| Auto-waiting | None | Basic | Full (Playwright-style) |
| OS backend | Screen capture | Win32 COM | Native UIA/AX/AT-SPI |
| Codegen recorder | No | No | Yes (`pyautoassist record`) |
| Cross-platform | Yes | Windows only | Windows/macOS/Linux |

## Installation

```bash
# Core (auto-detects platform)
pip install pyautoassist

# Platform-specific extras
pip install pyautoassist[windows]   # Windows UIA
pip install pyautoassist[macos]     # macOS Accessibility
pip install pyautoassist[linux]     # Linux AT-SPI2
```

## Quick Start

```python
import pyautoassist

# Create an automation session
app = pyautoassist.using_backend()

# Find a window
notepad = app.open("Notepad")

# Use locators (auto-waits for element)
app.locator("//Edit").fill("Hello, pyautoassist!")

# Chain locators within elements
notepad.locator("//MenuItem[@Name='File']").click()
notepad.locator("//MenuItem[@Name='Save']").click()
```

## Selectors

### XPath Style

Target elements by their OS accessibility properties:

```python
# By control type and name
app.locator("//Button[@Name='Submit']")
app.locator("//Edit[@Name='Username']")

# By AutomationId (most reliable)
app.locator("//Button[@AutomationId='btn-submit']")
app.locator("//Edit[@AutomationId='email-input']")

# By ClassName
app.locator("//Pane[@ClassName='Notepad']")

# Chained: nested elements
app.locator("//Pane[@ClassName='Notepad']//Button[@Name='File']")
```

### CSS Style

Shorthand selectors for quick access:

```python
# Type + ID (AutomationId)
app.locator("button#submit-btn")

# Type + class (ClassName)
app.locator("button.submit")

# Type + attribute
app.locator('button[name="OK"]')

# Child combinator
app.locator("pane > button")
```

### Supported Control Types

`button`, `edit`/`edit-text`/`textbox`, `pane`, `window`/`dialog`,
`menu`, `menuitem`, `checkbox`, `radio`/`radiobutton`,
`combobox`/`dropdown`, `list`, `listitem`, `tree`, `treeitem`,
`toolbar`, `tab`, `tabitem`, `image`, `hyperlink`, `slider`,
`progressbar`, `scrollbar`, `group`, `tooltip`, `statusbar`,
`header`, `separator`, `document`, `dataitem`, `custom`

## Auto-Waiting

Every action on a Locator automatically waits for the element to be ready:

```python
# Waits up to 30s for the button to exist, be visible, and be enabled
app.locator("//Button[@Name='Submit']").click()

# Custom timeout
app.locator("//Button[@Name='Submit']").with_timeout(5000).click()

# Wait for specific states
app.locator("//Button[@Name='Loading']").visible().click()
app.locator("//Edit[@Name='Email']").enabled().click()
```

## Element Actions

```python
el = app.locator("//Button[@Name='Submit']")

el.click()              # Left click
el.double_click()       # Double click
el.right_click()        # Context menu
el.fill("text")         # Set value (input fields)
el.type_text("text")    # Type character by character
el.clear()              # Clear input
el.select_option(label="Option 1")  # Dropdown selection
el.focus()              # Move keyboard focus
el.hover()              # Move mouse to element
el.press_key("Enter")   # Send key press
```

## Window Management

```python
# List all windows
for w in app.get_windows():
    print(f"{w.title} (PID: {w.pid})")

# Find by title
notepad = app.find_window(title="Notepad")
notepad.focus()
notepad.move(100, 100)
notepad.resize(800, 600)
notepad.close()

# Find by PID
window = app.find_window(pid=12345)
```

## Codegen Recorder

Generate automation code by clicking around:

```bash
# Start recording (Windows)
pyautoassist record

# Save to file
pyautoassist record --output recorded.py

# Specify backend
pyautoassist record --backend macos
```

The recorder hooks into OS mouse events, inspects the accessibility tree
at each click location, and prints pyautoassist-style code in real time.

## License

MIT
