uiautodev 0.3.3__py3-none-any.whl → 0.3.5__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/app.py CHANGED
@@ -17,6 +17,7 @@ from fastapi.responses import FileResponse, RedirectResponse
17
17
  from pydantic import BaseModel
18
18
 
19
19
  from uiautodev import __version__
20
+ from uiautodev.common import get_webpage_url
20
21
  from uiautodev.provider import AndroidProvider, IOSProvider, MockProvider
21
22
  from uiautodev.router.device import make_router
22
23
  from uiautodev.router.xml import router as xml_router
@@ -89,4 +90,6 @@ def demo() -> str:
89
90
  @app.get("/")
90
91
  def index_redirect():
91
92
  """ redirect to official homepage """
92
- return RedirectResponse("https://uiauto.dev")
93
+ url = get_webpage_url()
94
+ logger.debug("redirect to %s", url)
95
+ return RedirectResponse(url)
uiautodev/cli.py CHANGED
@@ -8,6 +8,7 @@ from __future__ import annotations
8
8
 
9
9
  import logging
10
10
  import platform
11
+ import subprocess
11
12
  import sys
12
13
  import threading
13
14
  import time
@@ -20,16 +21,22 @@ import uvicorn
20
21
 
21
22
  from uiautodev import __version__, command_proxy
22
23
  from uiautodev.command_types import Command
24
+ from uiautodev.common import get_webpage_url
23
25
  from uiautodev.provider import AndroidProvider, BaseProvider, IOSProvider
24
26
  from uiautodev.utils.common import convert_params_to_model, print_json
25
27
 
26
28
  logger = logging.getLogger(__name__)
27
29
 
30
+ CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help'])
28
31
 
29
- @click.group()
32
+ @click.group(context_settings=CONTEXT_SETTINGS)
30
33
  @click.option("--verbose", "-v", is_flag=True, default=False, help="verbose mode")
31
34
  def cli(verbose: bool):
32
35
  if verbose:
36
+ # try to enable logger is not very easy
37
+ # you have to setup logHandler(logFormatter) for the root logger
38
+ # and set all children logger to DEBUG
39
+ # that's why it is not easy to use it with logging
33
40
  root_logger = logging.getLogger(__name__.split(".")[0])
34
41
  root_logger.setLevel(logging.DEBUG)
35
42
 
@@ -40,6 +47,12 @@ def cli(verbose: bool):
40
47
  console_handler.setFormatter(formatter)
41
48
 
42
49
  root_logger.addHandler(console_handler)
50
+
51
+ # set all children logger to DEBUG
52
+ for k in root_logger.manager.loggerDict.keys():
53
+ if k.startswith(root_logger.name+"."):
54
+ logging.getLogger(k).setLevel(logging.DEBUG)
55
+
43
56
  logger.debug("Verbose mode enabled")
44
57
 
45
58
 
@@ -110,15 +123,22 @@ def appium(command: Command, params: list[str] = None):
110
123
 
111
124
  @cli.command('version')
112
125
  def print_version():
126
+ """ Print version """
113
127
  print(__version__)
114
128
 
115
129
 
116
- @cli.command(help="start uiauto.dev local server [default]")
130
+ @cli.command('self-update')
131
+ def self_update():
132
+ """ Update uiautodev to latest version """
133
+ subprocess.run([sys.executable, '-m', "pip", "install", "--upgrade", "uiautodev"])
134
+
135
+
136
+ @cli.command(help="start uiauto.dev local server [Default]")
117
137
  @click.option("--port", default=20242, help="port number", show_default=True)
118
138
  @click.option("--host", default="127.0.0.1", help="host", show_default=True)
119
139
  @click.option("--reload", is_flag=True, default=False, help="auto reload, dev only")
120
140
  @click.option("-f", "--force", is_flag=True, default=False, help="shutdown alrealy runningserver")
121
- @click.option("--no-browser", is_flag=True, default=False, help="do not open browser")
141
+ @click.option("-s", "--no-browser", is_flag=True, default=False, help="silent mode, do not open browser")
122
142
  def server(port: int, host: str, reload: bool, force: bool, no_browser: bool):
123
143
  logger.info("version: %s", __version__)
