Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

# encoding: utf-8 

from __future__ import print_function, division, absolute_import 

 

from .errors import ConsistencyError 

 

import functools 

import glob 

import hashlib 

import inspect 

import os 

import re 

import shutil 

import signal 

import sys 

 

 

def hexdigest(data): 

"""computes md5 hex digtes of given data of type bytes""" 

assert isinstance(data, bytes) 

digester = hashlib.md5() 

digester.update(data) 

return digester.hexdigest() 

 

 

def hexdigest_file(path): 

data = open(path, "rb").read() 

return hexdigest(data) 

 

 

def reformat_row(row, limit): 

new_rows = [] 

while True: 

new_rows.append([cell[:limit] for cell in row]) 

row = [cell[limit:] for cell in row] 

if all(len(c) == 0 for c in row): 

break 

return new_rows 

 

 

def print_table(header, rows, max_col_size=40, indent="", file=sys.stderr): 

"""pretty print table for given headers and rows. 

 

headers list of strings 

rows: list of list of values 

""" 

 

headers = reformat_row(header, max_col_size) 

new_rows = [] 

for row in rows: 

new_rows.extend(reformat_row(list(map(str, row)), max_col_size)) 

 

rows = new_rows 

 

col_sizes = list(map(len, headers[0])) 

for row in headers[1:] + rows: 

col_sizes = list(max(s, len(c)) for (s, c) in zip(col_sizes, map(str, row))) 

 

formatters = ["%-{}s".format(s) for s in col_sizes] 

for header in headers: 

for name, f in zip(header, formatters): 

print(indent, end="", file=file) 

print(f % name, end=" ", file=file) 

print(file=file) 

for c in col_sizes: 

print(indent, end="", file=file) 

print("-" * c, end=" ", file=file) 

print(file=file) 

for row in rows: 

for cell, f in zip(row, formatters): 

print(indent, end="", file=file) 

print(f % cell, end=" ", file=file) 

print(file=file) 

 

 

def print_signals(signals, indent="", file=sys.stdout): 

assert isinstance(signals, list) 

assert all(isinstance(signal, dict) for signal in signals) 

has_xyz = all("x" in signal and "y" in signal and "z" in signal for signal in signals) 

has_site = all("site" in signal for signal in signals) 

if not has_xyz or has_site: 

raise ConsistencyError("all signals must have either (x, y, z) or site fields") 

 

if has_xyz: 

header = ("timestamp", "parameter", "value", "x", "y", "z") 

else: 

header = ("timestamp", "parameter", "value", "site") 

 

rows = [[signal.get(field) for field in header] for signal in signals] 

print_table(header, rows, indent=indent, file=file) 

 

 

def find_executable(name, default=None): 

for folder in os.environ["PATH"].split(os.pathsep): 

path = os.path.join(folder, name) 

if os.path.exists(path): 

if os.access(path, os.X_OK): 

return path 

return default 

 

 

def abs_folder(path): 

return os.path.dirname(os.path.abspath(path)) 

 

 

def here(): 

"""determines folder containing the caller of this function""" 

# we go one step up in the call stack and read __file__ as set there: 

return abs_folder(inspect.stack()[1].frame.f_globals["__file__"]) 

 

 

class TimeoutError(Exception): 

pass 

 

 

def run_timed(function, args=None, kwargs=None, timeout_in_seconds=None): 

"""run given function with given args / kwargs, stopping execution if the function execution 

needs more than timeout_in_seconds seconds. 

 

In case timeout_in_seconds is None we wait until the function execution ends. 

""" 

 

args = () if args is None else args 

kwargs = {} if kwargs is None else kwargs 

 

if timeout_in_seconds is None: 

return function(*args, **kwargs) 

 

def handle_timeout(*a): 

signal.setitimer(signal.ITIMER_REAL, 0.0) 

raise TimeoutError() 

 

# we use signalt.setitimer here, signal.alarm only accepts integer values for the time span 

signal.setitimer(signal.ITIMER_REAL, timeout_in_seconds) 

signal.signal(signal.SIGALRM, handle_timeout) 

try: 

return function(*args, **kwargs) 

finally: 

signal.setitimer(signal.ITIMER_REAL, 0.0) 

 

 

def list_folder_recursive(folder, skip_hidden=True): 

folder = os.path.normpath(folder) # remove eventually preceedings dots 

for (dirname, __, files) in sorted(os.walk(folder)): 

if dirname.startswith(".") and skip_hidden: 

continue 

for file in sorted(files): 

if file.startswith(".") and skip_hidden: 

continue 

yield os.path.relpath(os.path.normpath(os.path.join(dirname, file)), folder) 

 

 

def copy(from_, to): 

"""copies file from from_ to to, if target folder does not exist all needed intermediate 

folders are created""" 

assert os.path.exists(from_) 

target_folder = os.path.dirname(to) 

if not os.path.exists(target_folder): 

os.makedirs(target_folder) 

shutil.copy(from_, to) 

 

 

def iter_to_list(function): 

@functools.wraps(function) 

def inner(*a, **kw): 

return list(function(*a, **kw)) 

return inner 

 

 

def is_int(txt): 

try: 

int(txt) 

return True 

except ValueError: 

return False 

 

 

def enumerate_filename(*pathes): 

next_numbers = [] 

parts = [] 

for path in pathes: 

filename = os.path.basename(path) 

dirname = os.path.dirname(path) 

 

name_stem, ext = os.path.splitext(filename) 

# remove trailing "_NNN" if exists: 

name_stem = re.split("_\d+$", name_stem)[0] 

 

stem = os.path.join(dirname, name_stem) 

parts.append((stem, ext)) 

files = glob.glob(stem + "*" + ext) 

appendices = [file[len(stem):-len(ext)].lstrip("_") for file in files] 

numbers = [int(a) for a in appendices if is_int(a)] 

if not numbers: 

next_number = 0 

else: 

next_number = max(numbers) + 1 

next_numbers.append(next_number) 

next_number = max(next_numbers) 

return [stem + "_{:d}".format(next_number) + ext for stem, ext in parts]