platynui-native


Nameplatynui-native JSON
Version 0.12.0.dev3 PyPI version JSON
download
home_pageNone
SummaryNative Python bindings for PlatynUI (core types + runtime)
upload_time2025-10-23 12:18:39
maintainerNone
docs_urlNone
authorNone
requires_python>=3.10
licenseApache-2.0
keywords robotframework platynui gui automation desktop
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            platynui-native
================

Native Python bindings for PlatynUI using PyO3 + maturin.

Quick start (local develop):

- uv sync --dev
- uv run maturin develop -m packages/native/Cargo.toml --release --features mock-provider

Then in Python:

```python
from platynui_native import core, runtime
pt = core.Point(1.0, 2.0)
rt = runtime.Runtime()
items = rt.evaluate("/control:Desktop", None)
```

Run smoke tests (uses mock provider feature):

```
uv run maturin develop -m packages/native/Cargo.toml --release --features mock-provider
uv run pytest -q packages/native/tests
```

API overview

- Module layout
  - `platynui_native.core`: `Point`/`Size`/`Rect`, `Namespace`, IDs, `attribute_names()`
  - `platynui_native.runtime`: `Runtime`, `UiNode`, `UiAttribute`, `EvaluatedAttribute`, pointer/keyboard methods
  - New: `Runtime.keyboard_known_key_names()` returns a list of supported key names from the active keyboard device.

- Creating a Runtime
  - `rt = runtime.Runtime()`

- Pointer buttons
  - Accepts: `'left' | 'middle' | 'right'`, `runtime.PointerButton` enum, or `int`.
  - Mapping: `1 → LEFT`, `2 → MIDDLE`, `3 → RIGHT`, other ints → `Other(n)`.

- Pointer overrides (class)
  - Timing (milliseconds unless noted):
    - `after_move_delay_ms`, `after_input_delay_ms`, `press_release_delay_ms`,
      `after_click_delay_ms`, `before_next_click_delay_ms`, `multi_click_delay_ms`,
      `ensure_move_timeout_ms`, `scroll_delay_ms`, `max_move_duration_ms`.
    - `move_time_per_pixel_us` (microseconds per pixel)
  - Motion/profile:
    - `speed_factor: float`
    - `acceleration_profile: 'constant'|'ease_in'|'ease_out'|'smooth_step'`
  - Origin (choose one):
    - `'desktop'`
    - `core.Point(x, y)` → absolute desktop point
    - `core.Rect(x, y, w, h)` → relative to rect (top-left origin)
  - Scrolling:
    - `scroll_step: (h: float, v: float)`; `scroll_delay_ms`
  - Other:
    - `ensure_move_threshold: float`
  - Properties: all fields are exposed read‑only (e.g. `ov.speed_factor`, `ov.origin`, `ov.after_move_delay_ms`).

- Keyboard overrides (class, milliseconds)
  - `press_delay_ms`, `release_delay_ms`, `between_keys_delay_ms`,
    `chord_press_delay_ms`, `chord_release_delay_ms`,
    `after_sequence_delay_ms`, `after_text_delay_ms`.
  - Properties: `kov.press_delay_ms`, `kov.between_keys_delay_ms`, etc.

Examples

```python
from platynui_native import core, runtime
rt = runtime.Runtime()

# Move & click with overrides
ov = runtime.PointerOverrides(speed_factor=1.5, after_move_delay_ms=15, origin='desktop')
rt.pointer_move_to(core.Point(100, 200), overrides=ov)
rt.pointer_click(core.Point(100, 200), button=runtime.PointerButton.LEFT,
                 overrides=runtime.PointerOverrides(multi_click_delay_ms=240))

# Click at current pointer position (no move)
rt.pointer_click(None, button=runtime.PointerButton.LEFT)

# Drag with relative origin
rt.pointer_drag(core.Point(10, 10), core.Point(180, 140), button=runtime.PointerButton.LEFT,
                overrides=runtime.PointerOverrides(origin=core.Rect(50, 60, 200, 200)))

# Keyboard with custom timings
rt.keyboard_type("Hello", overrides=runtime.KeyboardOverrides(between_keys_delay_ms=5))
rt.keyboard_press("<Ctrl+C>")
rt.keyboard_release("<Ctrl+C>")

# Inspect available key names from the active device
names = rt.keyboard_known_key_names()
print(names[:20])
```

