1 #-----------------------------------------------------------------
4 # BioPerl module Bio::Root::Exception
6 # Please direct questions and support issues to <bioperl-l@bioperl.org>
8 # Cared for by Steve Chervitz <sac@bioperl.org>
10 # You may distribute this module under the same terms as perl itself
11 #-----------------------------------------------------------------
15 Bio::Root::Exception - Generic exception objects for Bioperl
19 =head2 Throwing exceptions using L<Error.pm throw|Error::throw>:
21 use Bio::Root::Exception;
24 # Set Error::Debug to include stack trace data in the error messages
29 throw Bio::Root::FileOpenException ( "Can't open file $file for reading", $!);
31 =head2 Throwing exceptions using L<Bioperl throw|Bio::Root::Root/throw>:
33 # Here we have an object that ISA Bio::Root::Root, so it inherits throw().
36 $object->throw(-class => 'Bio::Root::FileOpenException',
37 -text => "Can't open file $file for reading",
40 =head2 Catching and handling exceptions using L<Error.pm try|Error/try>:
42 use Bio::Root::Exception;
45 # Note that we need to import the 'try' tag from Error.pm
47 # Set Error::Debug to include stack trace data in the error messages
53 throw Bio::Root::FileOpenException ( "Can't open file $file for reading", $!);
55 catch Bio::Root::FileOpenException with {
57 print STDERR "Using default input file: $default_file\n";
58 open (IN, $default_file) || die "Can't open $default_file";
62 print STDERR "An unexpected exception occurred: \n$err";
64 # By placing an the error object reference within double quotes,
65 # you're invoking its stringify() method.
68 # Any code that you want to execute regardless of whether or not
69 # an exception occurred.
71 # the ending semicolon is essential!
74 =head2 Defining a new Exception type as a subclass of Bio::Root::Exception:
76 @Bio::TestException::ISA = qw( Bio::Root::Exception );
80 =head2 Exceptions defined in L<Bio::Root::Exception>
82 These are generic exceptions for typical problem situations that could arise
83 in any module or script.
87 =item Bio::Root::Exception()
89 =item Bio::Root::NotImplemented()
91 =item Bio::Root::IOException()
93 =item Bio::Root::FileOpenException()
95 =item Bio::Root::SystemException()
97 =item Bio::Root::BadParameter()
99 =item Bio::Root::OutOfRange()
101 =item Bio::Root::NoSuchThing()
105 Using defined exception classes like these is a good idea because it
106 indicates the basic nature of what went wrong in a convenient,
109 If there is a type of exception that you want to throw
110 that is not covered by the classes listed above, it is easy to define
111 a new one that fits your needs. Just write a line like the following
112 in your module or script where you want to use it (or put it somewhere
113 that is accessible to your code):
115 @NoCanDoException::ISA = qw( Bio::Root::Exception );
117 All of the exceptions defined in this module inherit from a common
118 base class exception, Bio::Root::Exception. This allows a user to
119 write a handler for all Bioperl-derived exceptions as follows:
125 # some code that depends on Bioperl
127 catch Bio::Root::Exception with {
129 print "A Bioperl exception occurred:\n$err\n";
132 So if you do create your own exceptions, just be sure they inherit
133 from Bio::Root::Exception directly, or indirectly by inheriting from a
134 Bio::Root::Exception subclass.
136 The exceptions in Bio::Root::Exception are extensions of Graham Barr's
137 L<Error> module available from CPAN. Despite this dependency, the
138 L<Bio::Root::Exception> module does not explicitly C<require Error>.
139 This permits Bio::Root::Exception to be loaded even when
140 Error.pm is not available.
142 =head2 Throwing exceptions within Bioperl modules
144 Error.pm is not part of the Bioperl distibution, and may not be
145 present within any given perl installation. So, when you want to
146 throw an exception in a Bioperl module, the safe way to throw it
147 is to use L<Bio::Root::Root/throw> which can use Error.pm
148 when it's available. See documentation in Bio::Root::Root for details.
152 See the C<examples/exceptions> directory of the Bioperl distribution for
155 L<Bio::Root::Root/throw> for information about throwing
156 L<Bio::Root::Exception>-based exceptions.
158 L<Error> (available from CPAN, author: GBARR)
160 Error.pm is helping to guide the design of exception handling in Perl 6.
163 http://dev.perl.org/rfc/63.pod
165 http://dev.perl.org/rfc/88.pod
170 Steve Chervitz E<lt>sac@bioperl.orgE<gt>
174 Copyright (c) 2001 Steve Chervitz. All Rights Reserved.
176 This library is free software; you can redistribute it and/or modify
177 it under the same terms as Perl itself.
181 This software is provided "as is" without warranty of any kind.
187 # Define some generic exceptions.'
189 package Bio
::Root
::Exception
;
190 use Bio
::Root
::Version
;
194 my $debug = $Error::Debug
; # Prevents the "used only once" warning.
195 my $DEFAULT_VALUE = "__DUMMY__"; # Permits eval{} based handlers to work
197 =head2 L<Bio::Root::Exception>
199 Purpose : A generic base class for all BioPerl exceptions.
200 By including a "catch Bio::Root::Exception" block, you
201 should be able to trap all BioPerl exceptions.
202 Example : throw Bio::Root::Exception("A generic exception", $!);
206 #---------------------------------------------------------
207 @Bio::Root
::Exception
::ISA
= qw( Error );
208 #---------------------------------------------------------
210 =head1 Methods defined by Bio::Root::Exception
214 Purpose : Guarantees that -value is set properly before
215 calling Error::new().
217 Arguments: key-value style arguments same as for Error::new()
219 You can also specify plain arguments as ($message, $value)
220 where $value is optional.
222 -value, if defined, must be non-zero and not an empty string
223 in order for eval{}-based exception handlers to work.
224 These require that if($@) evaluates to true, which will not
225 be the case if the Error has no value (Error overloads
226 numeric operations to the Error::value() method).
228 It is OK to create Bio::Root::Exception objects without
229 specifing -value. In this case, an invisible dummy value is used.
231 If you happen to specify a -value of zero (0), it will
232 be replaced by the string "The number zero (0)".
234 If you happen to specify a -value of empty string (""), it will
235 be replaced by the string "An empty string ("")".
240 my ($class, @args) = @_;
241 my ($value, %params);
242 if( @args % 2 == 0 && $args[0] =~ /^-/) {
244 $value = $params{'-value'};
247 $params{-text
} = $args[0];
251 if( defined $value ) {
252 $value = "The number zero (0)" if $value =~ /^\d+$/ && $value == 0;
253 $value = "An empty string (\"\")" if $value eq "";
256 $value ||= $DEFAULT_VALUE;
258 $params{-value
} = $value;
260 my $self = $class->SUPER::new
( %params );
264 =head2 pretty_format()
266 Purpose : Get a nicely formatted string containing information about the
267 exception. Format is similar to that produced by
268 Bio::Root::Root::throw(), with the addition of the name of
269 the exception class in the EXCEPTION line and some other
270 data available via the Error object.
271 Example : print $error->pretty_format;
277 my $msg = $self->text;
279 if( $Error::Debug
) {
280 $stack = $self->_reformat_stacktrace();
282 my $value_string = $self->value ne $DEFAULT_VALUE ?
"VALUE: ".$self->value."\n" : "";
283 my $class = ref($self);
285 my $title = "------------- EXCEPTION: $class -------------";
286 my $footer = "\n" . '-' x CORE
::length($title);
287 my $out = "\n$title\n" .
288 "MSG: $msg\n". $value_string. $stack. $footer . "\n";
293 # Reformatting of the stack performed by _reformat_stacktrace:
294 # 1. Shift the file:line data in line i to line i+1.
295 # 2. change xxx::__ANON__() to "try{} block"
296 # 3. skip the "require" and "Error::subs::try" stack entries (boring)
297 # This means that the first line in the stack won't have any file:line data
298 # But this isn't a big issue since it's for a Bio::Root::-based method
299 # that doesn't vary from exception to exception.
301 sub _reformat_stacktrace
{
303 my $msg = $self->text;
304 my $stack = $self->stacktrace();
305 $stack =~ s/\Q$msg//;
306 my @stack = split( /\n/, $stack);
308 my ($method, $file, $linenum, $prev_file, $prev_linenum);
310 foreach my $i( 0..$#stack ) {
311 # print "STACK-ORIG: $stack[$i]\n";
312 if( ($stack[$i] =~ /^\s*([^(]+)\s*\(.*\) called at (\S+) line (\d+)/) ||
313 ($stack[$i] =~ /^\s*(require 0) called at (\S+) line (\d+)/)) {
314 ($method, $file, $linenum) = ($1, $2, $3);
320 if( $stack_count == 1 ) {
321 push @new_stack, "STACK: $method";
322 ($prev_file, $prev_linenum) = ($file, $linenum);
326 if( $method =~ /__ANON__/ ) {
327 $method = "try{} block";
329 if( ($method =~ /^require/ and $file =~ /Error\.pm/ ) ||
330 ($method =~ /^Error::subs::try/ ) ) {
333 push @new_stack, "STACK: $method $prev_file:$prev_linenum";
334 ($prev_file, $prev_linenum) = ($file, $linenum);
336 push @new_stack, "STACK: $prev_file:$prev_linenum";
338 return join "\n", @new_stack;
343 Purpose : Overrides Error::stringify() to call pretty_format().
344 This is called automatically when an exception object
345 is placed between double quotes.
346 Example : catch Bio::Root::Exception with {
351 See Also: L<pretty_format()|pretty_format>
356 my ($self, @args) = @_;
357 return $self->pretty_format( @args );
360 =head1 Subclasses of Bio::Root::Exception
362 =head2 L<Bio::Root::NotImplemented>
364 Purpose : Indicates that a method has not been implemented.
365 Example : throw Bio::Root::NotImplemented(
366 -text => "Method \"foo\" not implemented in module FooBar.",
371 #---------------------------------------------------------
372 @Bio::Root
::NotImplemented
::ISA
= qw( Bio::Root::Exception );
373 #---------------------------------------------------------
375 =head2 L<Bio::Root::IOException>
377 Purpose : Indicates that some input/output-related trouble has occurred.
378 Example : throw Bio::Root::IOException(
379 -text => "Can't save data to file $file.",
384 #---------------------------------------------------------
385 @Bio::Root
::IOException
::ISA
= qw( Bio::Root::Exception );
386 #---------------------------------------------------------
389 =head2 L<Bio::Root::FileOpenException>
391 Purpose : Indicates that a file could not be opened.
392 Example : throw Bio::Root::FileOpenException(
393 -text => "Can't open file $file for reading.",
398 #---------------------------------------------------------
399 @Bio::Root
::FileOpenException
::ISA
= qw( Bio::Root::IOException );
400 #---------------------------------------------------------
403 =head2 L<Bio::Root::SystemException>
405 Purpose : Indicates that a system call failed.
406 Example : unlink($file) or throw Bio::Root::SystemException(
407 -text => "Can't unlink file $file.",
412 #---------------------------------------------------------
413 @Bio::Root
::SystemException
::ISA
= qw( Bio::Root::Exception );
414 #---------------------------------------------------------
417 =head2 L<Bio::Root::BadParameter>
419 Purpose : Indicates that one or more parameters supplied to a method
420 are invalid, unspecified, or conflicting.
421 Example : throw Bio::Root::BadParameter(
422 -text => "Required parameter \"-foo\" was not specified",
427 #---------------------------------------------------------
428 @Bio::Root
::BadParameter
::ISA
= qw( Bio::Root::Exception );
429 #---------------------------------------------------------
432 =head2 L<Bio::Root::OutOfRange>
434 Purpose : Indicates that a specified (start,end) range or
435 an index to an array is outside the permitted range.
436 Example : throw Bio::Root::OutOfRange(
437 -text => "Start coordinate ($start) cannot be less than zero.",
442 #---------------------------------------------------------
443 @Bio::Root
::OutOfRange
::ISA
= qw( Bio::Root::Exception );
444 #---------------------------------------------------------
447 =head2 L<Bio::Root::NoSuchThing>
449 Purpose : Indicates that a requested thing cannot be located
450 and therefore could possibly be bogus.
451 Example : throw Bio::Root::NoSuchThing(
452 -text => "Accession M000001 could not be found.",
453 -value => "M000001" );
457 #---------------------------------------------------------
458 @Bio::Root
::NoSuchThing
::ISA
= qw( Bio::Root::Exception );
459 #---------------------------------------------------------