1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 """Module containing the status singleton object."""
24
25
26 from os import F_OK, access
27 from os.path import sep
28 import platform
29 from re import search
30 import sys
31 from threading import Lock, RLock
32
33
34 from compat import Queue
35 from relax_errors import RelaxError
36
37
39 """The relax status singleton class."""
40
41
42 _instance = None
43
66
67
69 """Determine, with a bit of magic, the relax installation path.
70
71 @return: The relax installation path. With a Mac OS X app, this will be the path to the 'Resources'.
72 @rtype: str
73 """
74
75
76 file_to_find = 'relax_errors.py'
77
78
79 for path in sys.path:
80
81 if access(path + sep + file_to_find, F_OK):
82 return path
83
84
85 for path in sys.path:
86
87 if search('Resources', path):
88
89 bits = path.split('Resources')
90 mac_path = bits[0] + 'Resources'
91
92
93 return mac_path
94
95
96 return sys.path[0]
97
98
100 """Initialise all the status data structures."""
101
102
103 self.exec_lock = Exec_lock()
104
105
106 self.pipe_lock = Relax_lock(name='pipe_lock')
107
108
109 self.spin_lock = Relax_lock(name='spin_lock')
110
111
112 self.exception_queue = Queue()
113
114
115 self.auto_analysis = {}
116 self.current_analysis = None
117
118
119 self.controller_max_entries = 100000
120
121
122 self.skipped_tests = []
123 """The skipped tests list. Each element should be a list of the test case name, the missing Python module, and the name of the test suite category (i.e. 'system' or 'unit')."""
124
125
126 self._setup_observers()
127
128
129 if platform.uname()[0] in ['Windows', 'Microsoft']:
130 self.text_width = 79
131 else:
132 self.text_width = 100
133
134
136 """Set up all the observer objects."""
137
138
139 self.observers = Observer_container()
140
141
142 self.observers.auto_analyses = Observer('auto_analyses')
143
144
145 self.observers.pipe_alteration = Observer('pipe_alteration')
146
147
148 self.observers.gui_uf = Observer('gui_uf')
149
150
151 self.observers.gui_analysis = Observer('gui_analysis')
152
153
154 self.observers.reset = Observer('reset')
155
156
157 self.observers.exec_lock = Observer('exec_lock')
158
159
160 self.observers.result_file = Observer('result_file')
161
162
163 self.observers.state_load = Observer('state_load')
164
165
167 """Initialise a status container for an auto-analysis.
168
169 @param name: The unique name of the auto-analysis. This will act as a key.
170 @type name: str.
171 @param type: The type of auto-analysis.
172 @type type: str
173 """
174
175
176 self.auto_analysis[name] = Auto_analysis(name, type)
177
178
180 """Reset the status object to its initial state."""
181
182
183 self._setup()
184
185
186
188 """The auto-analysis status container."""
189
191 """Initialise the auto-analysis status object.
192
193 @param name: The unique name of the auto-analysis. This will act as a key.
194 @type name: str.
195 @param type: The type of auto-analysis.
196 @type type: str
197 """
198
199
200 self._status = Status()
201
202
203 self.__dict__['type'] = type
204
205
206 self.__dict__['fin'] = False
207
208
209 self.__dict__['mc_number'] = None
210
211
213 """Replacement __setattr__() method.
214
215 @param name: The name of the attribute.
216 @type name: str
217 @param value: The value of the attribute.
218 @type value: anything
219 """
220
221
222 self.__dict__[name] = value
223
224
225 self._status.observers.auto_analyses.notify()
226
227
228
230 """A type of locking object for locking execution of relax."""
231
233 """Set up the lock-like object.
234
235 @keyword fake_lock: A flag which is True will allow this object to be debugged as the locking mechanism is turned off.
236 @type fake_lock: bool
237 """
238
239
240 self._fake_lock = fake_lock
241
242
243 self._lock = Lock()
244
245
246 self._status = Status()
247
248
249 self._name = None
250 self._mode = None
251
252
253 self._script_nest = 0
254
255
256 self._auto_from_script = False
257
258
259 if self._fake_lock:
260 self.log = open('lock.log', 'w')
261
262
263 - def acquire(self, name, mode='script'):
264 """Simulate the Lock.acquire() mechanism.
265
266 @param name: The name of the locking code.
267 @type name: str
268 @keyword mode: The mode of the code trying to obtain the lock. This can be one of 'script' for the scripting interface or 'auto-analysis' for the auto-analyses.
269 @type mode: str
270 """
271
272
273 if self._status.debug:
274 sys.stdout.write("debug> Execution lock: Acquisition by '%s' ('%s' mode).\n" % (name, mode))
275
276
277 if mode == 'script' and self._mode == 'script' and self.locked():
278
279 self._script_nest += 1
280
281
282 if self._fake_lock:
283 self.log.write("Nested by %s (to level %s)\n" % (name, self._script_nest))
284 self.log.flush()
285
286
287 return
288
289
290 if self.locked() and self._mode == 'script' and mode == 'auto-analysis':
291
292 if self._fake_lock:
293 self.log.write("Skipped unlocking of '%s' lock by '%s'\n" % (self._name, name))
294 self.log.flush()
295
296
297 self._auto_from_script = True
298
299
300 return
301
302
303 self._name = name
304 self._mode = mode
305
306
307 if self._fake_lock:
308 self.log.write("Acquired by %s\n" % self._name)
309 self.log.flush()
310 return
311
312
313 lock = self._lock.acquire()
314
315
316 status = Status()
317 status.observers.exec_lock.notify()
318
319
320 return lock
321
322
324 """Simulate the Lock.locked() mechanism."""
325
326
327 if self._fake_lock:
328 if self._name:
329 return True
330 else:
331 return False
332
333
334 return self._lock.locked()
335
336
338 """Simulate the Lock.release() mechanism."""
339
340
341 if self._status.debug:
342 sys.stdout.write("debug> Execution lock: Release by '%s' ('%s' mode).\n" % (self._name, self._mode))
343
344
345 if self._script_nest:
346
347 if self._fake_lock:
348 self.log.write("Script termination, nest decrement (%s -> %s)\n" % (self._script_nest, self._script_nest-1))
349 self.log.flush()
350
351
352 self._script_nest -= 1
353
354
355 return
356
357
358 if self._auto_from_script:
359
360 if self._fake_lock:
361 self.log.write("Auto-analysis launched from script, skipping release.\n")
362 self.log.flush()
363
364
365 self._auto_from_script = False
366
367
368 return
369
370
371 self._name = None
372 self._mode = None
373
374
375 if self._fake_lock:
376
377 text = 'Release'
378
379
380 if hasattr(self, 'test_name'):
381 text = text + 'd by %s' % self.test_name
382
383
384 self.log.write("%s\n\n" % text)
385 self.log.flush()
386 return
387
388
389 release = self._lock.release()
390
391
392 status = Status()
393 status.observers.exec_lock.notify()
394
395
396 return release
397
398
399
401 """The observer design pattern base class."""
402
404 """Set up the object.
405
406 @keyword name: The special name for the observer object, used in debugging.
407 @type name: str
408 """
409
410
411 self._name = name
412
413
414 self._callback = {}
415 self._method_names = {}
416
417
418 self._keys = []
419
420
421 self._status = Status()
422
423
425 """Notify all observers of the state change."""
426
427
428 for key in self._keys:
429
430 if self._status.debug:
431 if self._method_names[key]:
432 sys.stdout.write("debug> Observer: '%s' notifying the '%s' method %s().\n" % (self._name, key, self._method_names[key]))
433 else:
434 sys.stdout.write("debug> Observer: '%s' notifying '%s'.\n" % (self._name, key))
435
436
437 self._callback[key]()
438
439
440 - def register(self, key, method, method_name=None):
441 """Register a method to be called when the state changes.
442
443 @param key: The key to identify the observer's method.
444 @type key: str
445 @param method: The observer's method to be called after a state change.
446 @type method: method
447 @keyword method_name: The optional method name used in debugging printouts.
448 @type method_name: str or None
449 """
450
451
452 if key in self._keys:
453 raise RelaxError("The observer '%s' already exists." % key)
454
455
456 if key == None:
457 raise RelaxError("The observer key must be supplied.")
458
459
460 if self._status.debug:
461 if method_name:
462 sys.stdout.write("debug> Observer: '%s' registering the '%s' method %s().\n" % (self._name, key, method_name))
463 else:
464 sys.stdout.write("debug> Observer: '%s' registering '%s'.\n" % (self._name, key))
465
466
467 self._callback[key] = method
468
469
470 self._method_names[key] = method_name
471
472
473 self._keys.append(key)
474
475
477 """Reset the object."""
478
479
480 if self._status.debug:
481 sys.stdout.write("debug> Resetting observer '%s'.\n" % self._name)
482
483
484 self._callback = {}
485
486
487 self._keys = []
488
489
491 """Unregister the method corresponding to the key.
492
493 @param key: The key to identify the observer's method.
494 @type key: str
495 """
496
497
498 if self._status.debug:
499 sys.stdout.write("debug> Observer: '%s' unregistering '%s'.\n" % (self._name, key))
500
501
502 if key not in self._keys:
503 if self._status.debug:
504 sys.stdout.write("debug> The key '%s' does not exist.\n" % key)
505 return
506
507
508 self._callback.pop(key)
509
510
511 self._method_names.pop(key)
512
513
514 self._keys.remove(key)
515
516
517
519 """A type of locking object for relax."""
520
521 - def __init__(self, name='unknown', fake_lock=False):
522 """Set up the lock-like object.
523
524 @keyword name: The special name for the lock, used in debugging.
525 @type name: str
526 @keyword fake_lock: A flag which is True will allow this object to be debugged as the locking mechanism is turned off.
527 @type fake_lock: bool
528 """
529
530
531 self.name = name
532 self._fake_lock = fake_lock
533
534
535 self._lock = RLock()
536
537
538 self._status = Status()
539
540
541 if self._fake_lock:
542
543 self._lock_level = 0
544
545
546 - def acquire(self, acquirer='unknown'):
547 """Simulate the RLock.acquire() mechanism.
548
549 @keyword acquirer: The optional name of the acquirer.
550 @type acquirer: str
551 """
552
553
554 if self._status.debug:
555 sys.stdout.write("debug> Lock '%s': Acquisition by '%s'.\n" % (self.name, acquirer))
556
557
558 if self._fake_lock:
559
560 self._lock_level += 1
561
562
563 if self._lock_level > 1:
564 raise
565
566
567 return
568
569
570 lock = self._lock.acquire()
571
572
573 return lock
574
575
577 """Simulate the RLock.locked() mechanism."""
578
579
580 return self._lock.locked()
581
582
583 - def release(self, acquirer='unknown'):
584 """Simulate the RLock.release() mechanism.
585
586 @keyword acquirer: The optional name of the acquirer.
587 @type acquirer: str
588 """
589
590
591 if self._status.debug:
592 sys.stdout.write("debug> Lock '%s': Release by '%s'.\n" % (self.name, acquirer))
593
594
595 if self._fake_lock:
596
597 self._lock_level -= 1
598
599
600 return
601
602
603 release = self._lock.release()
604
605
606 return release
607
608
609
611 """The container for holding all the observer objects."""
612
614 """Print out info about all the status objects."""
615
616
617 blacklist = list(self.__class__.__dict__.keys() + dict.__dict__.keys())
618
619
620 for name in dir(self):
621
622 if name in blacklist:
623 continue
624
625
626 obj = getattr(self, name)
627
628
629 print("Observer '%s' keys: %s" % (obj._name, obj._keys))
630