124
144
  if force:
@@ -147,7 +167,7 @@ def open_browser_when_server_start(server_url: str):
147
167
  except Exception as e:
148
168
  time.sleep(0.5)
149
169
  import webbrowser
150
- web_url = "https://uiauto.dev"
170
+ web_url = get_webpage_url()
151
171
  logger.info("open browser: %s", web_url)
152
172
  webbrowser.open(web_url)
153
173
 
uiautodev/common.py ADDED
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+
4
+ """Created on Thu May 09 2024 11:33:17 by codeskyblue
5
+ """
6
+
7
+
8
+ import locale
9
+
10
+
11
+ def is_chinese_language() -> bool:
12
+ language_code, _ = locale.getdefaultlocale()
13
+
14
+ # Check if the language code starts with 'zh' (Chinese)
15
+ if language_code and language_code.startswith('zh'):
16
+ return True
17
+ else:
18
+ return False
19
+
20
+
21
+ def get_webpage_url() -> str:
22
+ web_url = "https://uiauto.dev"
23
+ if is_chinese_language():
24
+ web_url = "https://uiauto.devsleep.com"
25
+ return web_url
@@ -7,7 +7,6 @@
7
7
  import json
8
8
  import logging
9
9
  import re
10
- import socket
11
10
  import time
12
11
  from functools import cached_property, partial
13
12
  from typing import List, Tuple
@@ -15,6 +14,7 @@ from xml.etree import ElementTree
15
14
 
16
15
  import adbutils
17
16
  import requests
17
+ import uiautomator2 as u2
18
18
  from PIL import Image
19
19
 
20
20
  from uiautodev.command_types import CurrentAppResponse
@@ -34,24 +34,25 @@ class AndroidDriver(BaseDriver):
34
34
  self._get_u2_hierarchy,
35
35
  self._get_appium_hierarchy,
36
36
  self._get_udt_dump_hierarchy,
37
- self.device.dump_hierarchy,
38
- self._get_u2_lib_hierarchy,
39
37
  ]
40
38
 
41
39
  @cached_property
42
40
  def udt(self) -> UDT:
43
41
  return UDT(self.device)
42
+
43
+ @cached_property
44
+ def ud(self) -> u2.Device:
45
+ return u2.connect_usb(self.serial)
44
46
 
45
47
  def screenshot(self, id: int) -> Image.Image:
46
- # TODO: support multi-display
47
- if id > 0:
48
- raise ValueError("multi-display is not supported yet")
49
48
  try:
50
- img = self.device.screenshot()
49
+ img = self.device.screenshot(display_id=id)
51
50
  return img.convert("RGB")
52
51
  except adbutils.AdbError as e:
53
52
  logger.warning("screenshot error: %s", str(e))
54
- return self.udt.screenshot()
53
+ if id > 0:
54
+ raise AndroidDriverException("multi-display is not supported yet for uiautomator2")
55
+ return self.ud.screenshot()
55
56
 
56
57
  def shell(self, command: str) -> ShellResponse:
57
58
  try:
@@ -93,20 +94,11 @@ class AndroidDriver(BaseDriver):
93
94
  self._try_dump_list.remove(dump_func)
94
95
  self._try_dump_list.insert(0, dump_func)
95
96
  return result
96
- except (
97
- requests.RequestException,
98
- AndroidDriverException,
99
- UDTError,
100
- adbutils.AdbError,
101
- socket.timeout,
102
- ) as e:
103
- logger.warning("dump error: %s", e)
104
97
  except Exception as e:
105
98
  logger.exception("unexpected dump error: %s", e)
106
99
  raise AndroidDriverException("Failed to dump hierarchy")
107
100
 
108
101
  def _get_u2_hierarchy(self) -> str:
109
- import uiautomator2 as u2
110
102
  d = u2.connect_usb(self.serial)
111
103
  return d.dump_hierarchy()
112
104
  # c = self.device.create_connection(adbutils.Network.TCP, 9008)
@@ -146,14 +138,6 @@ class AndroidDriver(BaseDriver):
146
138
 
147
139
  def _get_udt_dump_hierarchy(self) -> str:
148
140
  return self.udt.dump_hierarchy()
