Kea2-python 0.2.0__tar.gz → 0.2.1__tar.gz
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_python-0.2.0 → kea2_python-0.2.1}/Kea2_python.egg-info/PKG-INFO +1 -1
- {kea2_python-0.2.0 → kea2_python-0.2.1}/PKG-INFO +1 -1
- {kea2_python-0.2.0 → kea2_python-0.2.1}/kea2/adbUtils.py +13 -5
- kea2_python-0.2.1/kea2/assets/monkeyq.jar +0 -0
- {kea2_python-0.2.0 → kea2_python-0.2.1}/kea2/bug_report_generator.py +1 -1
- {kea2_python-0.2.0 → kea2_python-0.2.1}/kea2/fastbotManager.py +14 -21
- kea2_python-0.2.1/kea2/logWatcher.py +79 -0
- {kea2_python-0.2.0 → kea2_python-0.2.1}/kea2/templates/bug_report_template.html +6 -2
- {kea2_python-0.2.0 → kea2_python-0.2.1}/pyproject.toml +1 -1
- kea2_python-0.2.0/kea2/assets/monkeyq.jar +0 -0
- kea2_python-0.2.0/kea2/logWatcher.py +0 -82
- {kea2_python-0.2.0 → kea2_python-0.2.1}/Kea2_python.egg-info/SOURCES.txt +0 -0
- {kea2_python-0.2.0 → kea2_python-0.2.1}/Kea2_python.egg-info/dependency_links.txt +0 -0
- {kea2_python-0.2.0 → kea2_python-0.2.1}/Kea2_python.egg-info/entry_points.txt +0 -0
- {kea2_python-0.2.0 → kea2_python-0.2.1}/Kea2_python.egg-info/requires.txt +0 -0
- {kea2_python-0.2.0 → kea2_python-0.2.1}/Kea2_python.egg-info/top_level.txt +0 -0
- {kea2_python-0.2.0 → kea2_python-0.2.1}/LICENSE +0 -0
- {kea2_python-0.2.0 → kea2_python-0.2.1}/README.md +0 -0
- {kea2_python-0.2.0 → kea2_python-0.2.1}/kea2/__init__.py +0 -0
- {kea2_python-0.2.0 → kea2_python-0.2.1}/kea2/absDriver.py +0 -0
- {kea2_python-0.2.0 → kea2_python-0.2.1}/kea2/assets/fastbot-thirdpart.jar +0 -0
- {kea2_python-0.2.0 → kea2_python-0.2.1}/kea2/assets/fastbot_configs/abl.strings +0 -0
- {kea2_python-0.2.0 → kea2_python-0.2.1}/kea2/assets/fastbot_configs/awl.strings +0 -0
- {kea2_python-0.2.0 → kea2_python-0.2.1}/kea2/assets/fastbot_configs/max.config +0 -0
- {kea2_python-0.2.0 → kea2_python-0.2.1}/kea2/assets/fastbot_configs/max.fuzzing.strings +0 -0
- {kea2_python-0.2.0 → kea2_python-0.2.1}/kea2/assets/fastbot_configs/max.schema.strings +0 -0
- {kea2_python-0.2.0 → kea2_python-0.2.1}/kea2/assets/fastbot_configs/max.strings +0 -0
- {kea2_python-0.2.0 → kea2_python-0.2.1}/kea2/assets/fastbot_configs/max.tree.pruning +0 -0
- {kea2_python-0.2.0 → kea2_python-0.2.1}/kea2/assets/fastbot_configs/widget.block.py +0 -0
- {kea2_python-0.2.0 → kea2_python-0.2.1}/kea2/assets/fastbot_libs/arm64-v8a/libfastbot_native.so +0 -0
- {kea2_python-0.2.0 → kea2_python-0.2.1}/kea2/assets/fastbot_libs/armeabi-v7a/libfastbot_native.so +0 -0
- {kea2_python-0.2.0 → kea2_python-0.2.1}/kea2/assets/fastbot_libs/x86/libfastbot_native.so +0 -0
- {kea2_python-0.2.0 → kea2_python-0.2.1}/kea2/assets/fastbot_libs/x86_64/libfastbot_native.so +0 -0
- {kea2_python-0.2.0 → kea2_python-0.2.1}/kea2/assets/framework.jar +0 -0
- {kea2_python-0.2.0 → kea2_python-0.2.1}/kea2/assets/kea2-thirdpart.jar +0 -0
- {kea2_python-0.2.0 → kea2_python-0.2.1}/kea2/assets/quicktest.py +0 -0
- {kea2_python-0.2.0 → kea2_python-0.2.1}/kea2/cli.py +0 -0
- {kea2_python-0.2.0 → kea2_python-0.2.1}/kea2/keaUtils.py +0 -0
- {kea2_python-0.2.0 → kea2_python-0.2.1}/kea2/kea_launcher.py +0 -0
- {kea2_python-0.2.0 → kea2_python-0.2.1}/kea2/resultSyncer.py +0 -0
- {kea2_python-0.2.0 → kea2_python-0.2.1}/kea2/u2Driver.py +0 -0
- {kea2_python-0.2.0 → kea2_python-0.2.1}/kea2/utils.py +0 -0
- {kea2_python-0.2.0 → kea2_python-0.2.1}/setup.cfg +0 -0
- {kea2_python-0.2.0 → kea2_python-0.2.1}/tests/test_u2Selector.py +0 -0
|
@@ -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) -> "
|
|
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)
|
|
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.
|
|
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}")
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
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
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
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):
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import re
|
|
2
|
+
import os
|
|
3
|
+
import threading
|
|
4
|
+
import time
|
|
5
|
+
from typing import IO
|
|
6
|
+
from kea2.utils import getLogger
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
logger = getLogger(__name__)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
PATTERN_EXCEPTION = re.compile(r"\[Fastbot\].+Internal\serror\n([\s\S]*)")
|
|
13
|
+
PATTERN_STATISTIC = re.compile(r".+Monkey\sis\sover!\n([\s\S]+)")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def thread_excepthook(args):
|
|
17
|
+
print(args.exc_value, flush=True)
|
|
18
|
+
os._exit(1)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class LogWatcher:
|
|
23
|
+
|
|
24
|
+
def watcher(self, poll_interval=3):
|
|
25
|
+
self.last_pos = 0
|
|
26
|
+
|
|
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)
|
|
34
|
+
|
|
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)
|
|
44
|
+
if exception_match:
|
|
45
|
+
exception_body = exception_match.group(1).strip()
|
|
46
|
+
if exception_body:
|
|
47
|
+
raise RuntimeError(
|
|
48
|
+
"[Error] Fatal Execption while running fastbot:\n" +
|
|
49
|
+
exception_body +
|
|
50
|
+
"\nSee fastbot.log for details."
|
|
51
|
+
)
|
|
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)
|
|
61
|
+
|
|
62
|
+
def __init__(self, log_file):
|
|
63
|
+
logger.info(f"Watching log: {log_file}")
|
|
64
|
+
self.log_file = log_file
|
|
65
|
+
self.end_flag = False
|
|
66
|
+
|
|
67
|
+
threading.excepthook = thread_excepthook
|
|
68
|
+
self.t = threading.Thread(target=self.watcher, daemon=True)
|
|
69
|
+
self.t.start()
|
|
70
|
+
|
|
71
|
+
def close(self):
|
|
72
|
+
logger.info("Close: LogWatcher")
|
|
73
|
+
self.end_flag = True
|
|
74
|
+
if self.t:
|
|
75
|
+
self.t.join()
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
if __name__ == "__main__":
|
|
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(
|
|
711
|
+
stepSize: steps.length > 0 ? Math.max(1, Math.ceil(Math.max(...steps) / 10)) : 1,
|
|
711
712
|
callback: function(value) {
|
|
712
|
-
|
|
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
|
},
|
|
Binary file
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import re
|
|
2
|
-
import os
|
|
3
|
-
import threading
|
|
4
|
-
import time
|
|
5
|
-
from .utils import getLogger
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
logger = getLogger(__name__)
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
PATTERN_EXCEPTION = re.compile(r"\[Fastbot\].+Internal\serror\n([\s\S]*)")
|
|
12
|
-
PATTERN_STATISTIC = re.compile(r".+Monkey\sis\sover!\n([\s\S]+)")
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
def thread_excepthook(args):
|
|
16
|
-
print(args.exc_value, flush=True)
|
|
17
|
-
os._exit(1)
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
class LogWatcher:
|
|
22
|
-
|
|
23
|
-
def watcher(self, poll_interval=0.5):
|
|
24
|
-
self.buffer = ""
|
|
25
|
-
self.last_pos = 0
|
|
26
|
-
|
|
27
|
-
while not self.end_flag:
|
|
28
|
-
self.read_log()
|
|
29
|
-
time.sleep(poll_interval)
|
|
30
|
-
|
|
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)
|
|
47
|
-
if exception_match:
|
|
48
|
-
exception_body = exception_match.group(1).strip()
|
|
49
|
-
if exception_body:
|
|
50
|
-
raise RuntimeError(
|
|
51
|
-
"[Error] Execption while running fastbot:\n" +
|
|
52
|
-
exception_body +
|
|
53
|
-
"\nSee fastbot.log for details."
|
|
54
|
-
)
|
|
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)
|
|
64
|
-
|
|
65
|
-
def __init__(self, log_file):
|
|
66
|
-
logger.info(f"Watching log: {log_file}")
|
|
67
|
-
self.log_file = log_file
|
|
68
|
-
self.end_flag = False
|
|
69
|
-
|
|
70
|
-
threading.excepthook = thread_excepthook
|
|
71
|
-
self.t = threading.Thread(target=self.watcher, daemon=True)
|
|
72
|
-
self.t.start()
|
|
73
|
-
|
|
74
|
-
def close(self):
|
|
75
|
-
logger.info("Close: LogWatcher")
|
|
76
|
-
self.end_flag = True
|
|
77
|
-
if self.t:
|
|
78
|
-
self.t.join()
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
if __name__ == "__main__":
|
|
82
|
-
LogWatcher("fastbot.log")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{kea2_python-0.2.0 → kea2_python-0.2.1}/kea2/assets/fastbot_libs/arm64-v8a/libfastbot_native.so
RENAMED
|
File without changes
|
{kea2_python-0.2.0 → kea2_python-0.2.1}/kea2/assets/fastbot_libs/armeabi-v7a/libfastbot_native.so
RENAMED
|
File without changes
|
|
File without changes
|
{kea2_python-0.2.0 → kea2_python-0.2.1}/kea2/assets/fastbot_libs/x86_64/libfastbot_native.so
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|