Kea2-python 0.2.0__py3-none-any.whl → 0.2.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 Kea2-python might be problematic. Click here for more details.

kea2/adbUtils.py CHANGED
@@ -6,7 +6,6 @@ from typing import List, Optional, Set, Tuple
6
6
  from kea2.utils import getLogger
7
7
  from adbutils import AdbDevice, adb
8
8
  from typing import IO, TYPE_CHECKING, Generator, Optional, List, Union
9
- from adbutils import AdbConnection
10
9
 
11
10
  logger = getLogger(__name__)
12
11
 
@@ -44,20 +43,29 @@ class ADBDevice(AdbDevice):
44
43
  super().__init__(client=adb, serial=ADBDevice.serial, transport_id=ADBDevice.transport_id)
45
44
 
46
45
  @property
47
- def stream_shell(self) -> "ADBStreamShell_V2":
46
+ def stream_shell(self) -> "StreamShell":
48
47
  if "shell_v2" in self.get_features():
49
48
  return ADBStreamShell_V2(session=self)
50
49
  logger.warning("Using ADBStreamShell_V1. All output will be printed to stdout.")
51
50
  return ADBStreamShell_V1(session=self)
52
51
 
52
+ def kill_proc(self, proc_name):
53
+ r = self.shell(f"ps -ef")
54
+ pids = [l for l in r.splitlines() if proc_name in l]
55
+ if pids:
56
+ logger.info(f"{proc_name} running, trying to kill it.")
57
+ pid = pids[0].split()[1]
58
+ self.shell(f"kill {pid}")
59
+
53
60
 
54
61
  class StreamShell:
55
62
  def __init__(self, session: "ADBDevice"):
56
63
  self.dev: ADBDevice = session
57
- self._thread = None
64
+ self._thread: threading.Thread = None
58
65
  self._exit_code = 255
59
66
  self.stdout = sys.stdout
60
67
  self.stderr = sys.stderr
68
+ self._finished = False
61
69
 
62
70
  def __call__(self, cmdargs: Union[List[str], str], stdout: IO = None,
63
71
  stderr: IO = None, timeout: Union[float, None] = None) -> "StreamShell":
@@ -107,7 +115,7 @@ class StreamShell:
107
115
  class ADBStreamShell_V1(StreamShell):
108
116
 
109
117
  def __call__(
110
- self, cmdargs: Union[List[str]], stdout: IO = None,
118
+ self, cmdargs: Union[List[str], str], stdout: IO = None,
111
119
  stderr: IO = None, timeout: Union[float, None] = None
112
120
  ) -> "StreamShell":
113
121
  return self.shell_v1(cmdargs, stdout, stderr, timeout)
@@ -168,7 +176,7 @@ class ADBStreamShell_V2(StreamShell):
168
176
  self._exit_code = 255
169
177
 
170
178
  def __call__(
171
- self, cmdargs: Union[List[str]], stdout: IO = None,
179
+ self, cmdargs: Union[List[str], str], stdout: IO = None,
172
180
  stderr: IO = None, timeout: Union[float, None] = None
173
181
  ) -> "StreamShell":
174
182
  return self.shell_v2(cmdargs, stdout, stderr, timeout)
kea2/assets/monkeyq.jar CHANGED
Binary file
@@ -94,7 +94,7 @@ class BugReportGenerator:
94
94
  with open(report_path, "w", encoding="utf-8") as f:
95
95
  f.write(html_content)
96
96
 
97
- logger.info(f"Bug report saved to: {report_path}")
97
+ logger.debug(f"Bug report saved to: {report_path}")
98
98
 
99
99
  except Exception as e:
100
100
  logger.error(f"Error generating bug report: {e}")
kea2/fastbotManager.py CHANGED
@@ -1,5 +1,5 @@
1
- import subprocess
2
- import threading
1
+ from retry import retry
2
+ from retry.api import retry_call
3
3
  from dataclasses import asdict
4
4
  import requests
5
5
  from time import sleep
@@ -80,25 +80,18 @@ class FastbotManager:
80
80
  """
81
81
  check if the script driver and proxy server are alive.
82
82
  """
83
+ def _check_alive_request():
84
+ _http_request(dev=self.dev, device_port=8090, method="GET", path="/ping")
83
85
 
84
- for _ in range(10):
85
- sleep(2)
86
- try:
87
- _http_request(
88
- dev=self.dev,
89
- device_port=8090,
90
- method="GET",
91
- path="/ping",
92
- )
93
- return
94
- except requests.ConnectionError:
95
- logger.info("waiting for connection.")
96
- pass
97
- raise RuntimeError("Failed to connect fastbot")
86
+ try:
87
+ retry_call(_check_alive_request, tries=10, delay=2)
88
+ except requests.ConnectionError:
89
+ raise RuntimeError("Failed to connect fastbot")
98
90
 