149
-
150
- def _get_u2_lib_hierarchy(self) -> str:
151
- try:
152
- import uiautomator2 as u2
153
- d = u2.connect_usb(self.serial)
154
- return d.dump_hierarchy()
155
- except ModuleNotFoundError:
156
- raise AndroidDriverException("uiautomator2 lib not installed")
157
141
 
158
142
  def tap(self, x: int, y: int):
159
143
  self.device.click(x, y)
@@ -6,20 +6,20 @@
6
6
 
7
7
 
8
8
  import atexit
9
- from base64 import b64decode
10
9
  import enum
11
10
  import io
12
11
  import json
13
12
  import logging
14
- from pprint import pprint
15
13
  import threading
16
14
  import time
15
+ from base64 import b64decode
17
16
  from pathlib import Path
17
+ from pprint import pprint
18
18
  from typing import Any, Optional
19
19
 
20
- from PIL import Image
21
20
  import adbutils
22
21
  import requests
22
+ from PIL import Image
23
23
  from pydantic import BaseModel
24
24
 
25
25
  """
@@ -5,6 +5,7 @@
5
5
  """
6
6
 
7
7
  import io
8
+ import logging
8
9
  from typing import Any, List
9
10
 
10
11
  from fastapi import APIRouter, Response
@@ -16,6 +17,8 @@ from uiautodev.model import DeviceInfo, Node, ShellResponse
16
17
  from uiautodev.provider import BaseProvider
17
18
 
18
19
 
20
+ logger = logging.getLogger(__name__)
21
+
19
22
  class AndroidShellPayload(BaseModel):
20
23
  command: str
21
24
 
@@ -31,6 +34,7 @@ def make_router(provider: BaseProvider) -> APIRouter:
31
34
  except NotImplementedError as e:
32
35
  return Response(content="list_devices not implemented", media_type="text/plain", status_code=501)
33
36
  except Exception as e:
37
+ logger.exception("list_devices failed")
34
38
  return Response(content=str(e), media_type="text/plain", status_code=500)
35
39
 
36
40
  @router.post("/{serial}/shell")
@@ -42,6 +46,7 @@ def make_router(provider: BaseProvider) -> APIRouter:
42
46
  except NotImplementedError as e:
43
47
  return Response(content="shell not implemented", media_type="text/plain", status_code=501)
44
48
  except Exception as e:
49
+ logger.exception("shell failed")
45
50
  return ShellResponse(output="", error=str(e))
46
51
 
