robotframework-desktop 0.1.0__py3-none-any.whl
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.
- DesktopLibrary/__init__.py +278 -0
- DesktopLibrary/context.py +272 -0
- DesktopLibrary/cursor.py +243 -0
- DesktopLibrary/engines/__init__.py +4 -0
- DesktopLibrary/engines/image.py +174 -0
- DesktopLibrary/engines/ui.py +192 -0
- DesktopLibrary/geometry.py +187 -0
- DesktopLibrary/keywords/__init__.py +23 -0
- DesktopLibrary/keywords/application.py +149 -0
- DesktopLibrary/keywords/base.py +90 -0
- DesktopLibrary/keywords/config.py +159 -0
- DesktopLibrary/keywords/cursor.py +201 -0
- DesktopLibrary/keywords/element.py +260 -0
- DesktopLibrary/keywords/find.py +136 -0
- DesktopLibrary/keywords/keyboard.py +171 -0
- DesktopLibrary/keywords/mouse.py +357 -0
- DesktopLibrary/keywords/ocr.py +166 -0
- DesktopLibrary/keywords/region.py +288 -0
- DesktopLibrary/keywords/wait.py +178 -0
- DesktopLibrary/locator.py +223 -0
- DesktopLibrary/overlay.py +180 -0
- robotframework_desktop-0.1.0.dist-info/METADATA +215 -0
- robotframework_desktop-0.1.0.dist-info/RECORD +25 -0
- robotframework_desktop-0.1.0.dist-info/WHEEL +5 -0
- robotframework_desktop-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
"""Screen overlays (highlight and interactive region selection) using Tkinter.
|
|
2
|
+
|
|
3
|
+
All Tk objects live in a dedicated daemon thread; other threads talk to it
|
|
4
|
+
through a queue.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import queue
|
|
8
|
+
import threading
|
|
9
|
+
import uuid
|
|
10
|
+
|
|
11
|
+
from .geometry import Region
|
|
12
|
+
|
|
13
|
+
_TRANSPARENT = '#ff00fe'
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class Overlay:
|
|
17
|
+
def __init__(self):
|
|
18
|
+
self._queue: queue.Queue = queue.Queue()
|
|
19
|
+
self._thread: threading.Thread | None = None
|
|
20
|
+
self._ready = threading.Event()
|
|
21
|
+
self._windows: dict[str, object] = {}
|
|
22
|
+
self._keys: dict[str, list[str]] = {}
|
|
23
|
+
self._root = None
|
|
24
|
+
|
|
25
|
+
# ---- thread ---------------------------------------------------------
|
|
26
|
+
def _ensure(self):
|
|
27
|
+
if self._thread and self._thread.is_alive():
|
|
28
|
+
return
|
|
29
|
+
self._ready.clear()
|
|
30
|
+
self._thread = threading.Thread(
|
|
31
|
+
target=self._run, name='DesktopLibraryOverlay', daemon=True
|
|
32
|
+
)
|
|
33
|
+
self._thread.start()
|
|
34
|
+
self._ready.wait(5)
|
|
35
|
+
|
|
36
|
+
def _run(self):
|
|
37
|
+
import tkinter as tk
|
|
38
|
+
|
|
39
|
+
self._root = tk.Tk()
|
|
40
|
+
self._root.withdraw()
|
|
41
|
+
self._ready.set()
|
|
42
|
+
self._root.after(30, self._poll)
|
|
43
|
+
self._root.mainloop()
|
|
44
|
+
|
|
45
|
+
def _poll(self):
|
|
46
|
+
try:
|
|
47
|
+
while True:
|
|
48
|
+
func, args = self._queue.get_nowait()
|
|
49
|
+
try:
|
|
50
|
+
func(*args)
|
|
51
|
+
except Exception:
|
|
52
|
+
pass
|
|
53
|
+
except queue.Empty:
|
|
54
|
+
pass
|
|
55
|
+
self._root.after(30, self._poll)
|
|
56
|
+
|
|
57
|
+
def _call(self, func, *args):
|
|
58
|
+
self._ensure()
|
|
59
|
+
self._queue.put((func, args))
|
|
60
|
+
|
|
61
|
+
# ---- highlight --------------------------------------------------------
|
|
62
|
+
def highlight(
|
|
63
|
+
self,
|
|
64
|
+
region: Region,
|
|
65
|
+
seconds: float = 0,
|
|
66
|
+
key: str = '',
|
|
67
|
+
color: str = 'red',
|
|
68
|
+
width: int = 3,
|
|
69
|
+
) -> str:
|
|
70
|
+
hid = uuid.uuid4().hex
|
|
71
|
+
self._keys.setdefault(key or hid, []).append(hid)
|
|
72
|
+
self._call(
|
|
73
|
+
self._create, hid, region, float(seconds or 0), color, int(width)
|
|
74
|
+
)
|
|
75
|
+
return hid
|
|
76
|
+
|
|
77
|
+
def _create(self, hid, region: Region, seconds, color, width):
|
|
78
|
+
import tkinter as tk
|
|
79
|
+
|
|
80
|
+
win = tk.Toplevel(self._root)
|
|
81
|
+
win.overrideredirect(True)
|
|
82
|
+
win.attributes('-topmost', True)
|
|
83
|
+
try:
|
|
84
|
+
win.attributes('-transparentcolor', _TRANSPARENT)
|
|
85
|
+
except tk.TclError:
|
|
86
|
+
win.attributes('-alpha', 0.4)
|
|
87
|
+
pad = width
|
|
88
|
+
win.geometry(
|
|
89
|
+
f'{region.width + 2 * pad}x{region.height + 2 * pad}+{region.x - pad}+{region.y - pad}'
|
|
90
|
+
)
|
|
91
|
+
canvas = tk.Canvas(win, bg=_TRANSPARENT, highlightthickness=0)
|
|
92
|
+
canvas.pack(fill='both', expand=True)
|
|
93
|
+
canvas.create_rectangle(
|
|
94
|
+
pad // 2,
|
|
95
|
+
pad // 2,
|
|
96
|
+
region.width + pad * 1.5,
|
|
97
|
+
region.height + pad * 1.5,
|
|
98
|
+
outline=color,
|
|
99
|
+
width=width,
|
|
100
|
+
)
|
|
101
|
+
self._windows[hid] = win
|
|
102
|
+
if seconds > 0:
|
|
103
|
+
self._root.after(int(seconds * 1000), lambda: self._destroy(hid))
|
|
104
|
+
|
|
105
|
+
def _destroy(self, hid):
|
|
106
|
+
win = self._windows.pop(hid, None)
|
|
107
|
+
if win is not None:
|
|
108
|
+
win.destroy()
|
|
109
|
+
|
|
110
|
+
def clear(self, key: str):
|
|
111
|
+
for hid in self._keys.pop(key, []):
|
|
112
|
+
self._call(self._destroy, hid)
|
|
113
|
+
|
|
114
|
+
def clear_all(self):
|
|
115
|
+
self._keys.clear()
|
|
116
|
+
for hid in list(self._windows):
|
|
117
|
+
self._call(self._destroy, hid)
|
|
118
|
+
|
|
119
|
+
# ---- region selection ---------------------------------------------------
|
|
120
|
+
def select_region(
|
|
121
|
+
self, message: str, bounds: Region, timeout: float = 300
|
|
122
|
+
) -> Region | None:
|
|
123
|
+
done = threading.Event()
|
|
124
|
+
result: dict = {}
|
|
125
|
+
self._call(self._select, message, bounds, result, done)
|
|
126
|
+
done.wait(timeout)
|
|
127
|
+
return result.get('region')
|
|
128
|
+
|
|
129
|
+
def _select(self, message, bounds: Region, result, done):
|
|
130
|
+
import tkinter as tk
|
|
131
|
+
|
|
132
|
+
win = tk.Toplevel(self._root)
|
|
133
|
+
win.overrideredirect(True)
|
|
134
|
+
win.attributes('-topmost', True)
|
|
135
|
+
win.attributes('-alpha', 0.3)
|
|
136
|
+
win.geometry(f'{bounds.width}x{bounds.height}+{bounds.x}+{bounds.y}')
|
|
137
|
+
canvas = tk.Canvas(
|
|
138
|
+
win, bg='black', cursor='cross', highlightthickness=0
|
|
139
|
+
)
|
|
140
|
+
canvas.pack(fill='both', expand=True)
|
|
141
|
+
canvas.create_text(
|
|
142
|
+
bounds.width // 2,
|
|
143
|
+
40,
|
|
144
|
+
text=message or 'Select a region (ESC to cancel)',
|
|
145
|
+
fill='white',
|
|
146
|
+
font=('Segoe UI', 18, 'bold'),
|
|
147
|
+
)
|
|
148
|
+
state = {'start': None, 'rect': None}
|
|
149
|
+
|
|
150
|
+
def press(e):
|
|
151
|
+
state['start'] = (e.x, e.y)
|
|
152
|
+
state['rect'] = canvas.create_rectangle(
|
|
153
|
+
e.x, e.y, e.x, e.y, outline='red', width=3
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
def drag(e):
|
|
157
|
+
if state['rect']:
|
|
158
|
+
sx, sy = state['start']
|
|
159
|
+
canvas.coords(state['rect'], sx, sy, e.x, e.y)
|
|
160
|
+
|
|
161
|
+
def release(e):
|
|
162
|
+
if state['start']:
|
|
163
|
+
sx, sy = state['start']
|
|
164
|
+
x1, x2 = sorted((sx, e.x))
|
|
165
|
+
y1, y2 = sorted((sy, e.y))
|
|
166
|
+
if x2 - x1 > 0 and y2 - y1 > 0:
|
|
167
|
+
result['region'] = Region(
|
|
168
|
+
bounds.x + x1, bounds.y + y1, x2 - x1, y2 - y1
|
|
169
|
+
)
|
|
170
|
+
finish()
|
|
171
|
+
|
|
172
|
+
def finish(_=None):
|
|
173
|
+
win.destroy()
|
|
174
|
+
done.set()
|
|
175
|
+
|
|
176
|
+
canvas.bind('<ButtonPress-1>', press)
|
|
177
|
+
canvas.bind('<B1-Motion>', drag)
|
|
178
|
+
canvas.bind('<ButtonRelease-1>', release)
|
|
179
|
+
win.bind('<Escape>', finish)
|
|
180
|
+
win.focus_force()
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: robotframework-desktop
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Robot Framework library for Windows desktop automation with hybrid image (pyautogui) and UI Automation (pywinauto) engines.
|
|
5
|
+
License: Apache-2.0
|
|
6
|
+
Keywords: robotframework,desktop,automation,pyautogui,pywinauto,uia,wpf,winforms
|
|
7
|
+
Classifier: Framework :: Robot Framework :: Library
|
|
8
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Requires-Python: >=3.10
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
Requires-Dist: robotframework>=6.1
|
|
13
|
+
Requires-Dist: robotframework-pythonlibcore>=4.2
|
|
14
|
+
Requires-Dist: pyautogui>=0.9.54
|
|
15
|
+
Requires-Dist: opencv-python>=4.8
|
|
16
|
+
Requires-Dist: pillow>=10.0
|
|
17
|
+
Requires-Dist: mss>=9.0
|
|
18
|
+
Requires-Dist: pywinauto>=0.6.8
|
|
19
|
+
Requires-Dist: pyperclip>=1.8
|
|
20
|
+
Requires-Dist: rapidocr>=3.0
|
|
21
|
+
Requires-Dist: onnxruntime>=1.17
|
|
22
|
+
Provides-Extra: ocr
|
|
23
|
+
Requires-Dist: rapidocr>=3.0; extra == "ocr"
|
|
24
|
+
Requires-Dist: onnxruntime>=1.17; extra == "ocr"
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: pytest>=7; extra == "dev"
|
|
27
|
+
Requires-Dist: rapidocr>=3.0; extra == "dev"
|
|
28
|
+
Requires-Dist: onnxruntime>=1.17; extra == "dev"
|
|
29
|
+
Requires-Dist: PyYAML>=6.0; extra == "dev"
|
|
30
|
+
Requires-Dist: blue>=0.9; extra == "dev"
|
|
31
|
+
|
|
32
|
+
<div align="center">
|
|
33
|
+
|
|
34
|
+
# 🖥️ robotframework-desktop
|
|
35
|
+
|
|
36
|
+
**Hybrid Windows desktop automation for [Robot Framework](https://robotframework.org)**
|
|
37
|
+
Image recognition · UI Automation · OCR — one keyword set, chosen by the locator.
|
|
38
|
+
|
|
39
|
+

|
|
40
|
+

|
|
41
|
+

|
|
42
|
+

|
|
43
|
+

|
|
44
|
+
|
|
45
|
+
[Install](#-install) · [Quick start](#-quick-start) · [Locators](#-locators) · [YAML locators](#-locators-in-a-yaml-file) · [OCR](#-ocr) · [Keywords](docs/DesktopLibrary.html)
|
|
46
|
+
|
|
47
|
+
</div>
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## ✨ Features
|
|
52
|
+
|
|
53
|
+
- 🔀 **Hybrid keywords** – `Click`, `Input Text`, `Drag And Drop`, ... work with images, UI elements or regions; the engine is picked from the `element` argument.
|
|
54
|
+
- 🖼️ **Image recognition** – pyautogui + OpenCV, per-call similarity, multiple candidate images, offsets and search regions.
|
|
55
|
+
- 🌳 **UI Automation** – pywinauto (`uia` and `win32` backends) for WPF, WinForms, UWP and Win32 apps.
|
|
56
|
+
- 🔤 **OCR** – [RapidOCR](https://github.com/RapidAI/RapidOCR) on onnxruntime, models bundled, **no external binary**; accent and case insensitive text search.
|
|
57
|
+
- ⏳ **Busy cursor aware** – actions wait automatically while the app shows the busy cursor.
|
|
58
|
+
- 🧩 **SikuliLibrary compatible** – implements all its actions, plus UIA keywords (`Attach To Window`, `Get Element Text`, `Set Element Value`, `Select Combobox Item`, ...).
|
|
59
|
+
|
|
60
|
+
## 📦 Install
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
pip install robotframework-desktop # core
|
|
64
|
+
pip install robotframework-desktop[ocr] # + OCR (rapidocr + onnxruntime)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## 🚀 Quick start
|
|
68
|
+
|
|
69
|
+
```robot
|
|
70
|
+
*** Settings ***
|
|
71
|
+
Library DesktopLibrary image_paths=${CURDIR}/images;${CURDIR}/shared similarity=0.6
|
|
72
|
+
|
|
73
|
+
*** Test Cases ***
|
|
74
|
+
Write In Notepad
|
|
75
|
+
Open Application notepad.exe
|
|
76
|
+
Attach To Window name_re:.*Notepad
|
|
77
|
+
Input Text class:Edit Hello
|
|
78
|
+
Click ${{ {"path": ["save.png", "save_dark.png"], "similarity": 0.85} }}
|
|
79
|
+
Wait Until Screen Contain done.png 10s
|
|
80
|
+
[Teardown] Close Application notepad.exe
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
> [!TIP]
|
|
84
|
+
> Relative image paths are searched in the `image_paths` folders (in order, extendable with `Add Image Path`) and then in the current working directory. The extension can be omitted.
|
|
85
|
+
|
|
86
|
+
## 🎯 Locators
|
|
87
|
+
|
|
88
|
+
| Locator | Engine |
|
|
89
|
+
|---|---|
|
|
90
|
+
| `save.png` · `save.png=0.85` · `image:C:/refs/save.png` | 🖼️ Image |
|
|
91
|
+
| `{"path": [...], "similarity": 0.8, "offset": {x, y}, "region": {x, y, width, height}}` | 🖼️ Image |
|
|
92
|
+
| `automation_id:btnSave` · `name:OK AND control_type:Button` | 🌳 UIA |
|
|
93
|
+
| `win32:class:Button` · `{"name": "Save", "backend": "win32"}` | 🌳 Win32 |
|
|
94
|
+
| `{"automation_id": "btnSave", "offset": {"x": 5, "y": 0}}` | 🌳 UIA |
|
|
95
|
+
| `[x, y, w, h]` · `{"region": {...}}` · region/match returned by keywords | 📐 Coordinates |
|
|
96
|
+
|
|
97
|
+
## 🗂️ Locators in a YAML file
|
|
98
|
+
|
|
99
|
+
Keep all element locators in one variable file ([full example](tests/atest/elements.yml)):
|
|
100
|
+
|
|
101
|
+
```yaml
|
|
102
|
+
APP:
|
|
103
|
+
BTN_SAVE: "automation_id:btnSave"
|
|
104
|
+
TXT_NAME:
|
|
105
|
+
automation_id: txtName
|
|
106
|
+
control_type: Edit
|
|
107
|
+
BTN_SAVE_WIN32:
|
|
108
|
+
name: Save
|
|
109
|
+
class_name_re: ".*BUTTON.*"
|
|
110
|
+
backend: win32
|
|
111
|
+
IMG_TARGET_OFFSET:
|
|
112
|
+
path: target.png
|
|
113
|
+
offset:
|
|
114
|
+
x: 30
|
|
115
|
+
y: 20
|
|
116
|
+
IMG_IN_REGION:
|
|
117
|
+
path: save.png
|
|
118
|
+
region:
|
|
119
|
+
x: 0
|
|
120
|
+
y: 0
|
|
121
|
+
width: 800
|
|
122
|
+
height: 600
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
```robot
|
|
126
|
+
*** Settings ***
|
|
127
|
+
Library DesktopLibrary
|
|
128
|
+
Variables elements.yml # requires PyYAML
|
|
129
|
+
|
|
130
|
+
*** Test Cases ***
|
|
131
|
+
Save
|
|
132
|
+
Input Text ${APP.TXT_NAME} Robot
|
|
133
|
+
Click ${APP.BTN_SAVE}
|
|
134
|
+
Click ${APP.IMG_TARGET_OFFSET}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## 🔤 OCR
|
|
138
|
+
|
|
139
|
+
No language setup needed — the default RapidOCR models read Latin text (accented letters may come out unaccented, so matching ignores accents and case).
|
|
140
|
+
|
|
141
|
+
```robot
|
|
142
|
+
${text}= Get Text automation_id:lblStatus
|
|
143
|
+
${text}= Read Text From Region [10, 400, 300, 30]
|
|
144
|
+
Click Text Clear
|
|
145
|
+
Set ROI [0, 0, 600, 400]
|
|
146
|
+
Region Click Text Clear
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## 🔁 Looping over elements
|
|
150
|
+
|
|
151
|
+
```robot
|
|
152
|
+
@{items}= Find Elements control_type:ListItem # [] when nothing is found
|
|
153
|
+
FOR ${item} IN @{items}
|
|
154
|
+
${text}= Get Element Text ${item}
|
|
155
|
+
IF $text == "Item 3" Click ${item}
|
|
156
|
+
END
|
|
157
|
+
@{icons}= Find Elements icon.png sort_by=column min_count=3
|
|
158
|
+
@{rows}= Find Child Elements automation_id:grid control_type:DataItem depth=1
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## ⏳ Busy cursor handling
|
|
162
|
+
|
|
163
|
+
Action keywords wait while the cursor is busy (`wait` / `appstarting`) until it stays normal for 0.5 s — **before** searching, before acting and **after** the action (watched for 0.2 s). On timeout (default 30 s) the keyword fails, or only warns with `busy_cursor_fail=False` / `ignore_busy_error=True`. Use `show_warnings=False` to log warnings as INFO.
|
|
164
|
+
|
|
165
|
+
```robot
|
|
166
|
+
Library DesktopLibrary busy_cursor_timeout=1 min busy_cursor_after_delay=0.3s
|
|
167
|
+
|
|
168
|
+
Click automation_id:btnLoad ignore_busy_error=True
|
|
169
|
+
Set Busy Cursor Wait False
|
|
170
|
+
Set Busy Cursor Types wait,appstarting,custom
|
|
171
|
+
Wait Until Cursor Is Not Busy 2 min
|
|
172
|
+
${cursor}= Get Current Cursor Type
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## 📚 Documentation
|
|
176
|
+
|
|
177
|
+
Full keyword reference: **[docs/DesktopLibrary.html](docs/DesktopLibrary.html)** (`just docs` to regenerate).
|
|
178
|
+
|
|
179
|
+
## 🛠️ Development
|
|
180
|
+
|
|
181
|
+
Requires [uv](https://docs.astral.sh/uv/) and [just](https://github.com/casey/just) (PowerShell recipes).
|
|
182
|
+
|
|
183
|
+
| Command | Description |
|
|
184
|
+
|---|---|
|
|
185
|
+
| `just setup` | Create `.venv` and install the library (editable + dev deps) |
|
|
186
|
+
| `just fmt` | Format code with [blue](https://github.com/grantjenks/blue) |
|
|
187
|
+
| `just test` | Unit tests (pytest) |
|
|
188
|
+
| `just atest` | Acceptance tests (Robot Framework) |
|
|
189
|
+
| `just docs` | Regenerate libdoc |
|
|
190
|
+
| `just build` | Build both wheels |
|
|
191
|
+
| `just build-full` | `dist/full` – OCR deps required |
|
|
192
|
+
| `just build-no-ocr` | `dist/no-ocr` – OCR optional (`[ocr]` extra) |
|
|
193
|
+
| `just check` | Show dependencies of the built wheels |
|
|
194
|
+
|
|
195
|
+
### Release
|
|
196
|
+
|
|
197
|
+
CI ([.github/workflows/ci.yml](.github/workflows/ci.yml)) runs lint, unit and acceptance tests on every push and pull request.
|
|
198
|
+
To publish a release, bump `version` in `pyproject.toml`, then:
|
|
199
|
+
|
|
200
|
+
```powershell
|
|
201
|
+
git tag v0.2.0
|
|
202
|
+
git push --tags
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
[.github/workflows/release.yml](.github/workflows/release.yml) runs the tests, builds both wheels and creates a GitHub Release with them attached:
|
|
206
|
+
|
|
207
|
+
- `robotframework-desktop` - OCR optional (`[ocr]` extra)
|
|
208
|
+
- `robotframework-desktop-full` - OCR deps required
|
|
209
|
+
|
|
210
|
+
> [!WARNING]
|
|
211
|
+
> The acceptance suite launches a small WinForms app ([tests/app/SampleApp.ps1](tests/app/SampleApp.ps1)) and generates its reference images at runtime. **Don't use the mouse or keyboard while it runs.**
|
|
212
|
+
|
|
213
|
+
## 📄 License
|
|
214
|
+
|
|
215
|
+
[Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
DesktopLibrary/__init__.py,sha256=v6_IvClm3ij_ve6ffFA4TfP2Em3nOnQkH_Rl-BcRa2U,11729
|
|
2
|
+
DesktopLibrary/context.py,sha256=Myqoe-ACr91XP3g41YxmUjfT951JI6P5gebiSZz_QzA,10125
|
|
3
|
+
DesktopLibrary/cursor.py,sha256=ACpv5kZgEZVsqL88LehMEB2iZhF3QT-eGrMgmfJKRGk,8573
|
|
4
|
+
DesktopLibrary/geometry.py,sha256=C4M6tLB16iQ-Vy9VU3m63SnVNWdRCA6f6xxxw6O3UcE,6722
|
|
5
|
+
DesktopLibrary/locator.py,sha256=ZjeT7MBbCbkgKToNzhF3h0V176PeUvI_ib_WlgZ_8PA,7383
|
|
6
|
+
DesktopLibrary/overlay.py,sha256=FFTmMPOJcXqv3EK_Pp7DKZuYJczjPYJGqrqydIrpjxM,5707
|
|
7
|
+
DesktopLibrary/engines/__init__.py,sha256=H2e7e6Q0aAqOcKVTnjnv_AucouoZuQHD_oVJvMpUpTk,139
|
|
8
|
+
DesktopLibrary/engines/image.py,sha256=oEj0vSe0recQX4cFSlzJ5ec__9yR8vAPUFQwa1ZJJp4,6152
|
|
9
|
+
DesktopLibrary/engines/ui.py,sha256=u9S--vIiE-JDfl6YGrw1Uvu4mRJHzRtHn2b6nn-L69o,6210
|
|
10
|
+
DesktopLibrary/keywords/__init__.py,sha256=DvYDv9uKyoa6LzTF9QGCidALVEGteTqTxnXtK_YMbEo,608
|
|
11
|
+
DesktopLibrary/keywords/application.py,sha256=4em6Bjyy802bBSe56TbBzg73Wr5iNMW5T4lpw49ZGB8,5073
|
|
12
|
+
DesktopLibrary/keywords/base.py,sha256=nOzEGtOpGgzSVIjzCqKBALOJLtJG0lRFFEN9fNYaMEE,2986
|
|
13
|
+
DesktopLibrary/keywords/config.py,sha256=DPaLerkHU0Q8QPmgmxqvz9cvbLfH2b3WP12iEoGv9OU,4901
|
|
14
|
+
DesktopLibrary/keywords/cursor.py,sha256=svRADiYSFX2N4woxK1KtxgMtQDhx6N1yTMEGp6wy6HA,7689
|
|
15
|
+
DesktopLibrary/keywords/element.py,sha256=ieAIUh2wcHdfr5oCn61nGqEzQZSjeh8SH47NaRgz4Wc,8991
|
|
16
|
+
DesktopLibrary/keywords/find.py,sha256=SxK25gFYCbuSPSRfVggZfkZlcIyV8NjqHlISt7Sl010,5446
|
|
17
|
+
DesktopLibrary/keywords/keyboard.py,sha256=11lPEFTLxeNSZGRD7YBli2wplYzSYfbRfxZDVjKWTPk,4756
|
|
18
|
+
DesktopLibrary/keywords/mouse.py,sha256=zZDX2mrHCQfDX_B4GOwKkwiRMecSevX-YC_fdJXnAI0,12314
|
|
19
|
+
DesktopLibrary/keywords/ocr.py,sha256=zXy9HbetD5vNB6zd95hrqpFlSLdMQHmaK51rm50u8vA,5442
|
|
20
|
+
DesktopLibrary/keywords/region.py,sha256=CTwysDYAx7d2WYKJuML20r5WtnqkqM3anEZSkavUYHQ,10308
|
|
21
|
+
DesktopLibrary/keywords/wait.py,sha256=DIfbUrgxicOTFmvf7DOuAYBne2BkFbw58pdMaV7YEgM,6523
|
|
22
|
+
robotframework_desktop-0.1.0.dist-info/METADATA,sha256=SvMaaX--oZT6jFLHh_HvKyy4kSGBQjDLPUqFyQitg5s,8437
|
|
23
|
+
robotframework_desktop-0.1.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
24
|
+
robotframework_desktop-0.1.0.dist-info/top_level.txt,sha256=5eYvVeCi3VKx9Lg4zk4yqN9m5A60Nxlima2FQIDCLKo,15
|
|
25
|
+
robotframework_desktop-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
DesktopLibrary
|