Mercurial > repos > mahtabm > ensembl
comparison variant_effect_predictor/Bio/Root/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 #----------------------------------------------------------------- | |
| 2 # $Id: Exception.pm,v 1.14 2002/06/29 00:42:17 sac Exp $ | |
| 3 # | |
| 4 # BioPerl module Bio::Root::Exception | |
| 5 # | |
| 6 # Cared for by Steve Chervitz <sac@bioperl.org> | |
| 7 # | |
| 8 # You may distribute this module under the same terms as perl itself | |
| 9 #----------------------------------------------------------------- | |
| 10 | |
| 11 =head1 NAME | |
| 12 | |
| 13 Bio::Root::Exception - Generic exception objects for Bioperl | |
| 14 | |
| 15 =head1 SYNOPSIS | |
| 16 | |
| 17 =head2 Throwing exceptions using B<Error::throw()>: | |
| 18 | |
| 19 use Bio::Root::Exception; | |
| 20 use Error; | |
| 21 | |
| 22 # Set Error::Debug to include stack trace data in the error messages | |
| 23 $Error::Debug = 1; | |
| 24 | |
| 25 $file = shift; | |
| 26 open (IN, $file) || | |
| 27 throw Bio::Root::FileOpenException ( "Can't open file $file for reading", $!); | |
| 28 | |
| 29 =head2 Throwing exceptions using B<Bio::Root::Root::throw()>: | |
| 30 | |
| 31 # Here we have an object that ISA Bio::Root::Root, so it inherits throw(). | |
| 32 | |
| 33 open (IN, $file) || | |
| 34 $object->throw(-class => 'Bio::Root::FileOpenException', | |
| 35 -text => "Can't open file $file for reading", | |
| 36 -value => $!); | |
| 37 | |
| 38 =head2 Catching and handling exceptions using B<Error::try()>: | |
| 39 | |
| 40 use Bio::Root::Exception; | |
| 41 use Error qw(:try); | |
| 42 | |
| 43 # Note that we need to import the 'try' tag from Error.pm | |
| 44 | |
| 45 # Set Error::Debug to include stack trace data in the error messages | |
| 46 $Error::Debug = 1; | |
| 47 | |
| 48 $file = shift; | |
| 49 try { | |
| 50 open (IN, $file) || | |
| 51 throw Bio::Root::FileOpenException ( "Can't open file $file for reading", $!); | |
| 52 } | |
| 53 catch Bio::Root::FileOpenException with { | |
| 54 my $err = shift; | |
| 55 print STDERR "Using default input file: $default_file\n"; | |
| 56 open (IN, $default_file) || die "Can't open $default_file"; | |
| 57 } | |
| 58 otherwise { | |
| 59 my $err = shift; | |
| 60 print STDERR "An unexpected exception occurred: \n$err"; | |
| 61 | |
| 62 # By placing an the error object reference within double quotes, | |
| 63 # you're invoking its stringify() method. | |
| 64 } | |
| 65 finally { | |
| 66 # Any code that you want to execute regardless of whether or not | |
| 67 # an exception occurred. | |
| 68 }; | |
| 69 # the ending semicolon is essential! | |
| 70 | |
| 71 | |
| 72 =head2 Defining a new Exception type as a subclass of Bio::Root::Exception: | |
| 73 | |
| 74 @Bio::TestException::ISA = qw( Bio::Root::Exception ); | |
| 75 | |
| 76 | |
| 77 =head1 DESCRIPTION | |
| 78 | |
| 79 =head2 Exceptions defined in B<Bio::Root::Exception> | |
| 80 | |
| 81 These are generic exceptions for typical problem situations that could arise | |
| 82 in any module or script. | |
| 83 | |
| 84 =over 8 | |
| 85 | |
| 86 =item Bio::Root::Exception() | |
| 87 | |
| 88 =item Bio::Root::NotImplemented() | |
| 89 | |
| 90 =item Bio::Root::IOException() | |
| 91 | |
| 92 =item Bio::Root::FileOpenException() | |
| 93 | |
| 94 =item Bio::Root::SystemException() | |
| 95 | |
| 96 =item Bio::Root::BadParameter() | |
| 97 | |
| 98 =item Bio::Root::OutOfRange() | |
| 99 | |
| 100 =item Bio::Root::NoSuchThing() | |
| 101 | |
| 102 =back | |
| 103 | |
| 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, | |
| 106 computable way. | |
| 107 | |
| 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): | |
| 113 | |
| 114 @NoCanDoException::ISA = qw( Bio::Root::Exception ); | |
| 115 | |
| 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: | |
| 119 | |
| 120 use Bio::Whatever; | |
| 121 use Error qw(:try); | |
| 122 | |
| 123 try { | |
| 124 # some code that depends on Bioperl | |
| 125 } | |
| 126 catch Bio::Root::Exception with { | |
| 127 my $err = shift; | |
| 128 print "A Bioperl exception occurred:\n$err\n"; | |
| 129 }; | |
| 130 | |
| 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. | |
| 134 | |
| 135 The exceptions in Bio::Root::Exception are extensions of Graham Barr's | |
| 136 B<Error.pm> module available from CPAN. Despite this dependency, the | |
| 137 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. | |
| 140 | |
| 141 =head2 Throwing exceptions within Bioperl modules | |
| 142 | |
| 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 B<Bio::Root::Root::throw()> which can use Error.pm | |
| 147 when it's available. See documentation in Bio::Root::Root for details. | |
| 148 | |
| 149 =head1 SEE ALSO | |
| 150 | |
| 151 See the C<examples/exceptions> directory of the Bioperl distribution for | |
| 152 working demo code. | |
| 153 | |
| 154 B<Bio::Root::Root::throw()> for information about throwing | |
| 155 Bio::Root::Exception-based exceptions. | |
| 156 | |
| 157 B<Error.pm> (available from CPAN, author: GBARR) | |
| 158 | |
| 159 Error.pm is helping to guide the design of exception handling in Perl 6. | |
| 160 See these RFC's: | |
| 161 | |
| 162 http://dev.perl.org/rfc/63.pod | |
| 163 | |
| 164 http://dev.perl.org/rfc/88.pod | |
| 165 | |
| 166 | |
| 167 =head1 AUTHOR | |
| 168 | |
| 169 Steve Chervitz E<lt>sac@bioperl.orgE<gt> | |
| 170 | |
| 171 =head1 COPYRIGHT | |
| 172 | |
| 173 Copyright (c) 2001 Steve Chervitz. All Rights Reserved. | |
| 174 | |
| 175 This library is free software; you can redistribute it and/or modify | |
| 176 it under the same terms as Perl itself. | |
| 177 | |
| 178 =head1 DISCLAIMER | |
| 179 | |
| 180 This software is provided "as is" without warranty of any kind. | |
| 181 | |
| 182 =head1 EXCEPTIONS | |
| 183 | |
| 184 =cut | |
| 185 | |
| 186 # Define some generic exceptions.' | |
| 187 | |
| 188 package Bio::Root::Exception; | |
| 189 | |
| 190 use strict; | |
| 191 | |
| 192 my $debug = $Error::Debug; # Prevents the "used only once" warning. | |
| 193 my $DEFAULT_VALUE = "__DUMMY__"; # Permits eval{} based handlers to work | |
| 194 | |
| 195 =head2 B<Bio::Root::Exception> | |
| 196 | |
| 197 Purpose : A generic base class for all BioPerl exceptions. | |
| 198 By including a "catch Bio::Root::Exception" block, you | |
| 199 should be able to trap all BioPerl exceptions. | |
| 200 Example : throw Bio::Root::Exception("A generic exception", $!); | |
| 201 | |
| 202 =cut | |
| 203 | |
| 204 #--------------------------------------------------------- | |
| 205 @Bio::Root::Exception::ISA = qw( Error ); | |
| 206 #--------------------------------------------------------- | |
| 207 | |
| 208 =head2 Methods defined by Bio::Root::Exception | |
| 209 | |
| 210 =over 4 | |
| 211 | |
| 212 =item B< new() > | |
| 213 | |
| 214 Purpose : Guarantees that -value is set properly before | |
| 215 calling Error::new(). | |
| 216 | |
| 217 Arguments: key-value style arguments same as for Error::new() | |
| 218 | |
| 219 You can also specify plain arguments as ($message, $value) | |
| 220 where $value is optional. | |
| 221 | |
| 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). | |
| 227 | |
| 228 It is OK to create Bio::Root::Exception objects without | |
| 229 specifing -value. In this case, an invisible dummy value is used. | |
| 230 | |
| 231 If you happen to specify a -value of zero (0), it will | |
| 232 be replaced by the string "The number zero (0)". | |
| 233 | |
| 234 If you happen to specify a -value of empty string (""), it will | |
| 235 be replaced by the string "An empty string ("")". | |
| 236 | |
| 237 =cut | |
| 238 | |
| 239 sub new { | |
| 240 my ($class, @args) = @_; | |
| 241 my ($value, %params); | |
| 242 if( @args % 2 == 0 && $args[0] =~ /^-/) { | |
| 243 %params = @args; | |
| 244 $value = $params{'-value'}; | |
| 245 } | |
| 246 else { | |
| 247 $params{-text} = $args[0]; | |
| 248 $value = $args[1]; | |
| 249 } | |
| 250 | |
| 251 if( defined $value and not $value) { | |
| 252 $value = "The number zero (0)" if $value == 0; | |
| 253 $value = "An empty string (\"\")" if $value eq ""; | |
| 254 } | |
| 255 else { | |
| 256 $value ||= $DEFAULT_VALUE; | |
| 257 } | |
| 258 $params{-value} = $value; | |
| 259 | |
| 260 my $self = $class->SUPER::new( %params ); | |
| 261 return $self; | |
| 262 } | |
| 263 | |
| 264 =item pretty_format() | |
| 265 | |
| 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; | |
| 272 | |
| 273 =cut | |
| 274 | |
| 275 sub pretty_format { | |
| 276 my $self = shift; | |
| 277 my $msg = $self->text; | |
| 278 my $stack = ''; | |
| 279 if( $Error::Debug ) { | |
| 280 $stack = $self->_reformat_stacktrace(); | |
| 281 } | |
| 282 my $value_string = $self->value ne $DEFAULT_VALUE ? "VALUE: ".$self->value."\n" : ""; | |
| 283 my $class = ref($self); | |
| 284 | |
| 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"; | |
| 289 return $out; | |
| 290 } | |
| 291 | |
| 292 | |
| 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. | |
| 300 | |
| 301 sub _reformat_stacktrace { | |
| 302 my $self = shift; | |
| 303 my $msg = $self->text; | |
| 304 my $stack = $self->stacktrace(); | |
| 305 $stack =~ s/\Q$msg//; | |
| 306 my @stack = split( /\n/, $stack); | |
| 307 my @new_stack = (); | |
| 308 my ($method, $file, $linenum, $prev_file, $prev_linenum); | |
| 309 my $stack_count = 0; | |
| 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); | |
| 315 $stack_count++; | |
| 316 } | |
| 317 else{ | |
| 318 next; | |
| 319 } | |
| 320 if( $stack_count == 1 ) { | |
| 321 push @new_stack, "STACK: $method"; | |
| 322 ($prev_file, $prev_linenum) = ($file, $linenum); | |
| 323 next; | |
| 324 } | |
| 325 | |
| 326 if( $method =~ /__ANON__/ ) { | |
| 327 $method = "try{} block"; | |
| 328 } | |
| 329 if( ($method =~ /^require/ and $file =~ /Error\.pm/ ) || | |
| 330 ($method =~ /^Error::subs::try/ ) ) { | |
| 331 last; | |
| 332 } | |
| 333 push @new_stack, "STACK: $method $prev_file:$prev_linenum"; | |
| 334 ($prev_file, $prev_linenum) = ($file, $linenum); | |
| 335 } | |
| 336 push @new_stack, "STACK: $prev_file:$prev_linenum"; | |
| 337 | |
| 338 return join "\n", @new_stack; | |
| 339 } | |
| 340 | |
| 341 =item B< stringify() > | |
| 342 | |
| 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 { | |
| 347 my $error = shift; | |
| 348 print "$error"; | |
| 349 } | |
| 350 | |
| 351 See Also: L<pretty_format()|pretty_format> | |
| 352 | |
| 353 =cut | |
| 354 | |
| 355 sub stringify { | |
| 356 my ($self, @args) = @_; | |
| 357 return $self->pretty_format( @args ); | |
| 358 } | |
| 359 | |
| 360 | |
| 361 | |
| 362 =back | |
| 363 | |
| 364 =head1 Subclasses of Bio::Root::Exception | |
| 365 | |
| 366 | |
| 367 =head2 B<Bio::Root::NotImplemented> | |
| 368 | |
| 369 Purpose : Indicates that a method has not been implemented. | |
| 370 Example : throw Bio::Root::NotImplemented( | |
| 371 -text => "Method \"foo\" not implemented in module FooBar.", | |
| 372 -value => "foo" ); | |
| 373 | |
| 374 =cut | |
| 375 | |
| 376 #--------------------------------------------------------- | |
| 377 @Bio::Root::NotImplemented::ISA = qw( Bio::Root::Exception ); | |
| 378 #--------------------------------------------------------- | |
| 379 | |
| 380 =head2 B<Bio::Root::IOException> | |
| 381 | |
| 382 Purpose : Indicates that some input/output-related trouble has occurred. | |
| 383 Example : throw Bio::Root::IOException( | |
| 384 -text => "Can't save data to file $file.", | |
| 385 -value => $! ); | |
| 386 | |
| 387 =cut | |
| 388 | |
| 389 #--------------------------------------------------------- | |
| 390 @Bio::Root::IOException::ISA = qw( Bio::Root::Exception ); | |
| 391 #--------------------------------------------------------- | |
| 392 | |
| 393 | |
| 394 =head2 B<Bio::Root::FileOpenException> | |
| 395 | |
| 396 Purpose : Indicates that a file could not be opened. | |
| 397 Example : throw Bio::Root::FileOpenException( | |
| 398 -text => "Can't open file $file for reading.", | |
| 399 -value => $! ); | |
| 400 | |
| 401 =cut | |
| 402 | |
| 403 #--------------------------------------------------------- | |
| 404 @Bio::Root::FileOpenException::ISA = qw( Bio::Root::IOException ); | |
| 405 #--------------------------------------------------------- | |
| 406 | |
| 407 | |
| 408 =head2 B<Bio::Root::SystemException> | |
| 409 | |
| 410 Purpose : Indicates that a system call failed. | |
| 411 Example : unlink($file) or throw Bio::Root::SystemException( | |
| 412 -text => "Can't unlink file $file.", | |
| 413 -value => $! ); | |
| 414 | |
| 415 =cut | |
| 416 | |
| 417 #--------------------------------------------------------- | |
| 418 @Bio::Root::SystemException::ISA = qw( Bio::Root::Exception ); | |
| 419 #--------------------------------------------------------- | |
| 420 | |
| 421 | |
| 422 =head2 B<Bio::Root::BadParameter> | |
| 423 | |
| 424 Purpose : Indicates that one or more parameters supplied to a method | |
| 425 are invalid, unspecified, or conflicting. | |
| 426 Example : throw Bio::Root::BadParameter( | |
| 427 -text => "Required parameter \"-foo\" was not specified", | |
| 428 -value => "-foo" ); | |
| 429 | |
| 430 =cut | |
| 431 | |
| 432 #--------------------------------------------------------- | |
| 433 @Bio::Root::BadParameter::ISA = qw( Bio::Root::Exception ); | |
| 434 #--------------------------------------------------------- | |
| 435 | |
| 436 | |
| 437 =head2 B<Bio::Root::OutOfRange> | |
| 438 | |
| 439 Purpose : Indicates that a specified (start,end) range or | |
| 440 an index to an array is outside the permitted range. | |
| 441 Example : throw Bio::Root::OutOfRange( | |
| 442 -text => "Start coordinate ($start) cannot be less than zero.", | |
| 443 -value => $start ); | |
| 444 | |
| 445 =cut | |
| 446 | |
| 447 #--------------------------------------------------------- | |
| 448 @Bio::Root::OutOfRange::ISA = qw( Bio::Root::Exception ); | |
| 449 #--------------------------------------------------------- | |
| 450 | |
| 451 | |
| 452 =head2 B<Bio::Root::NoSuchThing> | |
| 453 | |
| 454 Purpose : Indicates that a requested thing cannot be located | |
| 455 and therefore could possibly be bogus. | |
| 456 Example : throw Bio::Root::NoSuchThing( | |
| 457 -text => "Accession M000001 could not be found.", | |
| 458 -value => "M000001" ); | |
| 459 | |
| 460 =cut | |
| 461 | |
| 462 #--------------------------------------------------------- | |
| 463 @Bio::Root::NoSuchThing::ISA = qw( Bio::Root::Exception ); | |
| 464 #--------------------------------------------------------- | |
| 465 | |
| 466 | |
| 467 1; | |
| 468 |