47
52
  @router.get(
@@ -59,6 +64,7 @@ def make_router(provider: BaseProvider) -> APIRouter:
59
64
  image_bytes = buf.getvalue()
60
65
  return Response(content=image_bytes, media_type="image/jpeg")
61
66
  except Exception as e:
67
+ logger.exception("screenshot failed")
62
68
  return Response(content=str(e), media_type="text/plain", status_code=500)
63
69
 
64
70
  @router.get("/{serial}/hierarchy")
@@ -69,6 +75,7 @@ def make_router(provider: BaseProvider) -> APIRouter:
69
75
  xml_data, hierarchy = driver.dump_hierarchy()
70
76
  return hierarchy
71
77
  except Exception as e:
78
+ logger.exception("dump_hierarchy failed")
72
79
  return Response(content=str(e), media_type="text/plain", status_code=500)
73
80
 
74
81
  @router.post('/{serial}/command/tap')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: uiautodev
3
- Version: 0.3.3
3
+ Version: 0.3.5
4
4
  Summary: Mobile UI Automation, include UI hierarchy inspector, script recorder
5
5
  Home-page: https://uiauto.dev
6
6
  License: MIT
@@ -19,13 +19,15 @@ Requires-Dist: adbutils (>=2.6.0,<3.0.0)
19
19
  Requires-Dist: appium-python-client (>=4.0.0,<5.0.0) ; extra == "appium"
20
20
  Requires-Dist: click (>=8.1.7,<9.0.0)
21
21
  Requires-Dist: construct
22
- Requires-Dist: fastapi[all] (>=0.109.2,<0.110.0)
22
+ Requires-Dist: fastapi (>=0.111.0,<0.112.0)
23
23
  Requires-Dist: httpretty (>=1.1.4,<2.0.0)
24
+ Requires-Dist: httpx
24
25
  Requires-Dist: lxml
25
26
  Requires-Dist: pillow
27
+ Requires-Dist: poetry (>=1.8.2,<2.0.0)
26
28
  Requires-Dist: pygments (>=2)
27
- Requires-Dist: uiautomator2 (>=3.0.11,<4.0.0)
28
- Requires-Dist: uvicorn[standard] (>=0.27.1,<0.28.0)
29
+ Requires-Dist: uiautomator2 (>=2)
30
+ Requires-Dist: uvicorn[standard]
29
31
  Description-Content-Type: text/markdown
30
32
 
31
33
  # uiautodev
@@ -36,6 +38,32 @@ https://uiauto.dev
36
38
 
37
39
  UI Inspector for Android and iOS, help inspector element properties, and auto generate XPath, script.
38
40
 
41
+ # Install
42
+ ```bash
43
+ pip install uiautodev
44
+ ```
45
+
46
+ # Usage
47
+ ```bash
48
+ Usage: uiauto.dev [OPTIONS] COMMAND [ARGS]...
49
+
50
+ Options:
51
+ -v, --verbose verbose mode
52
+ -h, --help Show this message and exit.
53
+
54
+ Commands:
55
+ android COMMAND: tap, tapElement, installApp, currentApp,...
56
+ appium COMMAND: tap, tapElement, installApp, currentApp,...
57
+ ios COMMAND: tap, tapElement, installApp, currentApp,...
58
+ self-update Update uiautodev to latest version
59
+ server start uiauto.dev local server [Default]
60
+ version Print version
61
+ ```
62
+
63
+ ```bash
64
+ # run local server and open browser
65
+ uiauto.dev
66
+ ```
39
67
 
40
68
  # DEVELOP
41
69
  ```bash
@@ -1,29 +1,30 @@
1
1
  uiautodev/__init__.py,sha256=UBIzJoRjsFADqlrH5juQL4DSd0i3-rLhUtydeEluVEU,267
2
2
  uiautodev/__main__.py,sha256=0WZHyHW-M7FG5RexANNoIB5pkCX8xwQbTnmaOA9Y1kg,176
3
- uiautodev/app.py,sha256=Vk423jZqWJLKC9pZPaPH7a2UJVQ-LPx8HAvjaiXhyfA,2395
3
+ uiautodev/app.py,sha256=arc4dNclhUTw9x4QI0ZBE4_6FEI2RNOFF41pvHXLql8,2491
4
4
  uiautodev/appium_proxy.py,sha256=yMzPnIDo50hYSaq0g5bXUpgRrFa_849wNa2o7ZpxGNY,1773
5
5
  uiautodev/case.py,sha256=Jk2_5X2F-XIPnGuYTCqOVQiwwchwOhF7uKK5oKv5shg,3919
6
- uiautodev/cli.py,sha256=9_-jrbHR1ohtE7WNBXlHWO4V_RFJZajo70PSJfMX1tY,5405
6
+ uiautodev/cli.py,sha256=VBs5wDfmdBIyQQ8Nda0ACe84RRIAd8KRttrjAxm9YJc,6234
7
7
  uiautodev/command_proxy.py,sha256=eexXUwd4kt1gE3ab8QbSyUXd6zlghv6ize3NfvzeboE,4562
8
8
  uiautodev/command_types.py,sha256=d2s0GPLHCwr8QRMsPS8yrbr5irLUZLYBxLP4IifjSr8,1587
9
- uiautodev/driver/android.py,sha256=UxpxBPCX26z-slJWKZ-XbpXQsq_siUJVnV00UZ1CI3I,7596
9
+ uiautodev/common.py,sha256=t1jmG7S0LVXAigtg86J3vM2XXf1xYPfDV_HwSwyl3OI,552
10
+ uiautodev/driver/android.py,sha256=dks1AumgypQCoxkv62B0dlArNS0dGM69xbx-6C30jVc,7043
10
11
  uiautodev/driver/appium.py,sha256=U3TGpOXmu3tEa3E1ttTFoXehOfFyjavJQ3XA4CtqeBE,5308
11
12
  uiautodev/driver/base_driver.py,sha256=8CJrvulNzSZWrfBs8OBv2lTymsw-b3OyxOT8RxtkIyU,2048
12
13
  uiautodev/driver/ios.py,sha256=ymZKk2pKHPhKXX0Y-WLHwATHDLiXjnP0KeiByxU4Rpc,4353
13
14
  uiautodev/driver/mock.py,sha256=0VtxBkZRMbHiQGHjqm8Ih2Ld6baXiVxX8yUTwWJQlnE,2422
14
15
  uiautodev/driver/udt/appium-uiautomator2-v5.12.4-light.apk,sha256=cKUVKpqEiGRXODeqpwzVWllyjdSLyowFm94a6jDTvhI,3675062
15
- uiautodev/driver/udt/udt.py,sha256=Jys_EIfOks_Yx9BiX6crE8mTpijSlKN4blB27HdjHk4,8351
16
+ uiautodev/driver/udt/udt.py,sha256=p6opbUtYxEGTINIX83F6m2CtzB42iSSBYRv1SjXCEFg,8351
16
17
  uiautodev/exceptions.py,sha256=TuRD5SWQk5N2_KjrcDuXG_p84LBhLa2QEEXyFNFm0yQ,465
17
18
  uiautodev/model.py,sha256=0dD0PY8vBfgA9_GsEnNqM3TcNvNL_PUpTrHUc_BADKs,717
18
19
  uiautodev/provider.py,sha256=HDD_Jj-cJVfBceunzCYU9zJvGVya7Jd35GG9h85BY-0,2370
19
- uiautodev/router/device.py,sha256=etRUWm6XUfvyPDZlqdrr3395emzWQxNjkdnUq6P9JQs,3862
20
+ uiautodev/router/device.py,sha256=ZeXaYqeGcyH-_ehXfLsGAjGmW9gcL8KCoOs78c3ePNI,4116
20
21
  uiautodev/router/xml.py,sha256=MKVLhjMBqE4qbEraQxvdrVp_OBnylEL9Wti5lnmBDk4,891
21
22
  uiautodev/static/demo.html,sha256=qC7qUZP5Af9T3V5EuFGbovzv8mArwiGMWsX_vcs_Bt0,1240
22
23
  uiautodev/utils/common.py,sha256=HuXJvipkg1QQg6vCD7OxH6JQtqbSVbXNzI1X2OVcEcU,4785
23
24
  uiautodev/utils/exceptions.py,sha256=lL_G_E41KWvfXnl32-E4Vgr3_HyTboxq_EwzdQMuvK4,637
24
25
  uiautodev/utils/usbmux.py,sha256=LYupLDn7U4KFKhYQJrmIroS-3040gqZQVDRDB_FNDJM,17386
25
- uiautodev-0.3.3.dist-info/LICENSE,sha256=RyeW676gBYO7AVVP2zQgfEx5rPSt46vR47xXZe7TlX4,1068
26
- uiautodev-0.3.3.dist-info/METADATA,sha256=dE2gb2W7Gh2iJifgCM2PNmPRaKi2b18nPv89jpA4R7o,1700
27
- uiautodev-0.3.3.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
28
- uiautodev-0.3.3.dist-info/entry_points.txt,sha256=zBY8GgseYAAzPFA5Cf4rCCS9ivdyWsNxMVVYIaGAHJU,88
29
- uiautodev-0.3.3.dist-info/RECORD,,
26
+ uiautodev-0.3.5.dist-info/LICENSE,sha256=RyeW676gBYO7AVVP2zQgfEx5rPSt46vR47xXZe7TlX4,1068
27
+ uiautodev-0.3.5.dist-info/METADATA,sha256=-_etyW-6h0pVWBeqQpYUbxbRSq7rRgY7CA3l2-ryy_c,2329
28
+ uiautodev-0.3.5.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
29
+ uiautodev-0.3.5.dist-info/entry_points.txt,sha256=zBY8GgseYAAzPFA5Cf4rCCS9ivdyWsNxMVVYIaGAHJU,88
30
+ uiautodev-0.3.5.dist-info/RECORD,,