Kea2-python 1.1.2__tar.gz → 1.1.3b1__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.
Files changed (67) hide show
  1. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/Kea2_python.egg-info/PKG-INFO +1 -1
  2. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/Kea2_python.egg-info/SOURCES.txt +7 -0
  3. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/PKG-INFO +1 -1
  4. kea2_python-1.1.3b1/kea2/assets/fastbot_libs/arm64-v8a/libfastbot_native.so +0 -0
  5. kea2_python-1.1.3b1/kea2/assets/fastbot_libs/armeabi-v7a/libfastbot_native.so +0 -0
  6. kea2_python-1.1.3b1/kea2/assets/fastbot_libs/x86/libfastbot_native.so +0 -0
  7. kea2_python-1.1.3b1/kea2/assets/fastbot_libs/x86_64/libfastbot_native.so +0 -0
  8. kea2_python-1.1.3b1/kea2/assets/monkeyq.jar +0 -0
  9. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/kea2/cli.py +105 -1
  10. kea2_python-1.1.3b1/kea2/fastbotx/ActivityTimes.py +52 -0
  11. kea2_python-1.1.3b1/kea2/fastbotx/ReuseEntry.py +74 -0
  12. kea2_python-1.1.3b1/kea2/fastbotx/ReuseModel.py +63 -0
  13. kea2_python-1.1.3b1/kea2/fastbotx/__init__.py +7 -0
  14. kea2_python-1.1.3b1/kea2/fbm_parser.py +871 -0
  15. kea2_python-1.1.3b1/kea2/fs_lock.py +131 -0
  16. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/kea2/keaUtils.py +130 -12
  17. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/kea2/kea_launcher.py +21 -1
  18. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/kea2/report/bug_report_generator.py +70 -20
  19. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/kea2/report/report_merger.py +52 -0
  20. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/kea2/report/templates/bug_report_template.html +186 -3
  21. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/kea2/report/templates/merged_bug_report_template.html +556 -545
  22. kea2_python-1.1.3b1/kea2/report/widget_coverage.py +146 -0
  23. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/pyproject.toml +1 -1
  24. kea2_python-1.1.2/kea2/assets/fastbot_libs/arm64-v8a/libfastbot_native.so +0 -0
  25. kea2_python-1.1.2/kea2/assets/fastbot_libs/armeabi-v7a/libfastbot_native.so +0 -0
  26. kea2_python-1.1.2/kea2/assets/fastbot_libs/x86/libfastbot_native.so +0 -0
  27. kea2_python-1.1.2/kea2/assets/fastbot_libs/x86_64/libfastbot_native.so +0 -0
  28. kea2_python-1.1.2/kea2/assets/monkeyq.jar +0 -0
  29. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/Kea2_python.egg-info/dependency_links.txt +0 -0
  30. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/Kea2_python.egg-info/entry_points.txt +0 -0
  31. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/Kea2_python.egg-info/requires.txt +0 -0
  32. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/Kea2_python.egg-info/top_level.txt +0 -0
  33. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/LICENSE +0 -0
  34. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/README.md +0 -0
  35. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/kea2/__init__.py +0 -0
  36. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/kea2/adbUtils.py +0 -0
  37. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/kea2/assets/config_version.json +0 -0
  38. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/kea2/assets/fastbot-thirdpart.jar +0 -0
  39. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/kea2/assets/fastbot_configs/abl.strings +0 -0
  40. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/kea2/assets/fastbot_configs/awl.strings +0 -0
  41. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/kea2/assets/fastbot_configs/max.config +0 -0
  42. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/kea2/assets/fastbot_configs/max.fuzzing.strings +0 -0
  43. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/kea2/assets/fastbot_configs/max.schema.strings +0 -0
  44. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/kea2/assets/fastbot_configs/max.strings +0 -0
  45. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/kea2/assets/fastbot_configs/max.tree.pruning +0 -0
  46. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/kea2/assets/fastbot_configs/teardown.py +0 -0
  47. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/kea2/assets/fastbot_configs/widget.block.py +0 -0
  48. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/kea2/assets/framework.jar +0 -0
  49. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/kea2/assets/kea2-thirdpart.jar +0 -0
  50. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/kea2/assets/quicktest.py +0 -0
  51. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/kea2/fastbotManager.py +0 -0
  52. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/kea2/kea2_api.py +0 -0
  53. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/kea2/logWatcher.py +0 -0
  54. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/kea2/mixin.py +0 -0
  55. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/kea2/report/__init__.py +0 -0
  56. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/kea2/report/mixin.py +0 -0
  57. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/kea2/report/utils.py +0 -0
  58. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/kea2/result.py +0 -0
  59. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/kea2/resultSyncer.py +0 -0
  60. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/kea2/state.py +0 -0
  61. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/kea2/typedefs.py +0 -0
  62. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/kea2/u2Driver.py +0 -0
  63. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/kea2/utils.py +0 -0
  64. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/kea2/version_manager.py +0 -0
  65. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/setup.cfg +0 -0
  66. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/tests/test_u2Selector.py +0 -0
  67. {kea2_python-1.1.2 → kea2_python-1.1.3b1}/tests/test_xpath.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Kea2-python
