DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
toolbox.py
Go to the documentation of this file.
1from __future__ import print_function
2
3import re
4import signal
5
6import timing.common.definitions as defs
7import click
8import time
9
10from click import echo, style, secho
11
12# ------------------------------------------------------------------------------
13def hookDebugger(debugger='gdb'):
14 '''debugging helper, hooks debugger to running interpreter process'''
15
16 import os
17 pid = os.spawnvp(os.P_NOWAIT,
18 debugger, [debugger, '-q', 'python', str(os.getpid())])
19
20 # give debugger some time to attach to the python process
21 import time
22 time.sleep( 1 )
23
24 # verify the process' existence (will raise OSError if failed)
25 os.waitpid( pid, os.WNOHANG )
26 os.kill( pid, 0 )
27 return
28# ------------------------------------------------------------------------------
29
30# ------------------------------------------------------------------------------
31class IntRange(click.types.IntParamType):
32 """A parameter that works similar to :data:`click.INT` but restricts
33 the value to fit into a range. The default behavior is to fail if the
34 value falls outside the range, but it can also be silently clamped
35 between the two edges.
36
37 See :ref:`ranges` for an example.
38 """
39 name = 'integer range'
40
41 def __init__(self, min=None, max=None, clamp=False):
42 self.min = min
43 self.max = max
44 self.clamp = clamp
45
46 def convert(self, value, param, ctx):
47
48 if type(value) == str:
49 if value.startswith('0x'):
50 base = 16
51 elif value.startswith('0o'):
52 bae = 8
53 elif value.startswith('0b'):
54 base = 2
55 else:
56 base = 10
57 rv = int(value, base)
58 else:
59 rv = int(value)
60 if self.clamp:
61 if self.min is not None and rv < self.min:
62 return self.min
63 if self.max is not None and rv > self.max:
64 return self.max
65 if self.min is not None and rv < self.min or \
66 self.max is not None and rv > self.max:
67 if self.min is None:
68 self.fail('%s is bigger than the maximum valid value '
69 '%s.' % (rv, self.max), param, ctx)
70 elif self.max is None:
71 self.fail('%s is smaller than the minimum valid value '
72 '%s.' % (rv, self.min), param, ctx)
73 else:
74 self.fail('%s is not in the valid range of %s to %s.'
75 % (rv, self.min, self.max), param, ctx)
76 return rv
77
78 def __repr__(self):
79 return 'IntRange(%r, %r)' % (self.min, self.max)
80# ------------------------------------------------------------------------------
81
82
83# ------------------------------------------------------------------------------
84def sanitizeConnectionPaths(aConnectionPaths):
85
86 lConnectionList = aConnectionPaths.split(';')
87 for i,c in enumerate(lConnectionList):
88 if re.match('^\w+://.*', c) is None:
89 lConnectionList[i] = 'file://'+c
90 return ';'.join(lConnectionList)
91# ------------------------------------------------------------------------------
92
93# ------------------------------------------------------------------------------
94def completeDevices(ctx, args, incomplete):
95 import uhal
96 root_ctx = ctx.find_root()
97 devs = uhal.ConnectionManager(sanitizeConnectionPaths(str(root_ctx.params['connections']))).getDevices()
98 return [k for k in devs if incomplete in k]
99 # return []
100# ------------------------------------------------------------------------------
101
102
103# ------------------------------------------------------------------------------
104def readSubNodes(aNode, dispatch=True):
105 lValues = { n:aNode.getNode(n).read() for n in aNode.getNodes() }
106
107 if dispatch:
108 aNode.getClient().dispatch()
109 return lValues
110# ------------------------------------------------------------------------------
111
112
113# ------------------------------------------------------------------------------
114def resetSubNodes(aNode, aValue=0x0, dispatch=True):
115 """
116 Reset subnodes of aNode to aValue
117 """
118 lValues = { n:aNode.getNode(n).write(aValue) for n in aNode.getNodes() }
119 if dispatch:
120 aNode.getClient().dispatch()
121# ------------------------------------------------------------------------------
122
123# ------------------------------------------------------------------------------
124def hookDebugger(debugger='gdb'):
125 '''
126 debugging helper, hooks debugger to running interpreter process
127 '''
128
129 import os
130 pid = os.spawnvp(os.P_NOWAIT,
131 debugger, [debugger, '-q', 'python', str(os.getpid())])
132
133 # give debugger some time to attach to the python process
134 import time
135 time.sleep( 1 )
136
137 # verify the process' existence (will raise OSError if failed)
138 os.waitpid( pid, os.WNOHANG )
139 os.kill( pid, 0 )
140 return
141# ------------------------------------------------------------------------------
142
143# -----------------
144def validate_device(ctx, param, value):
145
146 lDevices = ctx.obj.mConnectionManager.getDevices()
147 if value not in lDevices:
148 raise click.BadParameter(
149 'Device must be one of '+
150 ', '.join(["'"+lId+"'" for lId in lDevices])
151 )
152 return value
153# -----------------
154
155
156# -----------------
157def complete_device(ctx, args, incomplete):
158 lDevices = ctx.obj.mConnectionManager.getDevices()
159
160 return [k for k in lDevices if incomplete in k]
161# -----------------
162
163# ------------------------------------------------------------------------------
164def split(ctx, param, value):
165 if value is None:
166 return []
167
168 return value.split(',')
169# ------------------------------------------------------------------------------
170
171# ------------------------------------------------------------------------------
172def __str2int__( value ):
173 if value.startswith('0x'):
174 base = 16
175 elif value.startswith('0o'):
176 bae = 8
177 elif value.startswith('0b'):
178 base = 2
179 else:
180 base = 10
181 return int(value, base)
182
183def split_ints(ctx, param, value):
184
185 sep = ','
186 dash = '-'
187
188 if value is None:
189 return []
190
191 numbers = []
192 for item in value.split(sep):
193 nums = item.split(dash)
194 if len(nums) == 1:
195 # single entry
196 numbers.append(__str2int__(item))
197 elif len(nums) == 2:
198 # range
199 i, j = __str2int__(nums[0]), __str2int__(nums[1])
200 if i > j:
201 click.ClickException('Invalid interval '+item)
202 numbers.extend(list(range(i,j+1)))
203 else:
204 click.ClickException('Malformed option (comma separated list expected): {}'.format(value))
205
206 return numbers
207# ------------------------------------------------------------------------------
208
209
210# ------------------------------------------------------------------------------
211def printRegTable(aRegs, aHeader=True, sort=True):
212 echo ( format_reg_table(aRegs, aHeader, sort) )
213# ------------------------------------------------------------------------------
214
215# ------------------------------------------------------------------------------
216def printDictTable(aDict, aHdr=True, aSort=True, aFmtr=None):
217 echo ( formatDictTable(aDict, aHdr, aSort, aFmtr) )
218# ------------------------------------------------------------------------------
219
220
221# ------------------------------------------------------------------------------
222def collateTables(t1, t2):
223 l1 = t1.split('\n')
224 l2 = t2.split('\n')
225
226 col1 = max([len(escape_ansi(l)) for l in l1])
227 col2 = max([len(escape_ansi(l)) for l in l2])
228
229 nrows = max(len(l1), len(l2));
230
231 l1 += [''] * (nrows - len(l1))
232 l2 += [''] * (nrows - len(l2))
233 fmt = '\'{:<%d}\' \'{:<%d}\'' % (col1, col2)
234 for c1,c2 in zip(l1, l2):
235 print (c1 + ' '*(col1-len(escape_ansi(c1))), ' ' ,c2 + ' '*(col2-len(escape_ansi(c2))))
236# ------------------------------------------------------------------------------
237
238# ------------------------------------------------------------------------------
239kReEscapeAnsi = re.compile(r'(\x9B|\x1B\[)[0-?]*[ -/]*[@-~]')
240
241def escape_ansi(line):
242 return kReEscapeAnsi.sub('', line)
243# ------------------------------------------------------------------------------
244
245# ------------------------------------------------------------------------------
246def formatTStamp( aRawTStamp, clock_frequency_hz ):
247 ts = int(aRawTStamp[0]) + int((aRawTStamp[1]) << 32)
248
249 lSubSec = ts % clock_frequency_hz
250 lSecFromEpoch = ts / clock_frequency_hz
251
252 return time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.localtime(lSecFromEpoch))
253# ------------------------------------------------------------------------------
254
255
256# ------------------------------------------------------------------------------
257def tstamp2int( aRawTStamp ):
258 return int(aRawTStamp[0]) + int((aRawTStamp[1]) << 32)
259# ------------------------------------------------------------------------------
260
261
262# ------------------------------------------------------------------------------
263def fmtEpState(aState):
264 aState = aState.value()
265 return '{} ({})'.format(defs.kEpStates[aState], hex(aState)) if aState in defs.kEpStates else hex(aState)
266# ------------------------------------------------------------------------------
267
268
269# ------------------------------------------------------------------------------
270class InterruptHandler(object):
271
272 def __init__(self, sig=signal.SIGINT):
273 self.sig = sig
274
275 def __enter__(self):
276
277 self.interrupted = False
278 self.released = False
279
280 self.original_handler = signal.getsignal(self.sig)
281
282 def handler(signum, frame):
283 self.release()
284 self.interrupted = True
285
286 signal.signal(self.sig, handler)
287
288 return self
289
290 def __exit__(self, type, value, tb):
291 self.release()
292
293 def release(self):
294
295 if self.released:
296 return False
297
298 signal.signal(self.sig, self.original_handler)
299
300 self.released = True
301
302 return True
303# ------------------------------------------------------------------------------
__init__(self, min=None, max=None, clamp=False)
Definition toolbox.py:41
convert(self, value, param, ctx)
Definition toolbox.py:46
__init__(self, sig=signal.SIGINT)
Definition toolbox.py:272
__exit__(self, type, value, tb)
Definition toolbox.py:290
resetSubNodes(aNode, aValue=0x0, dispatch=True)
Definition toolbox.py:114
formatTStamp(aRawTStamp, clock_frequency_hz)
Definition toolbox.py:246
readSubNodes(aNode, dispatch=True)
Definition toolbox.py:104
sanitizeConnectionPaths(aConnectionPaths)
Definition toolbox.py:84
fmtEpState(aState)
Definition toolbox.py:263
split(ctx, param, value)
Definition toolbox.py:164
hookDebugger(debugger='gdb')
Definition toolbox.py:13
completeDevices(ctx, args, incomplete)
Definition toolbox.py:94
printRegTable(aRegs, aHeader=True, sort=True)
Definition toolbox.py:211
printDictTable(aDict, aHdr=True, aSort=True, aFmtr=None)
Definition toolbox.py:216
tstamp2int(aRawTStamp)
Definition toolbox.py:257
complete_device(ctx, args, incomplete)
Definition toolbox.py:157
validate_device(ctx, param, value)
Definition toolbox.py:144
collateTables(t1, t2)
Definition toolbox.py:222
split_ints(ctx, param, value)
Definition toolbox.py:183