Kea2-python 0.1.2__py3-none-any.whl → 0.1.3__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/keaUtils.py +40 -25
- kea2/u2Driver.py +122 -108
- {kea2_python-0.1.2.dist-info → kea2_python-0.1.3.dist-info}/METADATA +3 -2
- {kea2_python-0.1.2.dist-info → kea2_python-0.1.3.dist-info}/RECORD +8 -8
- {kea2_python-0.1.2.dist-info → kea2_python-0.1.3.dist-info}/WHEEL +0 -0
- {kea2_python-0.1.2.dist-info → kea2_python-0.1.3.dist-info}/entry_points.txt +0 -0
- {kea2_python-0.1.2.dist-info → kea2_python-0.1.3.dist-info}/licenses/LICENSE +0 -0
- {kea2_python-0.1.2.dist-info → kea2_python-0.1.3.dist-info}/top_level.txt +0 -0
kea2/keaUtils.py
CHANGED
|
@@ -14,7 +14,7 @@ from .bug_report_generator import BugReportGenerator
|
|
|
14
14
|
from .resultSyncer import ResultSyncer
|
|
15
15
|
from .logWatcher import LogWatcher
|
|
16
16
|
from .utils import TimeStamp, getProjectRoot, getLogger
|
|
17
|
-
from .u2Driver import StaticU2UiObject
|
|
17
|
+
from .u2Driver import StaticU2UiObject
|
|
18
18
|
from .fastbotManager import FastbotManager
|
|
19
19
|
import uiautomator2 as u2
|
|
20
20
|
import types
|
|
@@ -344,8 +344,6 @@ class KeaTestRunner(TextTestRunner):
|
|
|
344
344
|
if self.options.profile_period and self.stepsCount % self.options.profile_period == 0:
|
|
345
345
|
resultSyncer.sync_event.set()
|
|
346
346
|
|
|
347
|
-
print(f"{len(propsSatisfiedPrecond)} precond satisfied.", flush=True)
|
|
348
|
-
|
|
349
347
|
# Go to the next round if no precond satisfied
|
|
350
348
|
if len(propsSatisfiedPrecond) == 0:
|
|
351
349
|
continue
|
|
@@ -478,18 +476,25 @@ class KeaTestRunner(TextTestRunner):
|
|
|
478
476
|
if not precond(test):
|
|
479
477
|
valid = False
|
|
480
478
|
break
|
|
479
|
+
except u2.UiObjectNotFoundError as e:
|
|
480
|
+
valid = False
|
|
481
|
+
break
|
|
481
482
|
except Exception as e:
|
|
482
|
-
|
|
483
|
+
logger.error(f"Error when checking precond: {getFullPropName(test)}")
|
|
483
484
|
traceback.print_exc()
|
|
484
485
|
valid = False
|
|
485
486
|
break
|
|
486
487
|
# if all the precond passed. make it the candidate prop.
|
|
487
488
|
if valid:
|
|
488
|
-
logger.debug(f"precond satisfied: {getFullPropName(test)}")
|
|
489
489
|
if result.getExcuted(test) >= getattr(prop, MAX_TRIES_MARKER, float("inf")):
|
|
490
|
-
|
|
490
|
+
print(f"{getFullPropName(test)} has reached its max_tries. Skip.", flush=True)
|
|
491
491
|
continue
|
|
492
492
|
validProps[propName] = test
|
|
493
|
+
|
|
494
|
+
print(f"{len(validProps)} precond satisfied.", flush=True)
|
|
495
|
+
if len(validProps) > 0:
|
|
496
|
+
print("[INFO] Valid properties:",flush=True)
|
|
497
|
+
print("\n".join([f' - {getFullPropName(p)}' for p in validProps.values()]), flush=True)
|
|
493
498
|
return validProps
|
|
494
499
|
|
|
495
500
|
def _logScript(self, execution_info:Dict):
|
|
@@ -619,46 +624,56 @@ class KeaTestRunner(TextTestRunner):
|
|
|
619
624
|
"""
|
|
620
625
|
def _get_xpath_widgets(func):
|
|
621
626
|
blocked_set = set()
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
627
|
+
script_driver = self.options.Driver.getScriptDriver()
|
|
628
|
+
preconds = getattr(func, PRECONDITIONS_MARKER, [])
|
|
629
|
+
|
|
630
|
+
def preconds_pass(preconds):
|
|
631
|
+
try:
|
|
632
|
+
return all(precond(script_driver) for precond in preconds)
|
|
633
|
+
except u2.UiObjectNotFoundError as e:
|
|
634
|
+
return False
|
|
635
|
+
except Exception as e:
|
|
636
|
+
logger.error(f"Error processing precond. Check if precond: {e}")
|
|
637
|
+
traceback.print_exc()
|
|
638
|
+
return False
|
|
639
|
+
|
|
640
|
+
if preconds_pass(preconds):
|
|
641
|
+
try:
|
|
626
642
|
_widgets = func(self.options.Driver.getStaticChecker())
|
|
627
643
|
_widgets = _widgets if isinstance(_widgets, list) else [_widgets]
|
|
628
644
|
for w in _widgets:
|
|
629
645
|
if isinstance(w, StaticU2UiObject):
|
|
630
|
-
xpath = selector_to_xpath(w.selector
|
|
631
|
-
|
|
646
|
+
xpath = w.selector_to_xpath(w.selector)
|
|
647
|
+
if xpath != '//error':
|
|
648
|
+
blocked_set.add(xpath)
|
|
632
649
|
elif isinstance(w, u2.xpath.XPathSelector):
|
|
633
650
|
xpath = w._parent.xpath
|
|
634
651
|
blocked_set.add(xpath)
|
|
635
652
|
else:
|
|
636
|
-
logger.
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
653
|
+
logger.error(f"block widget defined in {func.__name__} Not supported.")
|
|
654
|
+
except Exception as e:
|
|
655
|
+
logger.error(f"Error processing blocked widgets in: {func}")
|
|
656
|
+
logger.error(e)
|
|
657
|
+
traceback.print_exc()
|
|
640
658
|
return blocked_set
|
|
641
659
|
|
|
642
|
-
|
|
660
|
+
result = {
|
|
643
661
|
"widgets": set(),
|
|
644
662
|
"trees": set()
|
|
645
663
|
}
|
|
646
664
|
|
|
647
|
-
|
|
648
665
|
for func in self._blockWidgetFuncs["widgets"]:
|
|
649
666
|
widgets = _get_xpath_widgets(func)
|
|
650
|
-
|
|
651
|
-
|
|
667
|
+
result["widgets"].update(widgets)
|
|
652
668
|
|
|
653
669
|
for func in self._blockWidgetFuncs["trees"]:
|
|
654
670
|
trees = _get_xpath_widgets(func)
|
|
655
|
-
|
|
671
|
+
result["trees"].update(trees)
|
|
656
672
|
|
|
673
|
+
result["widgets"] = list(result["widgets"] - result["trees"])
|
|
674
|
+
result["trees"] = list(result["trees"])
|
|
657
675
|
|
|
658
|
-
|
|
659
|
-
res["trees"] = list(res["trees"])
|
|
660
|
-
|
|
661
|
-
return res
|
|
676
|
+
return result
|
|
662
677
|
|
|
663
678
|
|
|
664
679
|
def __del__(self):
|
kea2/u2Driver.py
CHANGED
|
@@ -100,39 +100,105 @@ class StaticU2UiObject(u2.UiObject):
|
|
|
100
100
|
return filterDict[originKey]
|
|
101
101
|
return originKey
|
|
102
102
|
|
|
103
|
-
def
|
|
103
|
+
def selector_to_xpath(self, selector: u2.Selector, is_initial: bool = True) -> str:
|
|
104
|
+
"""
|
|
105
|
+
Convert a u2 Selector into an XPath expression compatible with Java Android UI controls.
|
|
104
106
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
"""
|
|
109
|
-
new_kwargs = dict()
|
|
110
|
-
SPECIAL_KEY = {"mask", "childOrSibling", "childOrSiblingSelector"}
|
|
111
|
-
for key, val in kwargs.items():
|
|
112
|
-
if key in SPECIAL_KEY:
|
|
113
|
-
continue
|
|
114
|
-
key = self._transferU2Keys(key)
|
|
115
|
-
new_kwargs[key] = val
|
|
116
|
-
return new_kwargs
|
|
107
|
+
Args:
|
|
108
|
+
selector (u2.Selector): A u2 Selector object
|
|
109
|
+
is_initial (bool): Whether it is the initial node, defaults to True
|
|
117
110
|
|
|
118
|
-
|
|
111
|
+
Returns:
|
|
112
|
+
str: The corresponding XPath expression
|
|
113
|
+
"""
|
|
114
|
+
try:
|
|
119
115
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
116
|
+
xpath = ".//node" if is_initial else "node"
|
|
117
|
+
|
|
118
|
+
conditions = []
|
|
119
|
+
|
|
120
|
+
if "className" in selector:
|
|
121
|
+
conditions.insert(0, f"[@class='{selector['className']}']")
|
|
122
|
+
|
|
123
|
+
if "text" in selector:
|
|
124
|
+
conditions.append(f"[@text='{selector['text']}']")
|
|
125
|
+
elif "textContains" in selector:
|
|
126
|
+
conditions.append(f"[contains(@text, '{selector['textContains']}')]")
|
|
127
|
+
elif "textStartsWith" in selector:
|
|
128
|
+
conditions.append(f"[starts-with(@text, '{selector['textStartsWith']}')]")
|
|
129
|
+
elif "textMatches" in selector:
|
|
130
|
+
raise NotImplementedError("'textMatches' syntax is not supported")
|
|
131
|
+
|
|
132
|
+
if "description" in selector:
|
|
133
|
+
conditions.append(f"[@content-desc='{selector['description']}']")
|
|
134
|
+
elif "descriptionContains" in selector:
|
|
135
|
+
conditions.append(f"[contains(@content-desc, '{selector['descriptionContains']}')]")
|
|
136
|
+
elif "descriptionStartsWith" in selector:
|
|
137
|
+
conditions.append(f"[starts-with(@content-desc, '{selector['descriptionStartsWith']}')]")
|
|
138
|
+
elif "descriptionMatches" in selector:
|
|
139
|
+
raise NotImplementedError("'descriptionMatches' syntax is not supported")
|
|
140
|
+
|
|
141
|
+
if "packageName" in selector:
|
|
142
|
+
conditions.append(f"[@package='{selector['packageName']}']")
|
|
143
|
+
elif "packageNameMatches" in selector:
|
|
144
|
+
raise NotImplementedError("'packageNameMatches' syntax is not supported")
|
|
145
|
+
|
|
146
|
+
if "resourceId" in selector:
|
|
147
|
+
conditions.append(f"[@resource-id='{selector['resourceId']}']")
|
|
148
|
+
elif "resourceIdMatches" in selector:
|
|
149
|
+
raise NotImplementedError("'resourceIdMatches' syntax is not supported")
|
|
150
|
+
|
|
151
|
+
bool_props = ["checkable", "checked", "clickable", "longClickable", "scrollable", "enabled", "focusable",
|
|
152
|
+
"focused", "selected", "covered"]
|
|
153
|
+
|
|
154
|
+
def str_to_bool(value):
|
|
155
|
+
"""Convert string 'true'/'false' to boolean, or return original value if already boolean"""
|
|
156
|
+
if isinstance(value, str):
|
|
157
|
+
return value.lower() == "true"
|
|
158
|
+
return bool(value)
|
|
159
|
+
|
|
160
|
+
for prop in bool_props:
|
|
161
|
+
if prop in selector:
|
|
162
|
+
bool_value = str_to_bool(selector[prop])
|
|
163
|
+
value = "true" if bool_value else "false"
|
|
164
|
+
conditions.append(f"[@{prop}='{value}']")
|
|
165
|
+
|
|
166
|
+
if "index" in selector:
|
|
167
|
+
conditions.append(f"[@index='{selector['index']}']")
|
|
168
|
+
|
|
169
|
+
xpath += "".join(conditions)
|
|
170
|
+
|
|
171
|
+
if "childOrSibling" in selector and selector["childOrSibling"]:
|
|
172
|
+
for i, relation in enumerate(selector["childOrSibling"]):
|
|
173
|
+
sub_selector = selector["childOrSiblingSelector"][i]
|
|
174
|
+
sub_xpath = self.selector_to_xpath(sub_selector, False)
|
|
175
|
+
|
|
176
|
+
if relation == "child":
|
|
177
|
+
xpath += f"//{sub_xpath}"
|
|
178
|
+
elif relation == "sibling":
|
|
179
|
+
cur_root = xpath
|
|
180
|
+
following_sibling = cur_root + f"/following-sibling::{sub_xpath}"
|
|
181
|
+
preceding_sibling = cur_root + f"/preceding-sibling::{sub_xpath}"
|
|
182
|
+
xpath = f"({following_sibling} | {preceding_sibling})"
|
|
183
|
+
if "instance" in selector:
|
|
184
|
+
xpath = f"({xpath})[{selector['instance'] + 1}]"
|
|
185
|
+
|
|
186
|
+
return xpath
|
|
187
|
+
|
|
188
|
+
except Exception as e:
|
|
189
|
+
print(f"Error occurred during selector conversion: {e}")
|
|
190
|
+
return "//error"
|
|
125
191
|
|
|
126
192
|
|
|
127
193
|
@property
|
|
128
194
|
def exists(self):
|
|
129
|
-
|
|
130
|
-
xpath = self.
|
|
195
|
+
set_covered_to_deepest_node(self.selector)
|
|
196
|
+
xpath = self.selector_to_xpath(self.selector)
|
|
131
197
|
matched_widgets = self.session.xml.xpath(xpath)
|
|
132
198
|
return bool(matched_widgets)
|
|
133
199
|
|
|
134
200
|
def __len__(self):
|
|
135
|
-
xpath = self.
|
|
201
|
+
xpath = self.selector_to_xpath(self.selector)
|
|
136
202
|
matched_widgets = self.session.xml.xpath(xpath)
|
|
137
203
|
return len(matched_widgets)
|
|
138
204
|
|
|
@@ -141,6 +207,9 @@ class StaticU2UiObject(u2.UiObject):
|
|
|
141
207
|
|
|
142
208
|
def sibling(self, **kwargs):
|
|
143
209
|
return StaticU2UiObject(self.session, self.selector.clone().sibling(**kwargs))
|
|
210
|
+
|
|
211
|
+
def __getattr__(self, attr):
|
|
212
|
+
return getattr(super(), attr)
|
|
144
213
|
|
|
145
214
|
|
|
146
215
|
def _get_bounds(raw_bounds):
|
|
@@ -227,7 +296,9 @@ class U2StaticDevice(u2.Device):
|
|
|
227
296
|
self._script_driver = script_driver
|
|
228
297
|
|
|
229
298
|
def __call__(self, **kwargs):
|
|
230
|
-
|
|
299
|
+
ui = StaticU2UiObject(session=self, selector=u2.Selector(**kwargs))
|
|
300
|
+
ui.jsonrpc = self._script_driver.jsonrpc
|
|
301
|
+
return ui
|
|
231
302
|
|
|
232
303
|
@property
|
|
233
304
|
def xpath(self) -> u2.xpath.XPathEntry:
|
|
@@ -274,7 +345,12 @@ class U2StaticChecker(AbstractStaticChecker):
|
|
|
274
345
|
def setHierarchy(self, hierarchy: str):
|
|
275
346
|
if hierarchy is None:
|
|
276
347
|
return
|
|
277
|
-
|
|
348
|
+
if isinstance(hierarchy, str):
|
|
349
|
+
self.d.xml = etree.fromstring(hierarchy.encode("utf-8"))
|
|
350
|
+
elif isinstance(hierarchy, etree._Element):
|
|
351
|
+
self.d.xml = hierarchy
|
|
352
|
+
elif isinstance(hierarchy, etree._ElementTree):
|
|
353
|
+
self.d.xml = hierarchy.getroot()
|
|
278
354
|
_HindenWidgetFilter(self.d.xml)
|
|
279
355
|
|
|
280
356
|
def getInstance(self, hierarchy: str=None):
|
|
@@ -330,90 +406,6 @@ def forward_port(self, remote: Union[int, str]) -> int:
|
|
|
330
406
|
logger.debug(f"forwading port: tcp:{local_port} -> {remote}")
|
|
331
407
|
return local_port
|
|
332
408
|
|
|
333
|
-
|
|
334
|
-
def selector_to_xpath(selector: u2.Selector, is_initial: bool = True) -> str:
|
|
335
|
-
"""
|
|
336
|
-
Convert a u2 Selector into an XPath expression compatible with Java Android UI controls.
|
|
337
|
-
|
|
338
|
-
Args:
|
|
339
|
-
selector (u2.Selector): A u2 Selector object
|
|
340
|
-
is_initial (bool): Whether it is the initial node, defaults to True
|
|
341
|
-
|
|
342
|
-
Returns:
|
|
343
|
-
str: The corresponding XPath expression
|
|
344
|
-
"""
|
|
345
|
-
try:
|
|
346
|
-
if is_initial:
|
|
347
|
-
xpath = ".//node"
|
|
348
|
-
else:
|
|
349
|
-
xpath = "node"
|
|
350
|
-
|
|
351
|
-
conditions = []
|
|
352
|
-
|
|
353
|
-
if "className" in selector:
|
|
354
|
-
conditions.insert(0, f"[@class='{selector['className']}']") # 将 className 条件放在前面
|
|
355
|
-
|
|
356
|
-
if "text" in selector:
|
|
357
|
-
conditions.append(f"[@text='{selector['text']}']")
|
|
358
|
-
elif "textContains" in selector:
|
|
359
|
-
conditions.append(f"[contains(@text, '{selector['textContains']}')]")
|
|
360
|
-
elif "textMatches" in selector:
|
|
361
|
-
conditions.append(f"[re:match(@text, '{selector['textMatches']}')]")
|
|
362
|
-
elif "textStartsWith" in selector:
|
|
363
|
-
conditions.append(f"[starts-with(@text, '{selector['textStartsWith']}')]")
|
|
364
|
-
|
|
365
|
-
if "description" in selector:
|
|
366
|
-
conditions.append(f"[@content-desc='{selector['description']}']")
|
|
367
|
-
elif "descriptionContains" in selector:
|
|
368
|
-
conditions.append(f"[contains(@content-desc, '{selector['descriptionContains']}')]")
|
|
369
|
-
elif "descriptionMatches" in selector:
|
|
370
|
-
conditions.append(f"[re:match(@content-desc, '{selector['descriptionMatches']}')]")
|
|
371
|
-
elif "descriptionStartsWith" in selector:
|
|
372
|
-
conditions.append(f"[starts-with(@content-desc, '{selector['descriptionStartsWith']}')]")
|
|
373
|
-
|
|
374
|
-
if "packageName" in selector:
|
|
375
|
-
conditions.append(f"[@package='{selector['packageName']}']")
|
|
376
|
-
elif "packageNameMatches" in selector:
|
|
377
|
-
conditions.append(f"[re:match(@package, '{selector['packageNameMatches']}')]")
|
|
378
|
-
|
|
379
|
-
if "resourceId" in selector:
|
|
380
|
-
conditions.append(f"[@resource-id='{selector['resourceId']}']")
|
|
381
|
-
elif "resourceIdMatches" in selector:
|
|
382
|
-
conditions.append(f"[re:match(@resource-id, '{selector['resourceIdMatches']}')]")
|
|
383
|
-
|
|
384
|
-
bool_props = [
|
|
385
|
-
"checkable", "checked", "clickable", "longClickable", "scrollable",
|
|
386
|
-
"enabled", "focusable", "focused", "selected", "covered"
|
|
387
|
-
]
|
|
388
|
-
for prop in bool_props:
|
|
389
|
-
if prop in selector:
|
|
390
|
-
value = "true" if selector[prop] else "false"
|
|
391
|
-
conditions.append(f"[@{prop}='{value}']")
|
|
392
|
-
|
|
393
|
-
if "index" in selector:
|
|
394
|
-
conditions.append(f"[@index='{selector['index']}']")
|
|
395
|
-
elif "instance" in selector:
|
|
396
|
-
conditions.append(f"[@instance='{selector['instance']}']")
|
|
397
|
-
|
|
398
|
-
xpath += "".join(conditions)
|
|
399
|
-
|
|
400
|
-
if "childOrSibling" in selector and selector["childOrSibling"]:
|
|
401
|
-
for i, relation in enumerate(selector["childOrSibling"]):
|
|
402
|
-
sub_selector = selector["childOrSiblingSelector"][i]
|
|
403
|
-
sub_xpath = selector_to_xpath(sub_selector, False) # 递归处理子选择器
|
|
404
|
-
|
|
405
|
-
if relation == "child":
|
|
406
|
-
xpath += f"/{sub_xpath}"
|
|
407
|
-
elif relation == "sibling":
|
|
408
|
-
xpath_initial = xpath
|
|
409
|
-
xpath = '(' + xpath_initial + f"/following-sibling::{sub_xpath} | " + xpath_initial + f"/preceding-sibling::{sub_xpath})"
|
|
410
|
-
|
|
411
|
-
return xpath
|
|
412
|
-
|
|
413
|
-
except Exception as e:
|
|
414
|
-
print(f"Error occurred during selector conversion: {e}")
|
|
415
|
-
return "//error"
|
|
416
|
-
|
|
417
409
|
def is_port_in_use(port: int) -> bool:
|
|
418
410
|
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
|
419
411
|
return s.connect_ex(('127.0.0.1', port)) == 0
|
|
@@ -435,3 +427,25 @@ def get_free_port():
|
|
|
435
427
|
if not is_port_in_use(port):
|
|
436
428
|
return port
|
|
437
429
|
raise RuntimeError("No free port found")
|
|
430
|
+
|
|
431
|
+
def set_covered_to_deepest_node(selector: u2.Selector):
|
|
432
|
+
|
|
433
|
+
def find_deepest_nodes(node):
|
|
434
|
+
deepest_node = None
|
|
435
|
+
is_leaf = True
|
|
436
|
+
if "childOrSibling" in node and node["childOrSibling"]:
|
|
437
|
+
for i, relation in enumerate(node["childOrSibling"]):
|
|
438
|
+
sub_selector = node["childOrSiblingSelector"][i]
|
|
439
|
+
deepest_node = find_deepest_nodes(sub_selector)
|
|
440
|
+
is_leaf = False
|
|
441
|
+
|
|
442
|
+
if is_leaf:
|
|
443
|
+
deepest_node = node
|
|
444
|
+
return deepest_node
|
|
445
|
+
|
|
446
|
+
deepest_node = find_deepest_nodes(selector)
|
|
447
|
+
|
|
448
|
+
if deepest_node is not None:
|
|
449
|
+
dict.update(deepest_node, {"covered": False})
|
|
450
|
+
|
|
451
|
+
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: Kea2-python
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
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
|
|
@@ -17,8 +17,9 @@ Dynamic: license-file
|
|
|
17
17
|
[](https://pepy.tech/projects/kea2-python)
|
|
18
18
|

|
|
19
19
|
|
|
20
|
+
|
|
20
21
|
<div>
|
|
21
|
-
<img src="https://github.com/user-attachments/assets/
|
|
22
|
+
<img src="https://github.com/user-attachments/assets/aa5839fc-4542-46f6-918b-c9f891356c84" style="border-radius: 14px; width: 20%; height: 20%;"/>
|
|
22
23
|
</div>
|
|
23
24
|
|
|
24
25
|
## About
|
|
@@ -4,11 +4,11 @@ kea2/adbUtils.py,sha256=j6goAAzV1Ikmv26DZEE0Oi8S1PrejcV1Io3u_Xw4ws4,9910
|
|
|
4
4
|
kea2/bug_report_generator.py,sha256=G5h9nI1w1UaksjF3gkMC8UrXgiNmtU1D5VIuPiciOak,22792
|
|
5
5
|
kea2/cli.py,sha256=YgWOe5JB0_WBTKyBShBEymhLIqj6K5gNR4Aaj6Pbtn0,2796
|
|
6
6
|
kea2/fastbotManager.py,sha256=Ru7Aitcjlem52npJJLg-3KX5ctCoflaaLG4N0IgQ2QU,4828
|
|
7
|
-
kea2/keaUtils.py,sha256=
|
|
7
|
+
kea2/keaUtils.py,sha256=XylgzSS4_DcQn3SjbJJ2bA82v0LQV1qmbgZPRjBh-ZE,25932
|
|
8
8
|
kea2/kea_launcher.py,sha256=xDMHAzD2Ig2Dug9K4MzkTPwieKvLASmjUahEst8aaVU,5291
|
|
9
9
|
kea2/logWatcher.py,sha256=qpIsflbP37eX5b4EaWnrqyPbGP9lzQhRr3ainGFfZeI,2211
|
|
10
10
|
kea2/resultSyncer.py,sha256=f3qfne8WQCo1AA3cwx9IZzLdenjjMWbEpAqPdvddAqk,1984
|
|
11
|
-
kea2/u2Driver.py,sha256=
|
|
11
|
+
kea2/u2Driver.py,sha256=__rP_d5uY029_eAxPNUiNw3lq8PVLf8QZRe3uwZEmb4,15779
|
|
12
12
|
kea2/utils.py,sha256=8b4y-_B7knKRN_HqpWZM900IdRiZXwmzQnduVVN0GxQ,1384
|
|
13
13
|
kea2/assets/fastbot-thirdpart.jar,sha256=0SZ_OoZFWDGMnazgXKceHgKvXdUDoIa3Gb2bcifaikk,85664
|
|
14
14
|
kea2/assets/framework.jar,sha256=rTluOJJKj2DFwh7ascXso1udYdWv00BxBwSQ3Vmv-fw,1149240
|
|
@@ -28,9 +28,9 @@ kea2/assets/fastbot_libs/armeabi-v7a/libfastbot_native.so,sha256=UV8bhaiPoPKdd3q
|
|
|
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
30
|
kea2/templates/bug_report_template.html,sha256=sQ0Uu8SPeOIiyX5vPPTZPVKxh9-9raAZcCjSRS8YFe0,40624
|
|
31
|
-
kea2_python-0.1.
|
|
32
|
-
kea2_python-0.1.
|
|
33
|
-
kea2_python-0.1.
|
|
34
|
-
kea2_python-0.1.
|
|
35
|
-
kea2_python-0.1.
|
|
36
|
-
kea2_python-0.1.
|
|
31
|
+
kea2_python-0.1.3.dist-info/licenses/LICENSE,sha256=nM9PPjcsXVo5SzNsjRqWgA-gdJlwqZZcRDSC6Qf6bVE,2034
|
|
32
|
+
kea2_python-0.1.3.dist-info/METADATA,sha256=Y2ICVucbBO8JybwZMNKtTQSl_rJdndmKkD4PAVPwQWk,13234
|
|
33
|
+
kea2_python-0.1.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
34
|
+
kea2_python-0.1.3.dist-info/entry_points.txt,sha256=mFX06TyxXiUAJQ6JZn8QHzfn8n5R8_KJ5W-pTm_fRCA,39
|
|
35
|
+
kea2_python-0.1.3.dist-info/top_level.txt,sha256=TsgNH4PQoNOVhegpO7AcjutMVWp6Z4KDL1pBH9FnMmk,5
|
|
36
|
+
kea2_python-0.1.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|