Mercurial > repos > mahtabm > ensembl
comparison variant_effect_predictor/Bio/EnsEMBL/Utils/Exception.pm @ 0:1f6dce3d34e0
Uploaded
author | mahtabm |
---|---|
date | Thu, 11 Apr 2013 02:01:53 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1f6dce3d34e0 |
---|---|
1 =head1 LICENSE | |
2 | |
3 Copyright (c) 1999-2012 The European Bioinformatics Institute and | |
4 Genome Research Limited. All rights reserved. | |
5 | |
6 This software is distributed under a modified Apache license. | |
7 For license details, please see | |
8 | |
9 http://www.ensembl.org/info/about/code_licence.html | |
10 | |
11 =head1 CONTACT | |
12 | |
13 Please email comments or questions to the public Ensembl | |
14 developers list at <dev@ensembl.org>. | |
15 | |
16 Questions may also be sent to the Ensembl help desk at | |
17 <helpdesk@ensembl.org>. | |
18 | |
19 =cut | |
20 | |
21 =head1 NAME | |
22 | |
23 Bio::EnsEMBL::Utils::Exception - Utility functions for error handling | |
24 | |
25 =head1 SYNOPSIS | |
26 | |
27 use Bio::EnsEMBL::Utils::Exception | |
28 qw(throw warning deprecate verbose try catch); | |
29 | |
30 or to get all methods just | |
31 | |
32 use Bio::EnsEMBL::Utils::Exception; | |
33 | |
34 eval { throw("this is an exception with a stack trace") }; | |
35 if ($@) { | |
36 print "Caught exception:\n$@"; | |
37 } | |
38 | |
39 # Or you can us the try/catch confortable syntax instead to deal with | |
40 # throw or die. Don't forget the ";" after the catch block. With | |
41 # this syntax, the original $@ is in $_ in the catch subroutine. | |
42 | |
43 try { | |
44 throw("this is an exception with a stack trace"); | |
45 } | |
46 catch { print "Caught exception:\n$_" }; | |
47 | |
48 # silence warnings | |
49 verbose('OFF'); | |
50 | |
51 warning('this is a silent warning'); | |
52 | |
53 #show deprecated and warning messages but not info | |
54 verbose('DEPRECATE'); | |
55 | |
56 warning('this is a warning'); | |
57 | |
58 # show all messages | |
59 verbose('ALL'); | |
60 | |
61 info('this is an informational message'); | |
62 | |
63 sub my_sub { deprecate('use other_sub() instead') } | |
64 | |
65 verbose('EXCEPTION'); | |
66 info( 'This is a high priority info message.', 1000 ); | |
67 | |
68 =head1 DESCRIPTION | |
69 | |
70 This is derived from the Bio::Root module in BioPerl. Some formatting | |
71 has been changed and the deprecate function has been added. Most | |
72 notably the object methods are now static class methods that can be | |
73 called without inheriting from Bio::Root or Bio::EnsEMBL::Root. This is | |
74 especially useful for throwing exceptions with stack traces outside of a | |
75 blessed context. | |
76 | |
77 The originaly implementations of these methods were by Steve Chervitz | |
78 and refactored by Ewan Birney. | |
79 | |
80 It is recommended that these functions be used instead of inheriting | |
81 unnecessarily from the Bio::EnsEMBL::Root or Bio::Root object. The | |
82 functions exported by this package provide a set of useful error | |
83 handling methods. | |
84 | |
85 =head1 METHODS | |
86 | |
87 =cut | |
88 | |
89 package Bio::EnsEMBL::Utils::Exception; | |
90 | |
91 use strict; | |
92 use warnings; | |
93 | |
94 use Bio::EnsEMBL::ApiVersion; | |
95 | |
96 use Exporter; | |
97 | |
98 use vars qw(@ISA @EXPORT); | |
99 | |
100 @ISA = qw(Exporter); | |
101 @EXPORT = qw(throw warning stack_trace_dump | |
102 stack_trace verbose deprecate info try catch); | |
103 | |
104 my $VERBOSITY = 3000; | |
105 my $DEFAULT_INFO = 4000; | |
106 my $DEFAULT_DEPRECATE = 3000; | |
107 my $DEFAULT_WARNING = 2000; | |
108 my $DEFAULT_EXCEPTION = 1000; | |
109 | |
110 | |
111 =head2 throw | |
112 | |
113 Arg [1] : string $msg | |
114 Arg [2] : (optional) int $level | |
115 override the default level of exception throwing | |
116 Example : use Bio::EnsEMBL::Utils::Exception qw(throw); | |
117 throw('We have a problem'); | |
118 Description: Throws an exception which if not caught by an eval will | |
119 provide a stack trace to STDERR and die. If the verbosity level | |
120 is lower than the level of the throw, then no error message is | |
121 displayed but the program will still die (unless the exception | |
122 is caught). | |
123 Returntype : none | |
124 Exceptions : thrown every time | |
125 Caller : generally on error | |
126 | |
127 =cut | |
128 | |
129 sub throw { | |
130 my $string = shift; | |
131 | |
132 # For backwards compatibility with Bio::EnsEMBL::Root::throw: Allow | |
133 # to be called as an object method as well as class method. Root | |
134 # function now deprecated so call will have the string instead. | |
135 | |
136 $string = shift if ( ref($string) ); # Skip object if one provided. | |
137 $string = shift if ( $string eq "Bio::EnsEMBL::Utils::Exception" ); | |
138 | |
139 my $level = shift; | |
140 $level = $DEFAULT_EXCEPTION if ( !defined($level) ); | |
141 | |
142 if ( $VERBOSITY < $level ) { | |
143 die("\n"); # still die, but silently | |
144 } | |
145 | |
146 my $std = stack_trace_dump(3); | |
147 | |
148 my $out = sprintf( | |
149 "\n" . | |
150 "-------------------- EXCEPTION --------------------\n" . | |
151 "MSG: %s\n" . | |
152 "%s" . | |
153 "Date (localtime) = %s\n" . | |
154 "Ensembl API version = %s\n" . | |
155 "---------------------------------------------------\n", | |
156 $string, $std, scalar( localtime() ), software_version() ); | |
157 | |
158 die($out); | |
159 } ## end sub throw | |
160 | |
161 | |
162 | |
163 =head2 warning | |
164 | |
165 Arg [1] : string warning(message); | |
166 Arg [2] : (optional) int level | |
167 Override the default level of this warning changning the level | |
168 of verbosity at which it is displayed. | |
169 Example : use Bio::EnsEMBL::Utils::Exception qw(warning) | |
170 warning('This is a warning'); | |
171 Description: If the verbosity level is higher or equal to the level of this | |
172 warning then a warning message is printed to STDERR. If the | |
173 verbosity lower then nothing is done. Under the default | |
174 levels of warning and verbosity warnings will be displayed. | |
175 Returntype : none | |
176 Exceptions : warning every time | |
177 Caller : general | |
178 | |
179 =cut | |
180 | |
181 sub warning { | |
182 my $string = shift; | |
183 | |
184 # See throw() for this: | |
185 $string = shift if ( ref($string) ); # Skip object if one provided. | |
186 $string = shift if ( $string eq "Bio::EnsEMBL::Utils::Exception" ); | |
187 | |
188 my $level = shift; | |
189 $level = $DEFAULT_WARNING if ( !defined($level) ); | |
190 | |
191 return if ( $VERBOSITY < $level ); | |
192 | |
193 my @caller = caller; | |
194 my $line = $caller[2] || ''; | |
195 | |
196 # Use only two sub-dirs for brevity when reporting the file name. | |
197 my $file; | |
198 my @path = split( /\//, $caller[1] ); | |
199 $file = pop(@path); | |
200 my $i = 0; | |
201 while ( @path && $i < 2 ) { | |
202 $i++; | |
203 $file = pop(@path) . "/$file"; | |
204 } | |
205 | |
206 @caller = caller(1); | |
207 my $caller_line; | |
208 my $caller_file; | |
209 $i = 0; | |
210 if (@caller) { | |
211 @path = split( /\//, $caller[1] ); | |
212 $caller_line = $caller[2]; | |
213 $caller_file = pop(@path); | |
214 while ( @path && $i < 2 ) { | |
215 $i++; | |
216 $caller_file = pop(@path) . "/$caller_file"; | |
217 } | |
218 } | |
219 | |
220 my $out = | |
221 sprintf( "\n" . | |
222 "-------------------- WARNING ----------------------\n" . | |
223 "MSG: %s\n" . | |
224 "FILE: %s LINE: %d\n", | |
225 $string, $file, $line ); | |
226 | |
227 if ( defined($caller_file) ) { | |
228 $out .= sprintf( "CALLED BY: %s LINE: %d\n", $caller_file, | |
229 $caller_line ); | |
230 } | |
231 $out .= sprintf( | |
232 "Date (localtime) = %s\n" . | |
233 "Ensembl API version = %s\n" . | |
234 "---------------------------------------------------\n", | |
235 scalar( localtime() ), software_version() ); | |
236 | |
237 warn($out); | |
238 | |
239 } ## end sub warning | |
240 | |
241 | |
242 | |
243 =head2 info | |
244 | |
245 Arg [1] : string $string | |
246 The message to be displayed | |
247 Arg [2] : (optional) int $level | |
248 Override the default level of this message so it is displayed at | |
249 a different level of verbosity than it normally would be. | |
250 Example : use Bio::EnsEMBL::Utils::Exception qw(verbose info) | |
251 Description: This prints an info message to STDERR if verbosity is higher | |
252 than the level of the message. By default info messages are not | |
253 displayed. | |
254 Returntype : none | |
255 Exceptions : none | |
256 Caller : general | |
257 | |
258 =cut | |
259 | |
260 sub info { | |
261 my $string = shift; | |
262 $string = shift if($string eq "Bio::EnsEMBL::Utils::Exception"); | |
263 my $level = shift; | |
264 | |
265 $level = $DEFAULT_INFO if(!defined($level)); | |
266 | |
267 return if($VERBOSITY < $level); | |
268 | |
269 print STDERR "INFO: $string\n"; | |
270 } | |
271 | |
272 | |
273 | |
274 =head2 verbose | |
275 | |
276 Arg [1] : (optional) int | |
277 Example : use Bio::EnsEMBL::Utils::Exception qw(verbose warning); | |
278 #turn warnings and everything more important on (e.g. exception) | |
279 verbose('WARNING'); | |
280 warning("Warning displayed"); | |
281 info("This won't be displayed"); | |
282 deprecate("This won't be diplayed"); | |
283 | |
284 #turn exception messages on | |
285 verbose('EXCEPTION'); | |
286 warning("This won't do anything"); | |
287 throw("Die with a message"); | |
288 | |
289 #turn everying off | |
290 verbose('OFF'); #same as verbose(0); | |
291 warning("This won't do anything"); | |
292 throw("Die silently without a message"); | |
293 | |
294 #turn on all messages | |
295 verbose('ALL'); | |
296 info("All messages are now displayed"); | |
297 | |
298 if(verbose() > 3000) { | |
299 print "Verbosity is pretty high"; | |
300 } | |
301 | |
302 Description: Gets/Sets verbosity level which defines which messages are | |
303 to be displayed. An integer value may be passed or one of the | |
304 following strings: | |
305 'OFF' (= 0) | |
306 'EXCEPTION' (= 1000) | |
307 'WARNING' (= 2000) | |
308 'DEPRECATE' (= 3000) | |
309 'INFO' (= 4000) | |
310 'ALL' (= 1000000) | |
311 | |
312 Returntype : int | |
313 Exceptions : none | |
314 Caller : general | |
315 | |
316 =cut | |
317 | |
318 | |
319 sub verbose { | |
320 if(@_) { | |
321 my $verbosity = shift; | |
322 $verbosity = shift if($verbosity eq "Bio::EnsEMBL::Utils::Exception"); | |
323 if($verbosity =~ /\d+/) { #check if verbosity is an integer | |
324 $VERBOSITY = $verbosity; | |
325 } else { | |
326 $verbosity = uc($verbosity); | |
327 if($verbosity eq 'OFF' || $verbosity eq 'NOTHING' || | |
328 $verbosity eq 'NONE') { | |
329 $VERBOSITY = 0; | |
330 } elsif($verbosity eq 'EXCEPTION' || $verbosity eq 'THROW') { | |
331 $VERBOSITY = $DEFAULT_EXCEPTION; | |
332 } elsif($verbosity eq 'WARNING' || $verbosity eq 'WARN') { | |
333 $VERBOSITY = $DEFAULT_WARNING; | |
334 } elsif($verbosity eq 'DEPRECATE' || $verbosity eq 'DEPRECATED') { | |
335 $VERBOSITY = $DEFAULT_DEPRECATE; | |
336 } elsif($verbosity eq 'INFO') { | |
337 $VERBOSITY = $DEFAULT_INFO; | |
338 } elsif($verbosity eq 'ON' || $verbosity eq 'ALL') { | |
339 $VERBOSITY = 1e6; | |
340 } else { | |
341 $VERBOSITY = $DEFAULT_WARNING; | |
342 warning("Unknown level of verbosity: $verbosity"); | |
343 } | |
344 } | |
345 } | |
346 | |
347 return $VERBOSITY; | |
348 } | |
349 | |
350 | |
351 | |
352 =head2 stack_trace_dump | |
353 | |
354 Arg [1] : (optional) int $levels | |
355 The number of levels to ignore from the top of the stack when | |
356 creating the dump. This is useful when this is called internally | |
357 from a warning or throw function when the immediate caller and | |
358 stack_trace_dump function calls are themselves uninteresting. | |
359 Example : use Bio::EnsEMBL::Utils::Exception qw(stack_trace_dump); | |
360 print STDERR stack_trace_dump(); | |
361 Description: Returns a stack trace formatted as a string | |
362 Returntype : string | |
363 Exceptions : none | |
364 Caller : general, throw, warning | |
365 | |
366 =cut | |
367 | |
368 sub stack_trace_dump{ | |
369 my @stack = stack_trace(); | |
370 | |
371 my $levels = 2; #default is 2 levels so stack_trace_dump call is not present | |
372 $levels = shift if(@_); | |
373 $levels = shift if($levels eq "Bio::EnsEMBL::Utils::Exception"); | |
374 $levels = 1 if($levels < 1); | |
375 | |
376 while($levels) { | |
377 $levels--; | |
378 shift @stack; | |
379 } | |
380 | |
381 my $out; | |
382 my ($module,$function,$file,$position); | |
383 | |
384 | |
385 foreach my $stack ( @stack) { | |
386 ($module,$file,$position,$function) = @{$stack}; | |
387 $out .= "STACK $function $file:$position\n"; | |
388 } | |
389 | |
390 return $out; | |
391 } | |
392 | |
393 | |
394 | |
395 =head2 stack_trace | |
396 | |
397 Arg [1] : none | |
398 Example : use Bio::EnsEMBL::Utils::Exception qw(stack_trace) | |
399 Description: Gives an array to a reference of arrays with stack trace info | |
400 each coming from the caller(stack_number) call | |
401 Returntype : array of listrefs of strings | |
402 Exceptions : none | |
403 Caller : general, stack_trace_dump() | |
404 | |
405 =cut | |
406 | |
407 sub stack_trace { | |
408 my $i = 0; | |
409 my @out; | |
410 my $prev; | |
411 while ( my @call = caller($i++)) { | |
412 | |
413 # major annoyance that caller puts caller context as | |
414 # function name. Hence some monkeying around... | |
415 $prev->[3] = $call[3]; | |
416 push(@out,$prev); | |
417 $prev = \@call; | |
418 } | |
419 $prev->[3] = 'toplevel'; | |
420 push(@out,$prev); | |
421 return @out; | |
422 } | |
423 | |
424 | |
425 =head2 deprecate | |
426 | |
427 Arg [1] : string $mesg | |
428 A message describing why a method is deprecated | |
429 Example : use Bio::EnsEMBL::Utils::Exception qw(deprecate) | |
430 sub old_sub { | |
431 deprecate('Please use new_sub() instead'); | |
432 } | |
433 Description: Prints a warning to STDERR that the method which called | |
434 deprecate() is deprecated. Also prints the line number and | |
435 file from which the deprecated method was called. Deprecated | |
436 warnings only appear once for each location the method was | |
437 called from. No message is displayed if the level of verbosity | |
438 is lower than the level of the warning. | |
439 Returntype : none | |
440 Exceptions : warning every time | |
441 Caller : deprecated methods | |
442 | |
443 =cut | |
444 | |
445 my %DEPRECATED; | |
446 | |
447 sub deprecate { | |
448 my $mesg = shift; | |
449 $mesg = shift if($mesg eq "Bio::EnsEMBL::Utils::Exception"); #skip object if one provided | |
450 | |
451 my $level = shift; | |
452 | |
453 $level = $DEFAULT_DEPRECATE if(!defined($level)); | |
454 | |
455 return if($VERBOSITY < $level); | |
456 | |
457 my @caller = caller(1); | |
458 my $subname = $caller[3] ; | |
459 my $line = $caller[2]; | |
460 | |
461 #use only 2 subdirs for brevity when reporting the filename | |
462 my $file; | |
463 my @path = $caller[1]; | |
464 $file = pop(@path); | |
465 my $i = 0; | |
466 while(@path && $i < 2) { | |
467 $i++; | |
468 $file .= pop(@path); | |
469 } | |
470 | |
471 #keep track of who called this method so that the warning is only displayed | |
472 #once per deprecated call | |
473 return if $DEPRECATED{"$line:$file:$subname"}; | |
474 | |
475 if ( $VERBOSITY > -1 ) { | |
476 print STDERR | |
477 "\n------------------ DEPRECATED ---------------------\n" | |
478 . "Deprecated method call in file $file line $line.\n" | |
479 . "Method $subname is deprecated.\n" | |
480 . "$mesg\n" | |
481 . "Ensembl API version = " | |
482 . software_version() . "\n" | |
483 . "---------------------------------------------------\n"; | |
484 } | |
485 | |
486 $DEPRECATED{"$line:$file:$subname"} = 1; | |
487 } | |
488 | |
489 =head2 try/catch | |
490 | |
491 Arg [1] : anonymous subroutine | |
492 the block to be tried | |
493 Arg [2] : return value of the catch function | |
494 Example : use Bio::EnsEMBL::Utils::Exception qw(throw try catch) | |
495 The syntax is: | |
496 try { block1 } catch { block2 }; | |
497 { block1 } is the 1st argument | |
498 catch { block2 } is the 2nd argument | |
499 e.g. | |
500 try { | |
501 throw("this is an exception with a stack trace"); | |
502 } catch { | |
503 print "Caught exception:\n$_"; | |
504 }; | |
505 In block2, $_ is assigned the value of the first | |
506 throw or die statement executed in block 1. | |
507 | |
508 Description: Replaces the classical syntax | |
509 eval { block1 }; | |
510 if ($@) { block2 } | |
511 by a more confortable one. | |
512 In the try/catch syntax, the original $@ is in $_ in the catch subroutine. | |
513 This try/catch implementation is a copy and paste from | |
514 "Programming Perl" 3rd Edition, July 2000, by L.Wall, T. Christiansen | |
515 & J. Orwant. p227, and is only possible because of subroutine prototypes. | |
516 Returntype : depend on what is implemented the try or catch block | |
517 Exceptions : none | |
518 Caller : general | |
519 | |
520 =cut | |
521 | |
522 sub try (&$) { | |
523 my ($try, $catch) = @_; | |
524 eval { &$try }; | |
525 if ($@) { | |
526 chop $@; | |
527 local $_ = $@; | |
528 &$catch; | |
529 } | |
530 } | |
531 | |
532 sub catch (&) { | |
533 shift; | |
534 } | |
535 | |
536 1; |