Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
S2-group
GitHub Repository: S2-group/android-runner
Path: blob/master/AndroidRunner/util.py
629 views
1
import errno
2
import psutil
3
import json
4
import time
5
import os
6
import re
7
from collections import OrderedDict
8
from slugify import slugify
9
import csv
10
11
12
class ConfigError(Exception):
13
pass
14
15
class FileNotFoundError(Exception):
16
def __init__(self, filename):
17
Exception.__init__(self, '[Errno %s] %s: \'%s\'' % (errno.ENOENT, os.strerror(errno.ENOENT), filename))
18
19
20
class FileFormatError(Exception):
21
pass
22
23
24
def write_to_file(filename, rows):
25
with open(filename, 'w', encoding='utf-8') as f:
26
writer = csv.DictWriter(f, list(rows[0].keys()))
27
writer.writeheader()
28
writer.writerows(rows)
29
30
def load_json(path):
31
"""Load a JSON file from path, and returns an ordered dictionary or throws exceptions on formatting errors"""
32
try:
33
with open(path, 'r') as f:
34
try:
35
return json.loads(f.read(), object_pairs_hook=OrderedDict)
36
except ValueError:
37
raise FileFormatError(path)
38
except IOError as e:
39
if e.errno == errno.ENOENT:
40
raise FileNotFoundError(path)
41
else:
42
raise e
43
44
def list_subdir(a_dir):
45
"""List immediate subdirectories of a_dir"""
46
# https://stackoverflow.com/a/800201
47
return [name for name in os.listdir(a_dir)
48
if os.path.isdir(os.path.join(a_dir, name))]
49
50
def makedirs(path):
51
"""Create a directory on path if it does not exist"""
52
# https://stackoverflow.com/a/5032238
53
try:
54
os.makedirs(path)
55
except OSError as e:
56
if e.errno != errno.EEXIST:
57
raise
58
59
def wait_until(function, timeout, period=0.25, *args):
60
""" Block/suspend/sleep for a maximum of <timeout> seconds until function <function> returns True. Execute <function> every
61
<period> seconds. If <function> still returns False after <timeout> seconds throw a TimeourError.
62
63
Parameters
64
----------
65
function : callable
66
A Python function or method
67
timeout : float
68
Time in seconds until TimeoutError is thrown.
69
period : float
70
Time in seconds between each <function> call.
71
args : any
72
Arguments that are passed to <function>.
73
74
Raises
75
-------
76
TimeoutError
77
If <function> still returns False after <timeout> seconds.
78
79
Returns
80
-------
81
None
82
Nothing is returned.
83
"""
84
must_end = time.time() + timeout
85
while time.time() < must_end:
86
if function(*args):
87
return
88
time.sleep(period)
89
raise TimeoutError
90
91
# noinspection PyTypeChecker
92
def slugify_dir(value):
93
"""
94
Normalizes string, converts to lowercase, removes non-alpha characters,
95
and converts spaces to hyphens. Regex_pattern prevents slugify from removing
96
an underscore and replacing it with a hyphen.
97
"""
98
regex_pattern = r'[^\w]'
99
slug = slugify(value, regex_pattern=regex_pattern)
100
return slug
101
102
def keyboardinterrupt_handler(func):
103
""" Decorator that ensures that a KeyBoardInterrupt is handled
104
cleanly by terminating the associated process.
105
106
Is necessary as a KeyBoardInterrupt is send to a process and all of its child processes.
107
Each process therefore needs its own handler.
108
109
Can be used by putting @keyboardinterrupt_handler above a function.
110
"""
111
def inner_function(*args, **kwargs):
112
try:
113
func(*args, **kwargs)
114
except KeyboardInterrupt as e:
115
this_process = psutil.Process()
116
this_process.terminate()
117
return inner_function
118