1 #-----------------------------------------------------------------
3 # BioPerl module Bio::Root::Exception
5 # Please direct questions and support issues to <bioperl-l@bioperl.org>
7 # Cared for by Steve Chervitz <sac@bioperl.org>
9 # You may distribute this module under the same terms as perl itself
10 #-----------------------------------------------------------------
14 Bio::Root::Exception - Generic exception objects for Bioperl
18 =head2 Throwing exceptions using L<Error.pm throw|Error::throw>:
20 use Bio::Root::Exception;
23 # Set Error::Debug to include stack trace data in the error messages
28 throw Bio::Root::FileOpenException ( "Can't open file $file for reading", $!);
30 =head2 Throwing exceptions using L<Bioperl throw|Bio::Root::Root/throw>:
32 # Here we have an object that ISA Bio::Root::Root, so it inherits throw().
35 $object->throw(-class => 'Bio::Root::FileOpenException',
36 -text => "Can't open file $file for reading",
39 =head2 Catching and handling exceptions using L<Error.pm try|Error/try>:
41 use Bio::Root::Exception;
44 # Note that we need to import the 'try' tag from Error.pm
46 # Set Error::Debug to include stack trace data in the error messages
52 throw Bio::Root::FileOpenException ( "Can't open file $file for reading", $!);
54 catch Bio::Root::FileOpenException with {
56 print STDERR "Using default input file: $default_file\n";
57 open (IN, $default_file) || die "Can't open $default_file";
61 print STDERR "An unexpected exception occurred: \n$err";
63 # By placing an the error object reference within double quotes,
64 # you're invoking its stringify() method.
67 # Any code that you want to execute regardless of whether or not
68 # an exception occurred.
70 # the ending semicolon is essential!
73 =head2 Defining a new Exception type as a subclass of Bio::Root::Exception:
75 @Bio::TestException::ISA = qw( Bio::Root::Exception );
79 =head2 Exceptions defined in L<Bio::Root::Exception>
81 These are generic exceptions for typical problem situations that could arise
82 in any module or script.
86 =item Bio::Root::Exception()
88 =item Bio::Root::NotImplemented()
90 =item Bio::Root::IOException()
92 =item Bio::Root::FileOpenException()
94 =item Bio::Root::SystemException()
96 =item Bio::Root::BadParameter()
98 =item Bio::Root::OutOfRange()
100 =item Bio::Root::NoSuchThing()
104 Using defined exception classes like these is a good idea because it
105 indicates the basic nature of what went wrong in a convenient,
108 If there is a type of exception that you want to throw
109 that is not covered by the classes listed above, it is easy to define
110 a new one that fits your needs. Just write a line like the following
111 in your module or script where you want to use it (or put it somewhere
112 that is accessible to your code):
114 @NoCanDoException::ISA = qw( Bio::Root::Exception );
116 All of the exceptions defined in this module inherit from a common
117 base class exception, Bio::Root::Exception. This allows a user to
118 write a handler for all Bioperl-derived exceptions as follows:
124 # some code that depends on Bioperl
126 catch Bio::Root::Exception with {
128 print "A Bioperl exception occurred:\n$err\n";
131 So if you do create your own exceptions, just be sure they inherit
132 from Bio::Root::Exception directly, or indirectly by inheriting from a
133 Bio::Root::Exception subclass.
135 The exceptions in Bio::Root::Exception are extensions of Graham Barr's
136 L<Error> module available from CPAN. Despite this dependency, the
137 L<Bio::Root::Exception> module does not explicitly C<require Error>.
138 This permits Bio::Root::Exception to be loaded even when
139 Error.pm is not available.
141 =head2 Throwing exceptions within Bioperl modules
143 Error.pm is not part of the Bioperl distibution, and may not be
144 present within any given perl installation. So, when you want to
145 throw an exception in a Bioperl module, the safe way to throw it
146 is to use L<Bio::Root::Root/throw> which can use Error.pm
147 when it's available. See documentation in Bio::Root::Root for details.
151 See the C<examples/exceptions> directory of the Bioperl distribution for
154 L<Bio::Root::Root/throw> for information about throwing
155 L<Bio::Root::Exception>-based exceptions.
157 L<Error> (available from CPAN, author: GBARR)
159 Error.pm is helping to guide the design of exception handling in Perl 6.
162 http://dev.perl.org/rfc/63.pod
164 http://dev.perl.org/rfc/88.pod
169 Steve Chervitz E<lt>sac@bioperl.orgE<gt>
173 Copyright (c) 2001 Steve Chervitz. All Rights Reserved.
175 This library is free software; you can redistribute it and/or modify
176 it under the same terms as Perl itself.
180 This software is provided "as is" without warranty of any kind.
186 # Define some generic exceptions.'
188 package Bio
::Root
::Exception
;
189 use Bio
::Root
::Version
;
193 my $debug = $Error::Debug
; # Prevents the "used only once" warning.
194 my $DEFAULT_VALUE = "__DUMMY__"; # Permits eval{} based handlers to work
196 =head2 L<Bio::Root::Exception>
198 Purpose : A generic base class for all BioPerl exceptions.
199 By including a "catch Bio::Root::Exception" block, you
200 should be able to trap all BioPerl exceptions.
201 Example : throw Bio::Root::Exception("A generic exception", $!);
205 #---------------------------------------------------------
206 @Bio::Root
::Exception
::ISA
= qw( Error );
207 #---------------------------------------------------------
209 =head1 Methods defined by Bio::Root::Exception
213 Purpose : Guarantees that -value is set properly before
214 calling Error::new().
216 Arguments: key-value style arguments same as for Error::new()
218 You can also specify plain arguments as ($message, $value)
219 where $value is optional.
221 -value, if defined, must be non-zero and not an empty string
222 in order for eval{}-based exception handlers to work.
223 These require that if($@) evaluates to true, which will not
224 be the case if the Error has no value (Error overloads
225 numeric operations to the Error::value() method).
227 It is OK to create Bio::Root::Exception objects without
228 specifing -value. In this case, an invisible dummy value is used.
230 If you happen to specify a -value of zero (0), it will
231 be replaced by the string "The number zero (0)".
233 If you happen to specify a -value of empty string (""), it will
234 be replaced by the string "An empty string ("")".
239 my ($class, @args) = @_;
240 my ($value, %params);
241 if( @args % 2 == 0 && $args[0] =~ /^-/) {
243 $value = $params{'-value'};
246 $params{-text
} = $args[0];
250 if( defined $value ) {
251 $value = "The number zero (0)" if $value =~ /^\d+$/ && $value == 0;
252 $value = "An empty string (\"\")" if $value eq "";
255 $value ||= $DEFAULT_VALUE;
257 $params{-value
} = $value;
259 my $self = $class->SUPER::new
( %params );
263 =head2 pretty_format()
265 Purpose : Get a nicely formatted string containing information about the
266 exception. Format is similar to that produced by
267 Bio::Root::Root::throw(), with the addition of the name of
268 the exception class in the EXCEPTION line and some other
269 data available via the Error object.
270 Example : print $error->pretty_format;
276 my $msg = $self->text;
278 if( $Error::Debug
) {
279 $stack = $self->_reformat_stacktrace();
281 my $value_string = $self->value ne $DEFAULT_VALUE ?
"VALUE: ".$self->value."\n" : "";
282 my $class = ref($self);
284 my $title = "------------- EXCEPTION: $class -------------";
285 my $footer = "\n" . '-' x CORE
::length($title);
286 my $out = "\n$title\n" .
287 "MSG: $msg\n". $value_string. $stack. $footer . "\n";
292 # Reformatting of the stack performed by _reformat_stacktrace:
293 # 1. Shift the file:line data in line i to line i+1.
294 # 2. change xxx::__ANON__() to "try{} block"
295 # 3. skip the "require" and "Error::subs::try" stack entries (boring)
296 # This means that the first line in the stack won't have any file:line data
297 # But this isn't a big issue since it's for a Bio::Root::-based method
298 # that doesn't vary from exception to exception.
300 sub _reformat_stacktrace
{
302 my $msg = $self->text;
303 my $stack = $self->stacktrace();
304 $stack =~ s/\Q$msg//;
305 my @stack = split( /\n/, $stack);
307 my ($method, $file, $linenum, $prev_file, $prev_linenum);
309 foreach my $i( 0..$#stack ) {
310 # print "STACK-ORIG: $stack[$i]\n";
311 if( ($stack[$i] =~ /^\s*([^(]+)\s*\(.*\) called at (\S+) line (\d+)/) ||
312 ($stack[$i] =~ /^\s*(require 0) called at (\S+) line (\d+)/)) {
313 ($method, $file, $linenum) = ($1, $2, $3);
319 if( $stack_count == 1 ) {
320 push @new_stack, "STACK: $method";
321 ($prev_file, $prev_linenum) = ($file, $linenum);
325 if( $method =~ /__ANON__/ ) {
326 $method = "try{} block";
328 if( ($method =~ /^require/ and $file =~ /Error\.pm/ ) ||
329 ($method =~ /^Error::subs::try/ ) ) {
332 push @new_stack, "STACK: $method $prev_file:$prev_linenum";
333 ($prev_file, $prev_linenum) = ($file, $linenum);
335 push @new_stack, "STACK: $prev_file:$prev_linenum";
337 return join "\n", @new_stack;
342 Purpose : Overrides Error::stringify() to call pretty_format().
343 This is called automatically when an exception object
344 is placed between double quotes.
345 Example : catch Bio::Root::Exception with {
350 See Also: L<pretty_format()|pretty_format>
355 my ($self, @args) = @_;
356 return $self->pretty_format( @args );
359 =head1 Subclasses of Bio::Root::Exception
361 =head2 L<Bio::Root::NotImplemented>
363 Purpose : Indicates that a method has not been implemented.
364 Example : throw Bio::Root::NotImplemented(
365 -text => "Method \"foo\" not implemented in module FooBar.",
370 #---------------------------------------------------------
371 @Bio::Root
::NotImplemented
::ISA
= qw( Bio::Root::Exception );
372 #---------------------------------------------------------
374 =head2 L<Bio::Root::IOException>
376 Purpose : Indicates that some input/output-related trouble has occurred.
377 Example : throw Bio::Root::IOException(
378 -text => "Can't save data to file $file.",
383 #---------------------------------------------------------
384 @Bio::Root
::IOException
::ISA
= qw( Bio::Root::Exception );
385 #---------------------------------------------------------
388 =head2 L<Bio::Root::FileOpenException>
390 Purpose : Indicates that a file could not be opened.
391 Example : throw Bio::Root::FileOpenException(
392 -text => "Can't open file $file for reading.",
397 #---------------------------------------------------------
398 @Bio::Root
::FileOpenException
::ISA
= qw( Bio::Root::IOException );
399 #---------------------------------------------------------
402 =head2 L<Bio::Root::SystemException>
404 Purpose : Indicates that a system call failed.
405 Example : unlink($file) or throw Bio::Root::SystemException(
406 -text => "Can't unlink file $file.",
411 #---------------------------------------------------------
412 @Bio::Root
::SystemException
::ISA
= qw( Bio::Root::Exception );
413 #---------------------------------------------------------
416 =head2 L<Bio::Root::BadParameter>
418 Purpose : Indicates that one or more parameters supplied to a method
419 are invalid, unspecified, or conflicting.
420 Example : throw Bio::Root::BadParameter(
421 -text => "Required parameter \"-foo\" was not specified",
426 #---------------------------------------------------------
427 @Bio::Root
::BadParameter
::ISA
= qw( Bio::Root::Exception );
428 #---------------------------------------------------------
431 =head2 L<Bio::Root::OutOfRange>
433 Purpose : Indicates that a specified (start,end) range or
434 an index to an array is outside the permitted range.
435 Example : throw Bio::Root::OutOfRange(
436 -text => "Start coordinate ($start) cannot be less than zero.",
441 #---------------------------------------------------------
442 @Bio::Root
::OutOfRange
::ISA
= qw( Bio::Root::Exception );
443 #---------------------------------------------------------
446 =head2 L<Bio::Root::NoSuchThing>
448 Purpose : Indicates that a requested thing cannot be located
449 and therefore could possibly be bogus.
450 Example : throw Bio::Root::NoSuchThing(
451 -text => "Accession M000001 could not be found.",
452 -value => "M000001" );
456 #---------------------------------------------------------
457 @Bio::Root
::NoSuchThing
::ISA
= qw( Bio::Root::Exception );
458 #---------------------------------------------------------