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