3
- Version: 1.1.2
3
+ Version: 1.1.3b1
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
@@ -11,6 +11,8 @@ kea2/__init__.py
11
11
  kea2/adbUtils.py
12
12
  kea2/cli.py
13
13
  kea2/fastbotManager.py
14
+ kea2/fbm_parser.py
15
+ kea2/fs_lock.py
14
16
  kea2/kea2_api.py
15
17
  kea2/keaUtils.py
16
18
  kea2/kea_launcher.py
@@ -42,11 +44,16 @@ kea2/assets/fastbot_libs/arm64-v8a/libfastbot_native.so
42
44
  kea2/assets/fastbot_libs/armeabi-v7a/libfastbot_native.so
43
45
  kea2/assets/fastbot_libs/x86/libfastbot_native.so
44
46
  kea2/assets/fastbot_libs/x86_64/libfastbot_native.so
47
+ kea2/fastbotx/ActivityTimes.py
48
+ kea2/fastbotx/ReuseEntry.py
49
+ kea2/fastbotx/ReuseModel.py
50
+ kea2/fastbotx/__init__.py
45
51
  kea2/report/__init__.py
46
52
  kea2/report/bug_report_generator.py
47
53
  kea2/report/mixin.py
48
54
  kea2/report/report_merger.py
49
55
  kea2/report/utils.py
56
+ kea2/report/widget_coverage.py
50
57
  kea2/report/templates/bug_report_template.html
51
58
  kea2/report/templates/merged_bug_report_template.html
52
59
  tests/test_u2Selector.py
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Kea2-python
3
- Version: 1.1.2
3
+ Version: 1.1.3b1
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
@@ -105,7 +105,90 @@ def cmd_merge(args):
105
105
  print(f"📈 Merged {merge_summary.get('merged_directories', 0)} directories", flush=True)
106
106
 
107
107
  except Exception as e:
