uiautodev 0.10.0__py3-none-any.whl → 0.11.1__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.
Potentially problematic release.
This version of uiautodev might be problematic. Click here for more details.
- uiautodev/__init__.py +1 -1
- uiautodev/command_proxy.py +10 -2
- uiautodev/command_types.py +7 -1
- uiautodev/driver/android.py +8 -2
- uiautodev/driver/base_driver.py +8 -1
- uiautodev/driver/harmony.py +149 -9
- uiautodev/model.py +1 -0
- uiautodev/provider.py +10 -4
- uiautodev/router/proxy.py +1 -2
- {uiautodev-0.10.0.dist-info → uiautodev-0.11.1.dist-info}/METADATA +4 -2
- {uiautodev-0.10.0.dist-info → uiautodev-0.11.1.dist-info}/RECORD +14 -14
- {uiautodev-0.10.0.dist-info → uiautodev-0.11.1.dist-info}/WHEEL +1 -1
- {uiautodev-0.10.0.dist-info → uiautodev-0.11.1.dist-info}/entry_points.txt +0 -0
- {uiautodev-0.10.0.dist-info → uiautodev-0.11.1.dist-info/licenses}/LICENSE +0 -0
uiautodev/__init__.py
CHANGED
uiautodev/command_proxy.py
CHANGED
|
@@ -13,7 +13,7 @@ from typing import Callable, Dict, List, Optional, Union
|
|
|
13
13
|
from pydantic import BaseModel
|
|
14
14
|
|
|
15
15
|
from uiautodev.command_types import AppLaunchRequest, AppTerminateRequest, By, Command, CurrentAppResponse, \
|
|
16
|
-
DumpResponse, FindElementRequest, FindElementResponse, InstallAppRequest, InstallAppResponse, TapRequest, \
|
|
16
|
+
DumpResponse, FindElementRequest, FindElementResponse, InstallAppRequest, InstallAppResponse, SendKeysRequest, TapRequest, \
|
|
17
17
|
WindowSizeResponse
|
|
18
18
|
from uiautodev.driver.base_driver import BaseDriver
|
|
19
19
|
from uiautodev.exceptions import ElementNotFoundError
|
|
@@ -39,7 +39,7 @@ def get_command_params_type(command: Command) -> Optional[BaseModel]:
|
|
|
39
39
|
return type_hints.get("params")
|
|
40
40
|
|
|
41
41
|
|
|
42
|
-
def send_command(driver: BaseDriver, command:
|
|
42
|
+
def send_command(driver: BaseDriver, command: Command, params=None):
|
|
43
43
|
if command not in COMMANDS:
|
|
44
44
|
raise NotImplementedError(f"command {command} not implemented")
|
|
45
45
|
func = COMMANDS[command]
|
|
@@ -142,6 +142,14 @@ def dump(driver: BaseDriver) -> DumpResponse:
|
|
|
142
142
|
def wake_up(driver: BaseDriver):
|
|
143
143
|
driver.wake_up()
|
|
144
144
|
|
|
145
|
+
@register(Command.SEND_KEYS)
|
|
146
|
+
def send_keys(driver: BaseDriver, params: SendKeysRequest):
|
|
147
|
+
driver.send_keys(params.text)
|
|
148
|
+
|
|
149
|
+
@register(Command.CLEAR_TEXT)
|
|
150
|
+
def clear_text(driver: BaseDriver):
|
|
151
|
+
driver.clear_text()
|
|
152
|
+
|
|
145
153
|
|
|
146
154
|
def node_match(node: Node, by: By, value: str) -> bool:
|
|
147
155
|
if by == By.ID:
|
uiautodev/command_types.py
CHANGED
|
@@ -39,6 +39,8 @@ class Command(str, enum.Enum):
|
|
|
39
39
|
VOLUME_UP = "volumeUp"
|
|
40
40
|
VOLUME_DOWN = "volumeDown"
|
|
41
41
|
VOLUME_MUTE = "volumeMute"
|
|
42
|
+
SEND_KEYS = "sendKeys"
|
|
43
|
+
CLEAR_TEXT = "clearText"
|
|
42
44
|
|
|
43
45
|
|
|
44
46
|
class TapRequest(BaseModel):
|
|
@@ -94,4 +96,8 @@ class FindElementRequest(BaseModel):
|
|
|
94
96
|
|
|
95
97
|
class FindElementResponse(BaseModel):
|
|
96
98
|
count: int
|
|
97
|
-
value: List[Node]
|
|
99
|
+
value: List[Node]
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
class SendKeysRequest(BaseModel):
|
|
103
|
+
text: str
|
uiautodev/driver/android.py
CHANGED
|
@@ -127,7 +127,7 @@ class AndroidDriver(BaseDriver):
|
|
|
127
127
|
def volume_mute(self):
|
|
128
128
|
self.adb_device.keyevent("VOLUME_MUTE")
|
|
129
129
|
|
|
130
|
-
def get_app_version(self, package_name: str) ->
|
|
130
|
+
def get_app_version(self, package_name: str) -> dict:
|
|
131
131
|
"""
|
|
132
132
|
Get the version information of an app, including mainVersion and subVersion.
|
|
133
133
|
|
|
@@ -172,11 +172,17 @@ class AndroidDriver(BaseDriver):
|
|
|
172
172
|
|
|
173
173
|
def open_app_file(self, package: str) -> Iterator[bytes]:
|
|
174
174
|
line = self.adb_device.shell(f"pm path {package}")
|
|
175
|
+
assert isinstance(line, str)
|
|
175
176
|
if not line.startswith("package:"):
|
|
176
177
|
raise AndroidDriverException(f"Failed to get package path: {line}")
|
|
177
178
|
remote_path = line.split(':', 1)[1]
|
|
178
179
|
yield from self.adb_device.sync.iter_content(remote_path)
|
|
179
|
-
|
|
180
|
+
|
|
181
|
+
def send_keys(self, text: str):
|
|
182
|
+
self.ud.send_keys(text)
|
|
183
|
+
|
|
184
|
+
def clear_text(self):
|
|
185
|
+
self.ud.clear_text()
|
|
180
186
|
|
|
181
187
|
|
|
182
188
|
def parse_xml(xml_data: str, wsize: WindowSize, display_id: Optional[int] = None) -> Node:
|
uiautodev/driver/base_driver.py
CHANGED
|
@@ -102,4 +102,11 @@ class BaseDriver(abc.ABC):
|
|
|
102
102
|
def open_app_file(self, package: str) -> Iterator[bytes]:
|
|
103
103
|
""" open app file """
|
|
104
104
|
raise NotImplementedError()
|
|
105
|
-
|
|
105
|
+
|
|
106
|
+
def send_keys(self, text: str):
|
|
107
|
+
""" send keys to device """
|
|
108
|
+
raise NotImplementedError()
|
|
109
|
+
|
|
110
|
+
def clear_text(self):
|
|
111
|
+
""" clear text input on device """
|
|
112
|
+
raise NotImplementedError()
|
uiautodev/driver/harmony.py
CHANGED
|
@@ -10,7 +10,7 @@ import tempfile
|
|
|
10
10
|
import time
|
|
11
11
|
import uuid
|
|
12
12
|
from pathlib import Path
|
|
13
|
-
from typing import List, Optional, Tuple, Union, final
|
|
13
|
+
from typing import List, Optional, Tuple, Union, final, Dict
|
|
14
14
|
|
|
15
15
|
from PIL import Image
|
|
16
16
|
|
|
@@ -31,6 +31,7 @@ def run_command(command: str, timeout: int = 60) -> str:
|
|
|
31
31
|
capture_output=True,
|
|
32
32
|
timeout=timeout,
|
|
33
33
|
text=True,
|
|
34
|
+
errors='ignore',
|
|
34
35
|
input='' # this avoid stdout: "FreeChannelContinue handle->data is nullptr"
|
|
35
36
|
)
|
|
36
37
|
# the hdc shell stderr is (不仅没啥用,还没办法去掉)
|
|
@@ -50,10 +51,10 @@ class HDC:
|
|
|
50
51
|
def __init__(self):
|
|
51
52
|
self.hdc = 'hdc'
|
|
52
53
|
self.tmpdir = tempfile.TemporaryDirectory()
|
|
53
|
-
|
|
54
|
+
|
|
54
55
|
def __del__(self):
|
|
55
56
|
self.tmpdir.cleanup()
|
|
56
|
-
|
|
57
|
+
|
|
57
58
|
def list_device(self) -> List[str]:
|
|
58
59
|
command = f"{self.hdc} list targets"
|
|
59
60
|
result = run_command(command)
|
|
@@ -65,15 +66,48 @@ class HDC:
|
|
|
65
66
|
return devices
|
|
66
67
|
else:
|
|
67
68
|
return []
|
|
68
|
-
|
|
69
|
+
|
|
69
70
|
def shell(self, serial: str, command: str) -> str:
|
|
70
71
|
command = f"{self.hdc} -t {serial} shell \"{command}\""
|
|
71
72
|
result = run_command(command)
|
|
72
73
|
return result.strip()
|
|
73
|
-
|
|
74
|
+
|
|
75
|
+
def __split_text(self, text: str) -> str:
|
|
76
|
+
return text.split("\n")[0].strip() if text else ""
|
|
77
|
+
|
|
74
78
|
def get_model(self, serial: str) -> str:
|
|
75
79
|
return self.shell(serial, "param get const.product.model")
|
|
76
|
-
|
|
80
|
+
|
|
81
|
+
def get_name(self, serial: str) -> str:
|
|
82
|
+
data = self.shell(serial, "param get const.product.name")
|
|
83
|
+
return self.__split_text(data)
|
|
84
|
+
|
|
85
|
+
def wlan_ip(self, serial: str) -> str:
|
|
86
|
+
data = self.shell(serial, "ifconfig")
|
|
87
|
+
if not data or "not found" in data.lower() or "error" in data.lower():
|
|
88
|
+
logger.warning(f"ifconfig command failed or returned error for serial {serial}: {data!r}")
|
|
89
|
+
return ""
|
|
90
|
+
# Try multiple patterns for IP address
|
|
91
|
+
matches = re.findall(r'inet addr:(?!127)(\d+\.\d+\.\d+\.\d+)', data)
|
|
92
|
+
if not matches:
|
|
93
|
+
matches = re.findall(r'inet (?!127)(\d+\.\d+\.\d+\.\d+)', data)
|
|
94
|
+
if matches:
|
|
95
|
+
return matches[0]
|
|
96
|
+
logger.warning(f"No valid IP address found in ifconfig output for serial {serial}: {data!r}")
|
|
97
|
+
return ""
|
|
98
|
+
|
|
99
|
+
def sdk_version(self, serial: str) -> str:
|
|
100
|
+
data = self.shell(serial, "param get const.ohos.apiversion")
|
|
101
|
+
return self.__split_text(data)
|
|
102
|
+
|
|
103
|
+
def sys_version(self, serial: str) -> str:
|
|
104
|
+
data = self.shell(serial, "param get const.product.software.version")
|
|
105
|
+
return self.__split_text(data)
|
|
106
|
+
|
|
107
|
+
def brand(self, serial: str) -> str:
|
|
108
|
+
data = self.shell(serial, "param get const.product.brand")
|
|
109
|
+
return self.__split_text(data)
|
|
110
|
+
|
|
77
111
|
def pull(self, serial: str, remote: StrOrPath, local: StrOrPath):
|
|
78
112
|
if isinstance(remote, Path):
|
|
79
113
|
remote = remote.as_posix()
|
|
@@ -81,13 +115,13 @@ class HDC:
|
|
|
81
115
|
output = run_command(command)
|
|
82
116
|
if not os.path.exists(local):
|
|
83
117
|
raise HDCError(f"device file: {remote} not found", output)
|
|
84
|
-
|
|
118
|
+
|
|
85
119
|
def push(self, serial: str, local: StrOrPath, remote: StrOrPath) -> str:
|
|
86
120
|
if isinstance(remote, Path):
|
|
87
121
|
remote = remote.as_posix()
|
|
88
122
|
command = f"{self.hdc} -t {serial} file send {local} {remote}"
|
|
89
123
|
return run_command(command)
|
|
90
|
-
|
|
124
|
+
|
|
91
125
|
def screenshot(self, serial: str) -> Image.Image:
|
|
92
126
|
device_path = f'/data/local/tmp/screenshot-{int(time.time()*1000)}.png'
|
|
93
127
|
self.shell(serial, f"uitest screenCap -p {device_path}")
|
|
@@ -116,7 +150,7 @@ class HDC:
|
|
|
116
150
|
raise HDCError(f"failed to dump layout: {output}")
|
|
117
151
|
finally:
|
|
118
152
|
self.shell(serial, f"rm {remote_path}")
|
|
119
|
-
|
|
153
|
+
|
|
120
154
|
|
|
121
155
|
class HarmonyDriver(BaseDriver):
|
|
122
156
|
def __init__(self, hdc: HDC, serial: str):
|
|
@@ -164,6 +198,112 @@ class HarmonyDriver(BaseDriver):
|
|
|
164
198
|
else:
|
|
165
199
|
return None
|
|
166
200
|
|
|
201
|
+
def get_app_info(self, package_name: str) -> Dict:
|
|
202
|
+
"""
|
|
203
|
+
Get detailed information about a specific application.
|
|
204
|
+
|
|
205
|
+
Args:
|
|
206
|
+
package_name (str): The package name of the application to retrieve information for.
|
|
207
|
+
|
|
208
|
+
Returns:
|
|
209
|
+
Dict: A dictionary containing the application information. If an error occurs during parsing,
|
|
210
|
+
an empty dictionary is returned.
|
|
211
|
+
"""
|
|
212
|
+
app_info = {}
|
|
213
|
+
data = self.hdc.shell(self.serial, f"bm dump -n {package_name}")
|
|
214
|
+
output = data
|
|
215
|
+
try:
|
|
216
|
+
json_start = output.find("{")
|
|
217
|
+
json_end = output.rfind("}") + 1
|
|
218
|
+
json_output = output[json_start:json_end]
|
|
219
|
+
|
|
220
|
+
app_info = json.loads(json_output)
|
|
221
|
+
except Exception as e:
|
|
222
|
+
logger.error(f"An error occurred: {e}")
|
|
223
|
+
return app_info
|
|
224
|
+
|
|
225
|
+
def get_app_abilities(self, package_name: str) -> List[Dict]:
|
|
226
|
+
"""
|
|
227
|
+
Get the abilities of an application.
|
|
228
|
+
|
|
229
|
+
Args:
|
|
230
|
+
package_name (str): The package name of the application.
|
|
231
|
+
|
|
232
|
+
Returns:
|
|
233
|
+
List[Dict]: A list of dictionaries containing the abilities of the application.
|
|
234
|
+
"""
|
|
235
|
+
result = []
|
|
236
|
+
app_info = self.get_app_info(package_name)
|
|
237
|
+
hap_module_infos = app_info.get("hapModuleInfos")
|
|
238
|
+
main_entry = app_info.get("mainEntry")
|
|
239
|
+
for hap_module_info in hap_module_infos:
|
|
240
|
+
# 尝试读取moduleInfo
|
|
241
|
+
try:
|
|
242
|
+
ability_infos = hap_module_info.get("abilityInfos")
|
|
243
|
+
module_main = hap_module_info["mainAbility"]
|
|
244
|
+
except Exception as e:
|
|
245
|
+
logger.warning(f"Fail to parse moduleInfo item, {repr(e)}")
|
|
246
|
+
continue
|
|
247
|
+
# 尝试读取abilityInfo
|
|
248
|
+
for ability_info in ability_infos:
|
|
249
|
+
try:
|
|
250
|
+
is_launcher_ability = False
|
|
251
|
+
skills = ability_info['skills']
|
|
252
|
+
if len(skills) > 0 and "action.system.home" in skills[0]["actions"]:
|
|
253
|
+
is_launcher_ability = True
|
|
254
|
+
icon_ability_info = {
|
|
255
|
+
"name": ability_info["name"],
|
|
256
|
+
"moduleName": ability_info["moduleName"],
|
|
257
|
+
"moduleMainAbility": module_main,
|
|
258
|
+
"mainModule": main_entry,
|
|
259
|
+
"isLauncherAbility": is_launcher_ability
|
|
260
|
+
}
|
|
261
|
+
result.append(icon_ability_info)
|
|
262
|
+
except Exception as e:
|
|
263
|
+
logger.warning(f"Fail to parse ability_info item, {repr(e)}")
|
|
264
|
+
continue
|
|
265
|
+
logger.debug(f"all abilities: {result}")
|
|
266
|
+
return result
|
|
267
|
+
|
|
268
|
+
def get_app_main_ability(self, package_name: str) -> Dict:
|
|
269
|
+
"""
|
|
270
|
+
Get the main ability of an application.
|
|
271
|
+
|
|
272
|
+
Args:
|
|
273
|
+
package_name (str): The package name of the application to retrieve information for.
|
|
274
|
+
|
|
275
|
+
Returns:
|
|
276
|
+
Dict: A dictionary containing the main ability of the application.
|
|
277
|
+
|
|
278
|
+
"""
|
|
279
|
+
if not (abilities := self.get_app_abilities(package_name)):
|
|
280
|
+
return {}
|
|
281
|
+
for item in abilities:
|
|
282
|
+
score = 0
|
|
283
|
+
if (name := item["name"]) and name == item["moduleMainAbility"]:
|
|
284
|
+
score += 1
|
|
285
|
+
if (module_name := item["moduleName"]) and module_name == item["mainModule"]:
|
|
286
|
+
score += 1
|
|
287
|
+
item["score"] = score
|
|
288
|
+
abilities.sort(key=lambda x: (not x["isLauncherAbility"], -x["score"]))
|
|
289
|
+
logger.debug(f"main ability: {abilities[0]}")
|
|
290
|
+
return abilities[0]
|
|
291
|
+
|
|
292
|
+
def app_launch(self, package: str, page_name: Optional[str] = None):
|
|
293
|
+
"""
|
|
294
|
+
Start an application on the device.
|
|
295
|
+
If the `page_name` is empty, it will retrieve the main ability using `get_app_main_ability`.
|
|
296
|
+
Args:
|
|
297
|
+
package (str): The package name of the application.
|
|
298
|
+
page_name (Optional[str]): Ability Name within the application to start. If not provided, the main ability will be used.
|
|
299
|
+
"""
|
|
300
|
+
if not page_name:
|
|
301
|
+
page_name = self.get_app_main_ability(package).get('name', 'MainAbility')
|
|
302
|
+
self.shell(f"aa start -a {page_name} -b {package}")
|
|
303
|
+
|
|
304
|
+
def app_terminate(self, package: str):
|
|
305
|
+
self.shell(f"aa force-stop {package}")
|
|
306
|
+
|
|
167
307
|
def shell(self, command: str) -> ShellResponse:
|
|
168
308
|
result = self.hdc.shell(self.serial, command)
|
|
169
309
|
return ShellResponse(output=result)
|
uiautodev/model.py
CHANGED
uiautodev/provider.py
CHANGED
|
@@ -46,12 +46,18 @@ class AndroidProvider(BaseProvider):
|
|
|
46
46
|
def list_devices(self) -> list[DeviceInfo]:
|
|
47
47
|
adb = adbutils.AdbClient()
|
|
48
48
|
ret: list[DeviceInfo] = []
|
|
49
|
-
for d in adb.list():
|
|
49
|
+
for d in adb.list(extended=True):
|
|
50
50
|
if d.state != "device":
|
|
51
51
|
ret.append(DeviceInfo(serial=d.serial, status=d.state, enabled=False))
|
|
52
52
|
else:
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
ret.append(DeviceInfo(
|
|
54
|
+
serial=d.serial,
|
|
55
|
+
status=d.state,
|
|
56
|
+
name=d.tags.get('device', ''),
|
|
57
|
+
model=d.tags.get('model', ''),
|
|
58
|
+
product=d.tags.get('product', ''),
|
|
59
|
+
enabled=True
|
|
60
|
+
))
|
|
55
61
|
return ret
|
|
56
62
|
|
|
57
63
|
@lru_cache
|
|
@@ -76,7 +82,7 @@ class HarmonyProvider(BaseProvider):
|
|
|
76
82
|
|
|
77
83
|
def list_devices(self) -> list[DeviceInfo]:
|
|
78
84
|
devices = self.hdc.list_device()
|
|
79
|
-
return [DeviceInfo(serial=d, model=self.hdc.get_model(d), name=self.hdc.
|
|
85
|
+
return [DeviceInfo(serial=d, model=self.hdc.get_model(d), name=self.hdc.get_name(d)) for d in devices]
|
|
80
86
|
|
|
81
87
|
@lru_cache
|
|
82
88
|
def get_device_driver(self, serial: str) -> HarmonyDriver:
|
uiautodev/router/proxy.py
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
+
import logging
|
|
2
3
|
|
|
3
4
|
import httpx
|
|
4
5
|
import websockets
|
|
5
6
|
from fastapi import APIRouter, HTTPException, Request, WebSocket, WebSocketDisconnect
|
|
6
7
|
from fastapi.responses import Response
|
|
7
|
-
import logging
|
|
8
|
-
|
|
9
8
|
|
|
10
9
|
logger = logging.getLogger(__name__)
|
|
11
10
|
router = APIRouter()
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: uiautodev
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.11.1
|
|
4
4
|
Summary: Mobile UI Automation, include UI hierarchy inspector, script recorder
|
|
5
5
|
License: MIT
|
|
6
|
+
License-File: LICENSE
|
|
6
7
|
Author: codeskyblue
|
|
7
8
|
Author-email: codeskyblue@gmail.com
|
|
8
9
|
Requires-Python: >=3.8,<4.0
|
|
@@ -14,6 +15,7 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
14
15
|
Classifier: Programming Language :: Python :: 3.11
|
|
15
16
|
Classifier: Programming Language :: Python :: 3.12
|
|
16
17
|
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
17
19
|
Requires-Dist: Pillow
|
|
18
20
|
Requires-Dist: adbutils (>=2.8.10,<3)
|
|
19
21
|
Requires-Dist: click (>=8.1.7,<9.0.0)
|
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
uiautodev/__init__.py,sha256=
|
|
1
|
+
uiautodev/__init__.py,sha256=Ya4pFQpAHk2du5GJjKUOuuJd0dK2UYSmEaajmyAkLDU,165
|
|
2
2
|
uiautodev/__main__.py,sha256=0WZHyHW-M7FG5RexANNoIB5pkCX8xwQbTnmaOA9Y1kg,176
|
|
3
3
|
uiautodev/app.py,sha256=K3u6WCobH3Q5HmXvrZff0Cq44L0j1J4eBVhSxnSNKiE,6600
|
|
4
4
|
uiautodev/appium_proxy.py,sha256=yMzPnIDo50hYSaq0g5bXUpgRrFa_849wNa2o7ZpxGNY,1773
|
|
5
5
|
uiautodev/binaries/scrcpy_server.jar,sha256=ojxWWfNsJg8QXAItJ7yz6v_6JgcOe6qe2mbQE3ehrbo,71200
|
|
6
6
|
uiautodev/case.py,sha256=Jk2_5X2F-XIPnGuYTCqOVQiwwchwOhF7uKK5oKv5shg,3919
|
|
7
7
|
uiautodev/cli.py,sha256=FL9PBGo0UTttRhGW7THrWqNn2ujsA-728y0O46h2Qjk,6240
|
|
8
|
-
uiautodev/command_proxy.py,sha256=
|
|
9
|
-
uiautodev/command_types.py,sha256=
|
|
8
|
+
uiautodev/command_proxy.py,sha256=Od8jSVDOUJWWcni-Jq8_IHd34VbfWECi0mL1wl86lIo,5446
|
|
9
|
+
uiautodev/command_types.py,sha256=wZa-yQpxzQO79iFMHShJELuZgYJm-yweG-TeSBvzBvs,1867
|
|
10
10
|
uiautodev/common.py,sha256=1A0kXfxVrp_i5mc_aRjuqSDWFFZ7DwZR9qpRLu2GMMg,1488
|
|
11
|
-
uiautodev/driver/android.py,sha256=
|
|
11
|
+
uiautodev/driver/android.py,sha256=k4Mjq2gmsokwCUN68VGCuhbl7HHEEyeowuTzQFXjg30,8181
|
|
12
12
|
uiautodev/driver/appium.py,sha256=U3TGpOXmu3tEa3E1ttTFoXehOfFyjavJQ3XA4CtqeBE,5308
|
|
13
|
-
uiautodev/driver/base_driver.py,sha256=
|
|
14
|
-
uiautodev/driver/harmony.py,sha256=
|
|
13
|
+
uiautodev/driver/base_driver.py,sha256=6MBNfEg_CtS4ed90SaSGbdqmf-JNaypqiBNaZBRKeAo,3027
|
|
14
|
+
uiautodev/driver/harmony.py,sha256=L3Ggd1PNlv6cPDbaaf8BA7OqtUp-G5g4Tk9cvhpnakw,13777
|
|
15
15
|
uiautodev/driver/ios.py,sha256=EOi9k-Y4qQS6Htdz_ycBf5jYCnOkruB-mR0Sc8J-coo,4204
|
|
16
16
|
uiautodev/driver/mock.py,sha256=0VtxBkZRMbHiQGHjqm8Ih2Ld6baXiVxX8yUTwWJQlnE,2422
|
|
17
17
|
uiautodev/driver/testdata/layout.json,sha256=0z9jGJteXuGwkOhO_iINYPoDp1kCq-EaQds_iZkmiPQ,276538
|
|
18
18
|
uiautodev/driver/udt/appium-uiautomator2-v5.12.4-light.apk,sha256=cKUVKpqEiGRXODeqpwzVWllyjdSLyowFm94a6jDTvhI,3675062
|
|
19
19
|
uiautodev/driver/udt/udt.py,sha256=p6opbUtYxEGTINIX83F6m2CtzB42iSSBYRv1SjXCEFg,8351
|
|
20
20
|
uiautodev/exceptions.py,sha256=lQI14vshN5qExVE23g2aw5i2fkdQFfLCJj2dO6kVLZw,591
|
|
21
|
-
uiautodev/model.py,sha256=
|
|
22
|
-
uiautodev/provider.py,sha256=
|
|
21
|
+
uiautodev/model.py,sha256=hrqezVn1XFXHyajFxxmoiuGDZoYAodfitWMBzrYgziA,1071
|
|
22
|
+
uiautodev/provider.py,sha256=f3fh9IbgTRlJmxZXXTNNZbHgHBIqfQCIBKIPz_BOOng,3054
|
|
23
23
|
uiautodev/remote/android_input.py,sha256=r9y2SxnDw0GhN44emL-2Nz0UasaVaVtzh53hd-LJ710,2445
|
|
24
24
|
uiautodev/remote/harmony_mjpeg.py,sha256=-J2sVfPSTuqN80BelisvwaZAimWxIk9SIzD010q3h7c,8287
|
|
25
25
|
uiautodev/remote/keycode.py,sha256=RHSJVfcNY2pelQd7_tcE6T0j3n8CKBkiku7A2AJZUpk,8097
|
|
@@ -27,15 +27,15 @@ uiautodev/remote/scrcpy.py,sha256=JNSwC35f4os-IQW4ixx7ky9clpqRWvA8X_obUkwuOh8,74
|
|
|
27
27
|
uiautodev/remote/touch_controller.py,sha256=dYl5XTLaYEyZiNJmKwHQpw9QhPSkN3iUetJSaiQJBHg,4255
|
|
28
28
|
uiautodev/router/android.py,sha256=xwzaZduMRJsyml-7eZjNtQMg_c22ZpFAq6TErc_-tlA,1358
|
|
29
29
|
uiautodev/router/device.py,sha256=iNJUexRLUmgGT_n1UgWybX8PvRSDinpoUpvKX-NZi10,4298
|
|
30
|
-
uiautodev/router/proxy.py,sha256=
|
|
30
|
+
uiautodev/router/proxy.py,sha256=Kp_w1KfbKMp9RTERtLAQjn1_U3tUSC4ZWAliHeaJuug,2006
|
|
31
31
|
uiautodev/router/xml.py,sha256=MKVLhjMBqE4qbEraQxvdrVp_OBnylEL9Wti5lnmBDk4,891
|
|
32
32
|
uiautodev/static/demo.html,sha256=qC7qUZP5Af9T3V5EuFGbovzv8mArwiGMWsX_vcs_Bt0,1240
|
|
33
33
|
uiautodev/utils/common.py,sha256=L1qBBBS6jRgkXlGy5o6Xafo49auLXKRWyX9x8U_IKjc,4821
|
|
34
34
|
uiautodev/utils/envutils.py,sha256=Clyt2Hz9PXpK_fT0yWbMmixXyGvCaJO3LAgamM7aUVc,197
|
|
35
35
|
uiautodev/utils/exceptions.py,sha256=lL_G_E41KWvfXnl32-E4Vgr3_HyTboxq_EwzdQMuvK4,637
|
|
36
36
|
uiautodev/utils/usbmux.py,sha256=LYupLDn7U4KFKhYQJrmIroS-3040gqZQVDRDB_FNDJM,17386
|
|
37
|
-
uiautodev-0.
|
|
38
|
-
uiautodev-0.
|
|
39
|
-
uiautodev-0.
|
|
40
|
-
uiautodev-0.
|
|
41
|
-
uiautodev-0.
|
|
37
|
+
uiautodev-0.11.1.dist-info/METADATA,sha256=omxcGuHP5rjLAtT0JbnhdkCq58majJ3m726u4p25t9U,2628
|
|
38
|
+
uiautodev-0.11.1.dist-info/WHEEL,sha256=M5asmiAlL6HEcOq52Yi5mmk9KmTVjY2RDPtO4p9DMrc,88
|
|
39
|
+
uiautodev-0.11.1.dist-info/entry_points.txt,sha256=zBY8GgseYAAzPFA5Cf4rCCS9ivdyWsNxMVVYIaGAHJU,88
|
|
40
|
+
uiautodev-0.11.1.dist-info/licenses/LICENSE,sha256=RyeW676gBYO7AVVP2zQgfEx5rPSt46vR47xXZe7TlX4,1068
|
|
41
|
+
uiautodev-0.11.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|