Notes

- The mock provider feature (`--features mock-provider`) is intended for local development without platform backends. Some pointer/keyboard calls may raise `PointerError`/`KeyboardError` if the device is not available; structure/typing of arguments is still validated.

- Evaluate results
  - `Runtime.evaluate()` returns a list of `UiNode`, `EvaluatedAttribute`, or plain values (`UiValue`).
  - `UiNode.attributes()` returns `list[UiAttribute]` (no owner).
  - `EvaluatedAttribute` includes an `owner()` reference back to the `UiNode` it belongs to.

Reference

- Pointer defaults (from runtime profile/settings)
  - double_click_time: 500 ms; double_click_size: (4.0, 4.0); default_button: left
  - mode: Linear; steps_per_pixel: 1.5; speed_factor: 1.0
  - max_move_duration: 600 ms; move_time_per_pixel: 800 µs
  - acceleration_profile: SmoothStep
  - after_move_delay: 40 ms; after_input_delay: 35 ms
  - press_release_delay: 50 ms; after_click_delay: 80 ms
  - before_next_click_delay: 120 ms; multi_click_delay: 500 ms
  - ensure_move_position: true; ensure_move_threshold: 2.0; ensure_move_timeout: 250 ms
  - scroll_step: (0.0, -120.0); scroll_delay: 40 ms

- Keyboard defaults (KeyboardSettings.default)
  - press_delay: 35 ms; release_delay: 25 ms
  - between_keys_delay: 40 ms
  - chord_press_delay: 45 ms; chord_release_delay: 45 ms
  - after_sequence_delay: 75 ms; after_text_delay: 20 ms

Robot Framework usage (example)

Wrap the native runtime into a simple Python library and import it in Robot suites:

1) Create `examples/robot/platynui_lib.py`:

```python
from platynui_native import runtime

class PlatynUILib:
    def __init__(self):
        self.rt = runtime.Runtime()

    def pointer_move_to(self, x: float, y: float):
        self.rt.pointer_move_to((float(x), float(y)))

    def keyboard_type(self, sequence: str):
        self.rt.keyboard_type(sequence)
```

2) Create `examples/robot/quickstart.robot`:

```
*** Settings ***
Library    examples/robot/platynui_lib.py

*** Test Cases ***
Pointer And Keyboard Smoke
    Pointer Move To    100    200
    Keyboard Type      Hello
```

3) Run with the mock feature installed:

```
uv run maturin develop -m packages/native/Cargo.toml --release --features mock-provider
uv run robot examples/robot/quickstart.robot

Troubleshooting

## Mock Providers and Platform Devices

Mock providers do NOT auto-register in the inventory system. They are explicitly exposed as Python handles for testing:

### Available Mock Components

- **`MOCK_PROVIDER`** - Mock UI tree provider (provides a test UI tree)
- **`MOCK_PLATFORM`** - Mock desktop info provider (provides MockOS desktop with 3 monitors)
- **`MOCK_HIGHLIGHT_PROVIDER`** - Mock highlight provider
- **`MOCK_SCREENSHOT_PROVIDER`** - Mock screenshot provider
- **`MOCK_POINTER_DEVICE`** - Mock pointer/mouse device
- **`MOCK_KEYBOARD_DEVICE`** - Mock keyboard device

### Usage Examples

**Basic Runtime with Mock Provider:**
```python
from platynui_native import Runtime, MOCK_PROVIDER