108
- logger.error(f"Error during merge operation: {e}")
108
+ logger.error(f"Error during merge operation: {e}")
109
+
110
+
111
+ def cmd_mergefbm(args):
112
+ """Merge all FBM files in the specified folder and its subfolders using sum mode"""
113
+ from .fbm_parser import FBMMerger
114
+ import glob
115
+ import shutil
116
+
117
+ try:
118
+ # Validate input path
119
+ input_path = Path(args.path).resolve()
120
+ if not input_path.exists():
121
+ logger.error(f"Input directory does not exist: {input_path}")
122
+ return
123
+ if not input_path.is_dir():
124
+ logger.error(f"Input path is not a directory: {input_path}")
125
+ return
126
+
127
+ # Find all FBM files in the directory and its subdirectories
128
+ fbm_files = glob.glob(str(input_path / "**" / "*.fbm"), recursive=True)
129
+
130
+ if not fbm_files:
131
+ logger.error(f"No FBM files found in {input_path} or its subdirectories")
132
+ return
133
+
134
+ logger.debug(f"Found {len(fbm_files)} FBM files to merge:")
135
+ for fbm_file in fbm_files:
136
+ logger.debug(f" - {fbm_file}")
137
+
138
+ # Set default output file if not provided
139
+ if not args.output:
140
+ output_file = input_path / "merged.fbm"
141
+ else:
142
+ output_file = Path(args.output).resolve()
143
+
144
+ # Initialize merger
145
+ merger = FBMMerger()
146
+
147
+ # Handle different cases
148
+ if len(fbm_files) == 1:
149
+ # Only one file, just copy it to output
150
+ shutil.copyfile(fbm_files[0], output_file)
151
+ logger.info(f"Only one FBM file found, copied to {output_file}")
152
+ else:
153
+ # Merge files iteratively: start with the first file and merge with each subsequent file
154
+ # Create a temporary file for the intermediate merged result
155
+ temp_output = input_path / f".tmp_merged.fbm"
156
+
157
+ # Start with the first file as the initial merged result
158
+ shutil.copyfile(fbm_files[0], temp_output)
159
+
160
+ # Iterate through the remaining files and merge them one by one
161
+ for i in range(1, len(fbm_files)):
162
+ current_file = fbm_files[i]
163
+ next_temp = input_path / f".tmp_merged_{i}.fbm"
164
+
165
+ logger.debug(f"Merging {temp_output} and {current_file} into {next_temp}")
166
+ success = merger.merge(str(temp_output), str(current_file), str(next_temp), merge_mode='sum')
167
+
168
+ if not success:
169
+ logger.error(f"Failed to merge {temp_output} and {current_file}")
170
+ # Clean up temporary files
171
+ for f in [temp_output, next_temp]:
172
+ if f.exists() and f.name.startswith(".tmp_"):
173
+ f.unlink()
174
+ return
175
+
176
+ # Remove the previous temporary file and update to the new one
177
+ temp_output.unlink()
178
+ temp_output = next_temp
179
+
180
+ # Move the final merged file to the output location
181
+ if temp_output != output_file:
182
+ temp_output.replace(output_file)
183
+
184
+ print(f"✅ All FBM files merged successfully!", flush=True)
185
+ print(f"📊 Merged FBM file: {output_file}", flush=True)
186
+ print(f"📈 Merged {len(fbm_files)} FBM files", flush=True)
187
+
188
+ except Exception as e:
189
+ logger.error(f"Error during FBM merge operation: {e}")
190
+ import traceback
191
+ logger.debug(traceback.format_exc())
109
192
 
110
193
 
111
194
  def cmd_run(args):
@@ -168,6 +251,27 @@ _commands = [
168
251
  help="Output directory for merged report (optional)"
169
252
  )
170
253
  ]
254
+ ),
255
+ dict(
256
+ action=cmd_mergefbm,
257
+ command="mergefbm",
258
+ help="merge all FBM files in the specified folder and its subfolders using sum mode",
259
+ flags=[
260
+ dict(
261
+ name=["path"],
262
+ args=["-p", "--path"],
263
+ type=str,
264
+ required=True,
265
+ help="Path to the folder containing FBM files to merge"
266
+ ),
267
+ dict(
268
+ name=["output"],
269
+ args=["-o", "--output"],
270
+ type=str,
271
+ required=False,
272
+ help="Output file path for merged FBM file (optional, default: merged.fbm in the input folder)"
273
+ )
274
+ ]
171
275
  )
172
276
  ]
173
277
 
