From 60a1e433286c549a49c28de58dbae7a3cb759269 Mon Sep 17 00:00:00 2001 From: codeskyblue Date: Fri, 26 Apr 2024 18:02:25 +0800 Subject: [PATCH] remove more libs and optimized code --- docs/2to3.md | 11 ++++++++-- pyproject.toml | 7 +------ uiautomator2/__init__.py | 5 +---- uiautomator2/core.py | 42 +++++++++++++++++++++++++------------- uiautomator2/exceptions.py | 5 ++--- 5 files changed, 41 insertions(+), 29 deletions(-) diff --git a/docs/2to3.md b/docs/2to3.md index 0443f37..7ac460d 100644 --- a/docs/2to3.md +++ b/docs/2to3.md @@ -22,6 +22,9 @@ ### Lib removes - Remove logzero - Remove filelocks +- Remove progress +- Remove packaging +- Remove Pillow ### Module removes - Remove module uiautomator2.ext.xpath @@ -60,7 +63,7 @@ - Remove "uiautomator2 healthcheck" - Remove "uiautomator2 identify" -## Updates +## Function changes ### connect_usb - 2.x connect_usb(serial, init: bool) - 3.x connect_usb(serial) @@ -107,4 +110,8 @@ - 2.x sess = d.session("com.netease.cloudmusic", attach=True, strict=True) - 3.x sess = d.session("com.netease.cloudmusic", attach=True) -It seems the strict is useless, so I delete it. \ No newline at end of file +It seems the strict is useless, so I delete it. + +### push +- 2.x push(src, dst, mode, show_process:bool=False) +- 3.x push(src, dst, mode) \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 9011ab4..07e133c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [tool.poetry] name = "uiautomator2" version = "0.0.0" -description = "automator for anroid device" +description = "uiautomator for android device" homepage = "https://github.com/openatx/uiautomator2" authors = ["codeskyblue "] license = "MIT" @@ -14,12 +14,7 @@ requests = "*" lxml = "*" adbutils = "^2.2.3,!=2.3.0" retry = ">=0,<1" -packaging = ">=20.3" -pillow = "*" - -# TODO: remove later Deprecated = "*" -progress = "^1.6" [tool.poetry.group.dev.dependencies] pytest = "^8.1.1" diff --git a/uiautomator2/__init__.py b/uiautomator2/__init__.py index 8a4d80a..7692055 100644 --- a/uiautomator2/__init__.py +++ b/uiautomator2/__init__.py @@ -182,7 +182,7 @@ def reset_uiautomator(self): self.stop_uiautomator() self.start_uiautomator() - def push(self, src, dst: str, mode=0o644, show_progress=False): + def push(self, src, dst: str, mode=0o644): """ Push file into device @@ -190,10 +190,7 @@ def push(self, src, dst: str, mode=0o644, show_progress=False): src (path or fileobj): source file dst (str): destination can be folder or file path mode (int): file mode - show_progress (bool): not supported now """ - if show_progress: - logger.warning("show_progress is not supported now") self._dev.sync.push(src, dst, mode=mode) def pull(self, src: str, dst: str): diff --git a/uiautomator2/core.py b/uiautomator2/core.py index 428b654..c6c088b 100644 --- a/uiautomator2/core.py +++ b/uiautomator2/core.py @@ -5,6 +5,7 @@ """ import atexit +import re import threading import time import logging @@ -15,7 +16,7 @@ import adbutils import requests -from uiautomator2.exceptions import InjectPermissionError, RPCInvalidError, UiAutomationNotConnectedError, HTTPError, LaunchUiautomatorError, UiObjectNotFoundError, RPCUnknownError, APkSignatureError +from uiautomator2.exceptions import RPCInvalidError, UiAutomationNotConnectedError, HTTPError, LaunchUiAutomationError, UiObjectNotFoundError, RPCUnknownError, APkSignatureError, AccessibilityServiceAlreadyRegisteredError from uiautomator2.abstract import AbstractUiautomatorServer @@ -205,7 +206,7 @@ def _install_apk(self, apk_path: Path): self._dev.push(apk_path, target_path) self._dev.shell(['pm', 'install', '-r', '-t', target_path]) - def _wait_instrument_ready(self, timeout=10): + def _wait_instrument_ready(self, timeout: float): deadline = time.time() + timeout while time.time() < deadline: output = self._process.output.decode("utf-8", errors="ignore") @@ -213,27 +214,35 @@ def _wait_instrument_ready(self, timeout=10): raise APkSignatureError("app-uiautomator.apk does not have a signature matching the target") if "INSTRUMENTATION_STATUS: Error=" in output: error_message = output[output.find("INSTRUMENTATION_STATUS: Error="):].splitlines()[0] - raise LaunchUiautomatorError(error_message, output) - if "INSTRUMENTATION_STATUS_CODE: -1" in output: - raise LaunchUiautomatorError("am instrument error", output) - if "INSTRUMENTATION_STATUS_CODE: 1" in output: - # success - return + raise LaunchUiAutomationError(error_message, output) + if "INSTRUMENTATION_STATUS_CODE:" in output: + status_code = int(re.search(r"INSTRUMENTATION_STATUS_CODE: (-?\d+)", output).group(1)) + if status_code == 1: # success + logger.debug("am instrument success, status_code: %d", status_code) + return + raise LaunchUiAutomationError("am instrument error", f'CODE:{status_code}', output) + if self._process.pool() is not None: + raise LaunchUiAutomationError("am instrument quit", output) time.sleep(.5) - raise LaunchUiautomatorError("am instrument timeout") + raise LaunchUiAutomationError("am instrument launch timeout", f"{timeout}s", output) - def _wait_stub_ready(self, timeout=20): + def _wait_stub_ready(self, timeout: float): deadline = time.time() + timeout while time.time() < deadline: + output = self._process.output.decode("utf-8", errors="ignore") + if "already registered" in output: + raise AccessibilityServiceAlreadyRegisteredError("Possibly another UiAutomation service is running, you may find it output by \"adb shell ps -u shell\"",) + if self._process.pool() is not None: + raise LaunchUiAutomationError("uiautomator2 server quit", output) try: response = _http_request(self._dev, "GET", "/ping") if response.content == b"pong": return except HTTPError: time.sleep(.5) - raise LaunchUiautomatorError("uiautomator2 server not ready") + raise LaunchUiAutomationError("uiautomator2 server not ready") - def _wait_ready(self, launch_timeout=10, service_timeout=30): + def _wait_ready(self, launch_timeout=30, service_timeout=30): """Wait until uiautomator2 server is ready""" # wait am instrument start self._wait_instrument_ready(launch_timeout) @@ -252,7 +261,13 @@ def jsonrpc_call(self, method: str, params: Any = None, timeout: float = 10) -> """Send jsonrpc call to uiautomator2 server""" try: return _jsonrpc_call(self._dev, method, params, timeout, self._debug) - except (HTTPError, RPCInvalidError, UiAutomationNotConnectedError) as e: + except APkSignatureError: + logger.debug("APkSignatureError: %s", e) + self._dev.uninstall("com.github.uiautomator") + self._dev.uninstall("com.github.uiautomator.test") + self.start_uiautomator() + return _jsonrpc_call(self._dev, method, params, timeout, self._debug) + except (HTTPError, UiAutomationNotConnectedError) as e: logger.debug("uiautomator2 is not ok, error: %s", e) try: self.start_uiautomator() @@ -263,7 +278,6 @@ def jsonrpc_call(self, method: str, params: Any = None, timeout: float = 10) -> self.start_uiautomator() return _jsonrpc_call(self._dev, method, params, timeout, self._debug) - class SimpleUiautomatorServer(BasicUiautomatorServer, AbstractUiautomatorServer): @property def info(self) -> Dict[str, Any]: diff --git a/uiautomator2/exceptions.py b/uiautomator2/exceptions.py index f8ee1d7..fff95fc 100644 --- a/uiautomator2/exceptions.py +++ b/uiautomator2/exceptions.py @@ -9,12 +9,9 @@ class DeviceError(BaseException): pass class AdbShellError(DeviceError):... -class LaunchUiautomatorError(DeviceError):... class ConnectError(DeviceError):... class HTTPError(DeviceError):... - - class UiAutomationError(DeviceError): pass @@ -22,6 +19,8 @@ class UiAutomationError(DeviceError): class UiAutomationNotConnectedError(UiAutomationError):... class InjectPermissionError(UiAutomationError):... #开发者选项中: 模拟点击没有打开 class APkSignatureError(UiAutomationError):... +class LaunchUiAutomationError(UiAutomationError):... +class AccessibilityServiceAlreadyRegisteredError(UiAutomationError):... ## RPCError