99
91
  def request(self, method: str, path: str, data: Dict=None, timeout: int=10) -> HTTPResponse:
100
92
  return _http_request(self.dev, 8090, method, path, data, timeout)
101
93
 
94
+ @retry(Exception, tries=2, delay=2)
102
95
  def init(self, options: "Options", stamp):
103
96
  post_data = {
104
97
  "takeScreenshots": options.take_screenshots,
@@ -117,6 +110,7 @@ class FastbotManager:
117
110
  self._device_output_dir = re.match(r"outputDir:(.+)", r.text).group(1)
118
111
  print(f"[INFO] Fastbot initiated. outputDir: {r.text}", flush=True)
119
112
 
113
+ @retry(Exception, tries=2, delay=2)
120
114
  def stepMonkey(self, monkeyStepInfo):
121
115
  r = self.request(
122
116
  method="POST",
@@ -125,6 +119,7 @@ class FastbotManager:
125
119
  )
126
120
  return r.json()["result"]
127
121
 
122
+ @retry(Exception, tries=2, delay=2)
128
123
  def stopMonkey(self):
129
124
  """
130
125
  send a stop monkey request to the server.
@@ -136,6 +131,7 @@ class FastbotManager:
136
131
 
137
132
  print(f"[Server INFO] {r.text}", flush=True)
138
133
 
134
+ @retry(Exception, tries=2, delay=2)
139
135
  def logScript(self, execution_info: Dict):
140
136
  r = self.request(
141
137
  method="POST",
@@ -182,12 +178,7 @@ class FastbotManager:
182
178
  logger.info("Launching fastbot with shell command:\n{}".format(" ".join(full_cmd)))
183
179
  logger.info("Fastbot log will be saved to {}".format(outfile.name))
184
180
 
185
- # stream = self.dev.shell(shell_command, encoding="utf-8", stream=True, timeout=float("inf"))
186
- # process handler
187
181
  t = self.dev.stream_shell(shell_command, stdout=outfile, stderr=outfile)
188
- # proc = subprocess.Popen(full_cmd, stdout=outfile, stderr=outfile)
189
- # t = threading.Thread(target=self.close_on_exit, args=(proc, outfile), daemon=True)
190
- # t.start()
191
182
  return t
192
183
 
193
184
  def close_on_exit(self, proc: ADBStreamShell_V2, f: IO):
@@ -203,6 +194,8 @@ class FastbotManager:
203
194
  return self.thread.poll()
204
195
 
205
196
  def start(self):
197
+ # kill the fastbot process if runing.
198
+ self.dev.kill_proc("com.android.commands.monkey")
206
199
  self.thread = self._activateFastbot()
207
200
 
208
201
  def join(self):
kea2/logWatcher.py CHANGED
@@ -2,7 +2,8 @@ import re
2
2
  import os
3
3
  import threading
4
4
  import time
5
- from .utils import getLogger
5
+ from typing import IO
6
+ from kea2.utils import getLogger
6
7
 
7
8
 
8
9
  logger = getLogger(__name__)
@@ -20,47 +21,43 @@ def thread_excepthook(args):
20
21
 
21
22
  class LogWatcher:
22
23
 
23
- def watcher(self, poll_interval=0.5):
24
- self.buffer = ""
24
+ def watcher(self, poll_interval=3):
25
25
  self.last_pos = 0
26
26
 
27
- while not self.end_flag:
28
- self.read_log()
29
- time.sleep(poll_interval)
27
+ with open(self.log_file, "r") as fp:
28
+ while not self.end_flag:
29
+ self.read_log(fp)
30
+ time.sleep(poll_interval)
31
+
32
+ time.sleep(0.2)
33
+ self.read_log(fp)
30
34
 
31
- time.sleep(0.2)
32
- self.read_log()
33
-
34
- def read_log(self):
35
- with open(self.log_file, 'r', encoding='utf-8') as f:
36
- f.seek(self.last_pos)
37
- new_data = f.read()
38
- self.last_pos = f.tell()
39
-
40
- if new_data:
41
- self.buffer += new_data
42
- self.parse_log()
43
-
44
- def parse_log(self):
45
- buffer = self.buffer
46
- exception_match = PATTERN_EXCEPTION.search(buffer)
35
+ def read_log(self, f: IO):
36
+ f.seek(self.last_pos)
37
+ buffer = f.read()
38
+ self.last_pos = f.tell()
39
+
40
+ self.parse_log(buffer)
41
+
42
+ def parse_log(self, content):
43
+ exception_match = PATTERN_EXCEPTION.search(content)
47
44
  if exception_match:
48
45
  exception_body = exception_match.group(1).strip()
49
46
  if exception_body:
50
47
  raise RuntimeError(
51
- "[Error] Execption while running fastbot:\n" +
48
+ "[Error] Fatal Execption while running fastbot:\n" +
52
49
  exception_body +
53
50
  "\nSee fastbot.log for details."
54
51
  )
55
- if self.end_flag:
56
- statistic_match = PATTERN_STATISTIC.search(buffer)
57
- if statistic_match:
58
- statistic_body = statistic_match.group(1).strip()
59
- if statistic_body:
60
- print(
61
- "[INFO] Fastbot exit:\n" +
62
- statistic_body
63
- , flush=True)
52
+
53
+ statistic_match = PATTERN_STATISTIC.search(content)
54
+ if statistic_match:
55
+ statistic_body = statistic_match.group(1).strip()
56
+ if statistic_body:
57
+ print(
58
+ "[INFO] Fastbot exit:\n" +
59
+ statistic_body
60
+ , flush=True)
64
61
 
65
62
  def __init__(self, log_file):
66
63
  logger.info(f"Watching log: {log_file}")
@@ -79,4 +76,4 @@ class LogWatcher:
79
76
 
80
77
 
81
78
  if __name__ == "__main__":
82
- LogWatcher("fastbot.log")
79
+ LogWatcher("/Users/atria/Desktop/coding/Kea2/output/res_2025062510_0420056539/fastbot_2025062510_0420056539.log")
@@ -696,6 +696,7 @@
696
696
  x: {
697
697
  type: 'linear',
698
698
  beginAtZero: true,
699
+ max: steps.length > 0 ? Math.max(...steps) : 10,
699
700
  grid: {
700
701
  display: false
701
702
  },
@@ -707,9 +708,12 @@
707
708
  }
708
709
  },
709
710
  ticks: {
710
- stepSize: Math.max(10, Math.ceil(Math.max(...steps) / 10)),
711
+ stepSize: steps.length > 0 ? Math.max(1, Math.ceil(Math.max(...steps) / 10)) : 1,
711
712
  callback: function(value) {
712
- return value;
713
+ if (Number.isInteger(value) && value <= (steps.length > 0 ? Math.max(...steps) : 10)) {
714
+ return value;
715
+ }
716
+ return null;
713
717
  }
714
718
  }
715
719
  },
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Kea2-python
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: A python library for supporting and customizing automated UI testing for mobile apps
5
5
  Author-email: Xixian Liang <xixian@stu.ecnu.edu.cn>
6
6
  Requires-Python: >=3.8
@@ -1,19 +1,19 @@
1
1
  kea2/__init__.py,sha256=JFJjqgf5KB4bXUFQ3upkEug0cFMFIk9p3OHV9vzulHw,75
2
2
  kea2/absDriver.py,sha256=NzmsLs1Ojz-yEXctGAqj7aKBwAQW19zd83l65RABCe8,1288
3
- kea2/adbUtils.py,sha256=1t5oxr3CVen2kn4ilPy7lZolnEDawVXAjfDwXJMjBIk,19532
4
- kea2/bug_report_generator.py,sha256=avpZgUywmUePO1_2dDXBgUkxAAa0gpiTpaDtyjInw7Q,20245
3
+ kea2/adbUtils.py,sha256=9XwKDIzEDOQjOchPsZPPK6WDC0ojYNSvW0YvMfwAwQY,19842
4
+ kea2/bug_report_generator.py,sha256=br0OkUDFmaJz0S7s-0uxbAPOFJYAlDjmG436dCwoDIo,20246
5
5
  kea2/cli.py,sha256=YgWOe5JB0_WBTKyBShBEymhLIqj6K5gNR4Aaj6Pbtn0,2796
6
- kea2/fastbotManager.py,sha256=DI5jtUEf2ro9I2MNKxw6Oh42nmEjcpLecEMj0IhKZGs,6974
6
+ kea2/fastbotManager.py,sha256=dersx5sg1xW1z4nObwUBz5VzHQNi-ADHsAfhJMti8BU,6788
7
7
  kea2/keaUtils.py,sha256=yNuEIIWfxTBfApiasKy9eMD-iKeLLH0LKunZbuxL_j8,25595
8
8
  kea2/kea_launcher.py,sha256=eV8MvWWRwbhXJ2IaxjSIRL9ZyZF6OKlEeWzAfwkoXLg,5712
9
- kea2/logWatcher.py,sha256=qpIsflbP37eX5b4EaWnrqyPbGP9lzQhRr3ainGFfZeI,2211
9
+ kea2/logWatcher.py,sha256=NL3HwscDgA4-vcUl0r0yYH1naUVv-_YA9LNA4b3VxNE,2178
10
10
  kea2/resultSyncer.py,sha256=9kb3H0Innwj7oPboDDTf97nbjam7EP6HYxywR9B8SvM,2437
11
11
  kea2/u2Driver.py,sha256=nRleo-NmKuqgY-_4aiPREDQ2Yw-9yawd9hdslD1RmE4,15539
12
12
  kea2/utils.py,sha256=ErMUCwKddA6xETE8xKFI281N6iiVzpDBEhfSZ_JFNGQ,1467
13
13
  kea2/assets/fastbot-thirdpart.jar,sha256=0SZ_OoZFWDGMnazgXKceHgKvXdUDoIa3Gb2bcifaikk,85664
14
14
  kea2/assets/framework.jar,sha256=rTluOJJKj2DFwh7ascXso1udYdWv00BxBwSQ3Vmv-fw,1149240
15
15
  kea2/assets/kea2-thirdpart.jar,sha256=HYdtG2gqDLuLb72dpK3lX-Y6QUNTrJ-bfQopU5aWpfo,359346
16
- kea2/assets/monkeyq.jar,sha256=EU8aF9S3N1SiZ_RGxP2etPeNBLr9tVPwj0XcCwGNcjc,111988
16
+ kea2/assets/monkeyq.jar,sha256=TTptUo-B4VV9Q8AeQKSqi1KsyG3eY4iYYb0NZCc4yV4,112189
17
17
  kea2/assets/quicktest.py,sha256=TJj9GaRioFrijU9PMLpyZY8S07db67UZFBr5G-aQY80,3000
18
18
  kea2/assets/fastbot_configs/abl.strings,sha256=Rn8_YEbVGOJqndIY_-kWnR5NaoFI-cuB-ij10Ddhl90,75
19
19
  kea2/assets/fastbot_configs/awl.strings,sha256=-j4980GoWQxGOM9ijAwXPQmziCwFBZJFmuiv2tOEaYI,101
@@ -27,10 +27,10 @@ kea2/assets/fastbot_libs/arm64-v8a/libfastbot_native.so,sha256=tAFrG73pJi7XakRxS
27
27
  kea2/assets/fastbot_libs/armeabi-v7a/libfastbot_native.so,sha256=UV8bhaiPoPKdd3q0vj3kSZqPR9anllai_tz_2QkMMbQ,1335372
28
28
  kea2/assets/fastbot_libs/x86/libfastbot_native.so,sha256=k-aw1gEXRWMKZRNHIggKNuZy0wC1y2BnveJGEIO6rbo,2036856
29
29
  kea2/assets/fastbot_libs/x86_64/libfastbot_native.so,sha256=tiofhlf4uMQcU5WAvrdLgTBME0lb83hVUoGtTwxmE8A,2121416
30
- kea2/templates/bug_report_template.html,sha256=59KL5rRwGwKs7mNgtiWSSUD_NG_5Cu5Agq4QfydCLt8,37935
31
- kea2_python-0.2.0.dist-info/licenses/LICENSE,sha256=nM9PPjcsXVo5SzNsjRqWgA-gdJlwqZZcRDSC6Qf6bVE,2034
32
- kea2_python-0.2.0.dist-info/METADATA,sha256=zszS6ye6p4gYZLscTZdxah8GI3-dowxlEJNKAuRxijg,14023
33
- kea2_python-0.2.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
34
- kea2_python-0.2.0.dist-info/entry_points.txt,sha256=mFX06TyxXiUAJQ6JZn8QHzfn8n5R8_KJ5W-pTm_fRCA,39
35
- kea2_python-0.2.0.dist-info/top_level.txt,sha256=TsgNH4PQoNOVhegpO7AcjutMVWp6Z4KDL1pBH9FnMmk,5
36
- kea2_python-0.2.0.dist-info/RECORD,,
30
+ kea2/templates/bug_report_template.html,sha256=hAg57OTUfScH9HJTwkBMI1HhVAcElMW8jO1eS6AE5rs,38249
31
+ kea2_python-0.2.1.dist-info/licenses/LICENSE,sha256=nM9PPjcsXVo5SzNsjRqWgA-gdJlwqZZcRDSC6Qf6bVE,2034
32
+ kea2_python-0.2.1.dist-info/METADATA,sha256=vKYdL6LnlhFM8HTB1rI45KsVRi-AHGaVn0AEgQe0Nm4,14023
33
+ kea2_python-0.2.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
34
+ kea2_python-0.2.1.dist-info/entry_points.txt,sha256=mFX06TyxXiUAJQ6JZn8QHzfn8n5R8_KJ5W-pTm_fRCA,39
35
+ kea2_python-0.2.1.dist-info/top_level.txt,sha256=TsgNH4PQoNOVhegpO7AcjutMVWp6Z4KDL1pBH9FnMmk,5
36
+ kea2_python-0.2.1.dist-info/RECORD,,