rt = Runtime.new_with_providers([MOCK_PROVIDER])
# Uses OS platform devices (may fail if not available)
```

**Full Mock Runtime (for testing):**
```python
from platynui_native import (
    Runtime, PlatformOverrides,
    MOCK_PROVIDER, MOCK_PLATFORM,
    MOCK_POINTER_DEVICE, MOCK_KEYBOARD_DEVICE,
    MOCK_SCREENSHOT_PROVIDER, MOCK_HIGHLIGHT_PROVIDER
)

# Configure platform overrides
overrides = PlatformOverrides()
overrides.desktop_info = MOCK_PLATFORM
overrides.pointer = MOCK_POINTER_DEVICE
overrides.keyboard = MOCK_KEYBOARD_DEVICE
overrides.screenshot = MOCK_SCREENSHOT_PROVIDER
overrides.highlight = MOCK_HIGHLIGHT_PROVIDER

# Create runtime with all mock components
rt = Runtime.new_with_providers_and_platforms([MOCK_PROVIDER], overrides)

# Now all operations work without real OS providers
info = rt.desktop_info()
print(info["os_name"])  # Output: "MockOS"
```

### Build Requirements

The `mock-provider` feature links the mock crates, making the handles available:

```bash
uv run maturin develop -m packages/native/Cargo.toml --features mock-provider
```

### Common Issues

- **"no PointerDevice registered"**: Pass `MOCK_POINTER_DEVICE` in `PlatformOverrides`
- **"no KeyboardDevice registered"**: Pass `MOCK_KEYBOARD_DEVICE` in `PlatformOverrides`
- **Want mock desktop info**: Pass `MOCK_PLATFORM` in `overrides.desktop_info`

## Other Issues

- If `maturin` complains about the manifest path, always pass `-m packages/native/Cargo.toml` for mixed projects.
- If your shell shows a VIRTUAL_ENV mismatch, prefer `uv run --active ...` to target the active environment explicitly.
```
- Multi‑click: `Runtime.pointer_multi_click(point=None, clicks=2, ...)` uses 2 clicks by default.


            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "platynui-native",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.10",
    "maintainer_email": "Daniel Biehl <daniel.biehl@imbus.de>",
    "keywords": "robotframework, platynui, gui, automation, desktop",
    "author": null,
    "author_email": "Daniel Biehl <daniel.biehl@imbus.de>",
    "download_url": null,
    "platform": null,
    "description": "platynui-native\r\n================\r\n\r\nNative Python bindings for PlatynUI using PyO3 + maturin.\r\n\r\nQuick start (local develop):\r\n\r\n- uv sync --dev\r\n- uv run maturin develop -m packages/native/Cargo.toml --release --features mock-provider\r\n\r\nThen in Python:\r\n\r\n```python\r\nfrom platynui_native import core, runtime\r\npt = core.Point(1.0, 2.0)\r\nrt = runtime.Runtime()\r\nitems = rt.evaluate(\"/control:Desktop\", None)\r\n```\r\n\r\nRun smoke tests (uses mock provider feature):\r\n\r\n```\r\nuv run maturin develop -m packages/native/Cargo.toml --release --features mock-provider\r\nuv run pytest -q packages/native/tests\r\n```\r\n\r\nAPI overview\r\n\r\n- Module layout\r\n  - `platynui_native.core`: `Point`/`Size`/`Rect`, `Namespace`, IDs, `attribute_names()`\r\n  - `platynui_native.runtime`: `Runtime`, `UiNode`, `UiAttribute`, `EvaluatedAttribute`, pointer/keyboard methods\r\n  - New: `Runtime.keyboard_known_key_names()` returns a list of supported key names from the active keyboard device.\r\n\r\n- Creating a Runtime\r\n  - `rt = runtime.Runtime()`\r\n\r\n- Pointer buttons\r\n  - Accepts: `'left' | 'middle' | 'right'`, `runtime.PointerButton` enum, or `int`.\r\n  - Mapping: `1 \u2192 LEFT`, `2 \u2192 MIDDLE`, `3 \u2192 RIGHT`, other ints \u2192 `Other(n)`.\r\n\r\n- Pointer overrides (class)\r\n  - Timing (milliseconds unless noted):\r\n    - `after_move_delay_ms`, `after_input_delay_ms`, `press_release_delay_ms`,\r\n      `after_click_delay_ms`, `before_next_click_delay_ms`, `multi_click_delay_ms`,\r\n      `ensure_move_timeout_ms`, `scroll_delay_ms`, `max_move_duration_ms`.\r\n    - `move_time_per_pixel_us` (microseconds per pixel)\r\n  - Motion/profile:\r\n    - `speed_factor: float`\r\n    - `acceleration_profile: 'constant'|'ease_in'|'ease_out'|'smooth_step'`\r\n  - Origin (choose one):\r\n    - `'desktop'`\r\n    - `core.Point(x, y)` \u2192 absolute desktop point\r\n    - `core.Rect(x, y, w, h)` \u2192 relative to rect (top-left origin)\r\n  - Scrolling:\r\n    - `scroll_step: (h: float, v: float)`; `scroll_delay_ms`\r\n  - Other:\r\n    - `ensure_move_threshold: float`\r\n  - Properties: all fields are exposed read\u2011only (e.g. `ov.speed_factor`, `ov.origin`, `ov.after_move_delay_ms`).\r\n\r\n- Keyboard overrides (class, milliseconds)\r\n  - `press_delay_ms`, `release_delay_ms`, `between_keys_delay_ms`,\r\n    `chord_press_delay_ms`, `chord_release_delay_ms`,\r\n    `after_sequence_delay_ms`, `after_text_delay_ms`.\r\n  - Properties: `kov.press_delay_ms`, `kov.between_keys_delay_ms`, etc.\r\n\r\nExamples\r\n\r\n```python\r\nfrom platynui_native import core, runtime\r\nrt = runtime.Runtime()\r\n\r\n# Move & click with overrides\r\nov = runtime.PointerOverrides(speed_factor=1.5, after_move_delay_ms=15, origin='desktop')\r\nrt.pointer_move_to(core.Point(100, 200), overrides=ov)\r\nrt.pointer_click(core.Point(100, 200), button=runtime.PointerButton.LEFT,\r\n                 overrides=runtime.PointerOverrides(multi_click_delay_ms=240))\r\n\r\n# Click at current pointer position (no move)\r\nrt.pointer_click(None, button=runtime.PointerButton.LEFT)\r\n\r\n# Drag with relative origin\r\nrt.pointer_drag(core.Point(10, 10), core.Point(180, 140), button=runtime.PointerButton.LEFT,\r\n                overrides=runtime.PointerOverrides(origin=core.Rect(50, 60, 200, 200)))\r\n\r\n# Keyboard with custom timings\r\nrt.keyboard_type(\"Hello\", overrides=runtime.KeyboardOverrides(between_keys_delay_ms=5))\r\nrt.keyboard_press(\"<Ctrl+C>\")\r\nrt.keyboard_release(\"<Ctrl+C>\")\r\n\r\n# Inspect available key names from the active device\r\nnames = rt.keyboard_known_key_names()\r\nprint(names[:20])\r\n```\r\n\r\nNotes\r\n\r\n- The mock provider feature (`--features mock-provider`) is intended for local development without platform backends. Some pointer/keyboard calls may raise `PointerError`/`KeyboardError` if the device is not available; structure/typing of arguments is still validated.\r\n\r\n- Evaluate results\r\n  - `Runtime.evaluate()` returns a list of `UiNode`, `EvaluatedAttribute`, or plain values (`UiValue`).\r\n  - `UiNode.attributes()` returns `list[UiAttribute]` (no owner).\r\n  - `EvaluatedAttribute` includes an `owner()` reference back to the `UiNode` it belongs to.\r\n\r\nReference\r\n\r\n- Pointer defaults (from runtime profile/settings)\r\n  - double_click_time: 500 ms; double_click_size: (4.0, 4.0); default_button: left\r\n  - mode: Linear; steps_per_pixel: 1.5; speed_factor: 1.0\r\n  - max_move_duration: 600 ms; move_time_per_pixel: 800 \u00b5s\r\n  - acceleration_profile: SmoothStep\r\n  - after_move_delay: 40 ms; after_input_delay: 35 ms\r\n  - press_release_delay: 50 ms; after_click_delay: 80 ms\r\n  - before_next_click_delay: 120 ms; multi_click_delay: 500 ms\r\n  - ensure_move_position: true; ensure_move_threshold: 2.0; ensure_move_timeout: 250 ms\r\n  - scroll_step: (0.0, -120.0); scroll_delay: 40 ms\r\n\r\n- Keyboard defaults (KeyboardSettings.default)\r\n  - press_delay: 35 ms; release_delay: 25 ms\r\n  - between_keys_delay: 40 ms\r\n  - chord_press_delay: 45 ms; chord_release_delay: 45 ms\r\n  - after_sequence_delay: 75 ms; after_text_delay: 20 ms\r\n\r\nRobot Framework usage (example)\r\n\r\nWrap the native runtime into a simple Python library and import it in Robot suites:\r\n\r\n1) Create `examples/robot/platynui_lib.py`:\r\n\r\n```python\r\nfrom platynui_native import runtime\r\n\r\nclass PlatynUILib:\r\n    def __init__(self):\r\n        self.rt = runtime.Runtime()\r\n\r\n    def pointer_move_to(self, x: float, y: float):\r\n        self.rt.pointer_move_to((float(x), float(y)))\r\n\r\n    def keyboard_type(self, sequence: str):\r\n        self.rt.keyboard_type(sequence)\r\n```\r\n\r\n2) Create `examples/robot/quickstart.robot`:\r\n\r\n```\r\n*** Settings ***\r\nLibrary    examples/robot/platynui_lib.py\r\n\r\n*** Test Cases ***\r\nPointer And Keyboard Smoke\r\n    Pointer Move To    100    200\r\n    Keyboard Type      Hello\r\n```\r\n\r\n3) Run with the mock feature installed:\r\n\r\n```\r\nuv run maturin develop -m packages/native/Cargo.toml --release --features mock-provider\r\nuv run robot examples/robot/quickstart.robot\r\n\r\nTroubleshooting\r\n\r\n## Mock Providers and Platform Devices\r\n\r\nMock providers do NOT auto-register in the inventory system. They are explicitly exposed as Python handles for testing:\r\n\r\n### Available Mock Components\r\n\r\n- **`MOCK_PROVIDER`** - Mock UI tree provider (provides a test UI tree)\r\n- **`MOCK_PLATFORM`** - Mock desktop info provider (provides MockOS desktop with 3 monitors)\r\n- **`MOCK_HIGHLIGHT_PROVIDER`** - Mock highlight provider\r\n- **`MOCK_SCREENSHOT_PROVIDER`** - Mock screenshot provider\r\n- **`MOCK_POINTER_DEVICE`** - Mock pointer/mouse device\r\n- **`MOCK_KEYBOARD_DEVICE`** - Mock keyboard device\r\n\r\n### Usage Examples\r\n\r\n**Basic Runtime with Mock Provider:**\r\n```python\r\nfrom platynui_native import Runtime, MOCK_PROVIDER\r\n\r\nrt = Runtime.new_with_providers([MOCK_PROVIDER])\r\n# Uses OS platform devices (may fail if not available)\r\n```\r\n\r\n**Full Mock Runtime (for testing):**\r\n```python\r\nfrom platynui_native import (\r\n    Runtime, PlatformOverrides,\r\n    MOCK_PROVIDER, MOCK_PLATFORM,\r\n    MOCK_POINTER_DEVICE, MOCK_KEYBOARD_DEVICE,\r\n    MOCK_SCREENSHOT_PROVIDER, MOCK_HIGHLIGHT_PROVIDER\r\n)\r\n\r\n# Configure platform overrides\r\noverrides = PlatformOverrides()\r\noverrides.desktop_info = MOCK_PLATFORM\r\noverrides.pointer = MOCK_POINTER_DEVICE\r\noverrides.keyboard = MOCK_KEYBOARD_DEVICE\r\noverrides.screenshot = MOCK_SCREENSHOT_PROVIDER\r\noverrides.highlight = MOCK_HIGHLIGHT_PROVIDER\r\n\r\n# Create runtime with all mock components\r\nrt = Runtime.new_with_providers_and_platforms([MOCK_PROVIDER], overrides)\r\n\r\n# Now all operations work without real OS providers\r\ninfo = rt.desktop_info()\r\nprint(info[\"os_name\"])  # Output: \"MockOS\"\r\n```\r\n\r\n### Build Requirements\r\n\r\nThe `mock-provider` feature links the mock crates, making the handles available:\r\n\r\n```bash\r\nuv run maturin develop -m packages/native/Cargo.toml --features mock-provider\r\n```\r\n\r\n### Common Issues\r\n\r\n- **\"no PointerDevice registered\"**: Pass `MOCK_POINTER_DEVICE` in `PlatformOverrides`\r\n- **\"no KeyboardDevice registered\"**: Pass `MOCK_KEYBOARD_DEVICE` in `PlatformOverrides`\r\n- **Want mock desktop info**: Pass `MOCK_PLATFORM` in `overrides.desktop_info`\r\n\r\n## Other Issues\r\n\r\n- If `maturin` complains about the manifest path, always pass `-m packages/native/Cargo.toml` for mixed projects.\r\n- If your shell shows a VIRTUAL_ENV mismatch, prefer `uv run --active ...` to target the active environment explicitly.\r\n```\r\n- Multi\u2011click: `Runtime.pointer_multi_click(point=None, clicks=2, ...)` uses 2 clicks by default.\r\n\n",
    "bugtrack_url": null,
    "license": "Apache-2.0",
    "summary": "Native Python bindings for PlatynUI (core types + runtime)",
    "version": "0.12.0.dev3",
    "project_urls": {
        "Changelog": "https://github.com/imbus/robotframework-PlatynUI/blob/main/CHANGELOG.md",
        "Documentation": "https://github.com/imbus/robotframework-PlatynUI#readme",
        "Homepage": "https://github.com/imbus/robotframework-PlatynUI",
        "Issues": "https://github.com/imbus/robotframework-PlatynUI/issues",
        "Source": "https://github.com/imbus/robotframework-PlatynUI"
    },
    "split_keywords": [
        "robotframework",
        " platynui",
        " gui",
        " automation",
        " desktop"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "e3a413ebbf9e82ea7406cb5b007fd841d5fc5fe44f17c8e8df54435016160b47",
                "md5": "90b0fa44ffbfe95159ba78e8e7e55dac",
                "sha256": "b16fa62cd268398aee3a244b0f543e1333a371b0e9ba913d5501ed63e906877d"
            },
            "downloads": -1,
            "filename": "platynui_native-0.12.0.dev3-cp310-abi3-win_amd64.whl",
            "has_sig": false,
            "md5_digest": "90b0fa44ffbfe95159ba78e8e7e55dac",
            "packagetype": "bdist_wheel",
            "python_version": "cp310",
            "requires_python": ">=3.10",
            "size": 2489230,
            "upload_time": "2025-10-23T12:18:39",
            "upload_time_iso_8601": "2025-10-23T12:18:39.775001Z",
            "url": "https://files.pythonhosted.org/packages/e3/a4/13ebbf9e82ea7406cb5b007fd841d5fc5fe44f17c8e8df54435016160b47/platynui_native-0.12.0.dev3-cp310-abi3-win_amd64.whl",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-10-23 12:18:39",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "imbus",
    "github_project": "robotframework-PlatynUI",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "platynui-native"
}
        
Elapsed time: 0.76582s