@@ -0,0 +1,52 @@
1
+ import flatbuffers
2
+ from flatbuffers.compat import import_numpy
3
+ np = import_numpy()
4
+
5
+ class ActivityTimes(object):
6
+ __slots__ = ['_tab']
7
+
8
+ @classmethod
9
+ def GetRootAs(cls, buf, offset=0):
10
+ n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
11
+ x = ActivityTimes()
12
+ x.Init(buf, n + offset)
13
+ return x
14
+
15
+ @classmethod
16
+ def GetRootAsActivityTimes(cls, buf, offset=0):
17
+ """This method is deprecated. Please switch to GetRootAs."""
18
+ return cls.GetRootAs(buf, offset)
19
+ # ActivityTimes
20
+ def Init(self, buf, pos):
21
+ self._tab = flatbuffers.table.Table(buf, pos)
22
+
23
+ # ActivityTimes
24
+ def Activity(self):
25
+ o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
26
+ if o != 0:
27
+ return self._tab.String(o + self._tab.Pos)
28
+ return None
29
+
30
+ # ActivityTimes
31
+ def Times(self):
32
+ o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
33
+ if o != 0:
34
+ return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
35
+ return 0
36
+
37
+ def Start(builder): builder.StartObject(2)
38
+ def ActivityTimesStart(builder):
39
+ """This method is deprecated. Please switch to Start."""
40
+ return Start(builder)
41
+ def AddActivity(builder, activity): builder.PrependUOffsetTRelativeSlot(0, flatbuffers.number_types.UOffsetTFlags.py_type(activity), 0)
42
+ def ActivityTimesAddActivity(builder, activity):
43
+ """This method is deprecated. Please switch to AddActivity."""
44
+ return AddActivity(builder, activity)
45
+ def AddTimes(builder, times): builder.PrependInt32Slot(1, times, 0)
46
+ def ActivityTimesAddTimes(builder, times):
47
+ """This method is deprecated. Please switch to AddTimes."""
48
+ return AddTimes(builder, times)
49
+ def End(builder): return builder.EndObject()
50
+ def ActivityTimesEnd(builder):
51
+ """This method is deprecated. Please switch to End."""
52
+ return End(builder)
@@ -0,0 +1,74 @@
1
+ import flatbuffers
2
+ from flatbuffers.compat import import_numpy
3
+ np = import_numpy()
4
+
5
+ class ReuseEntry(object):
6
+ __slots__ = ['_tab']
7
+
8
+ @classmethod
9
+ def GetRootAs(cls, buf, offset=0):
10
+ n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
11
+ x = ReuseEntry()
12
+ x.Init(buf, n + offset)
13
+ return x
14
+
15
+ @classmethod
16
+ def GetRootAsReuseEntry(cls, buf, offset=0):
17
+ """This method is deprecated. Please switch to GetRootAs."""
18
+ return cls.GetRootAs(buf, offset)
19
+ # ReuseEntry
20
+ def Init(self, buf, pos):
21
+ self._tab = flatbuffers.table.Table(buf, pos)
22
+
23
+ # ReuseEntry
24
+ def Action(self):
25
+ o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
26
+ if o != 0:
27
+ return self._tab.Get(flatbuffers.number_types.Uint64Flags, o + self._tab.Pos)
28
+ return 0
29
+
30
+ # ReuseEntry
31
+ def Targets(self, j):
32
+ o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
33
+ if o != 0:
34
+ x = self._tab.Vector(o)
35
+ x += flatbuffers.number_types.UOffsetTFlags.py_type(j) * 4
36
+ x = self._tab.Indirect(x)
37
+ from .ActivityTimes import ActivityTimes
38
+ obj = ActivityTimes()
39
+ obj.Init(self._tab.Bytes, x)
40
+ return obj
41
+ return None
42
+
43
+ # ReuseEntry
44
+ def TargetsLength(self):
45
+ o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
46
+ if o != 0:
47
+ return self._tab.VectorLen(o)
48
+ return 0
49
+
50
+ # ReuseEntry
51
+ def TargetsIsNone(self):
52
+ o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
53
+ return o == 0
54
+
55
+ def Start(builder): builder.StartObject(2)
56
+ def ReuseEntryStart(builder):
57
+ """This method is deprecated. Please switch to Start."""
58
+ return Start(builder)
59
+ def AddAction(builder, action): builder.PrependUint64Slot(0, action, 0)
60
+ def ReuseEntryAddAction(builder, action):
61
+ """This method is deprecated. Please switch to AddAction."""
62
+ return AddAction(builder, action)
63
+ def AddTargets(builder, targets): builder.PrependUOffsetTRelativeSlot(1, flatbuffers.number_types.UOffsetTFlags.py_type(targets), 0)
64
+ def ReuseEntryAddTargets(builder, targets):
65
+ """This method is deprecated. Please switch to AddTargets."""
66
+ return AddTargets(builder, targets)
67
+ def StartTargetsVector(builder, numElems): return builder.StartVector(4, numElems, 4)
68
+ def ReuseEntryStartTargetsVector(builder, numElems):
69
+ """This method is deprecated. Please switch to Start."""
70
+ return StartTargetsVector(builder, numElems)
71
+ def End(builder): return builder.EndObject()
72
+ def ReuseEntryEnd(builder):
73
+ """This method is deprecated. Please switch to End."""
74
+ return End(builder)
@@ -0,0 +1,63 @@
1
+ import flatbuffers
2
+ from flatbuffers.compat import import_numpy
3
+ np = import_numpy()
4
+
5
+ class ReuseModel(object):
6
+ __slots__ = ['_tab']
7
+
8
+ @classmethod
9
+ def GetRootAs(cls, buf, offset=0):
10
+ n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
11
+ x = ReuseModel()
12
+ x.Init(buf, n + offset)
13
+ return x
14
+
15
+ @classmethod
16
+ def GetRootAsReuseModel(cls, buf, offset=0):
17
+ """This method is deprecated. Please switch to GetRootAs."""
18
+ return cls.GetRootAs(buf, offset)
19
+ # ReuseModel
20
+ def Init(self, buf, pos):
21
+ self._tab = flatbuffers.table.Table(buf, pos)
22
+
23
+ # ReuseModel
24
+ def Model(self, j):
25
+ o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
26
+ if o != 0:
27
+ x = self._tab.Vector(o)
28
+ x += flatbuffers.number_types.UOffsetTFlags.py_type(j) * 4
29
+ x = self._tab.Indirect(x)
30
+ from .ReuseEntry import ReuseEntry
31
+ obj = ReuseEntry()
32
+ obj.Init(self._tab.Bytes, x)
33
+ return obj
34
+ return None
35
+
36
+ # ReuseModel
37
+ def ModelLength(self):
38
+ o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
39
+ if o != 0:
40
+ return self._tab.VectorLen(o)
41
+ return 0
42
+
43
+ # ReuseModel
44
+ def ModelIsNone(self):
45
+ o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
46
+ return o == 0
47
+
48
+ def Start(builder): builder.StartObject(1)
49
+ def ReuseModelStart(builder):
50
+ """This method is deprecated. Please switch to Start."""
51
+ return Start(builder)
52
+ def AddModel(builder, model): builder.PrependUOffsetTRelativeSlot(0, flatbuffers.number_types.UOffsetTFlags.py_type(model), 0)
53
+ def ReuseModelAddModel(builder, model):
54
+ """This method is deprecated. Please switch to AddModel."""
55
+ return AddModel(builder, model)
56
+ def StartModelVector(builder, numElems): return builder.StartVector(4, numElems, 4)
57
+ def ReuseModelStartModelVector(builder, numElems):
58
+ """This method is deprecated. Please switch to Start."""
59
+ return StartModelVector(builder, numElems)
60
+ def End(builder): return builder.EndObject()
61
+ def ReuseModelEnd(builder):
62
+ """This method is deprecated. Please switch to End."""
63
+ return End(builder)
@@ -0,0 +1,7 @@
1
+ from .ActivityTimes import ActivityTimes
2
+ from .ReuseEntry import ReuseEntry
3
+ from .ReuseModel import ReuseModel
4
+
5
+ __all__ = ['ActivityTimes', 'ReuseEntry', 'ReuseModel']
6
+
7
+