Mercurial > repos > mahtabm > ensembl
comparison variant_effect_predictor/Bio/Root/Root.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 package Bio::Root::Root; | |
| 2 use strict; | |
| 3 | |
| 4 # $Id: Root.pm,v 1.30 2002/12/16 09:44:28 birney Exp $ | |
| 5 | |
| 6 =head1 NAME | |
| 7 | |
| 8 Bio::Root::Root - Hash-based implementation of Bio::Root::RootI | |
| 9 | |
| 10 =head1 SYNOPSIS | |
| 11 | |
| 12 # any bioperl or bioperl compliant object is a RootI | |
| 13 # compliant object | |
| 14 | |
| 15 # Here's how to throw and catch an exception using the eval-based syntax. | |
| 16 | |
| 17 $obj->throw("This is an exception"); | |
| 18 | |
| 19 eval { | |
| 20 $obj->throw("This is catching an exception"); | |
| 21 }; | |
| 22 | |
| 23 if( $@ ) { | |
| 24 print "Caught exception"; | |
| 25 } else { | |
| 26 print "no exception"; | |
| 27 } | |
| 28 | |
| 29 # Alternatively, using the new typed exception syntax in the throw() call: | |
| 30 | |
| 31 $obj->throw( -class => 'Bio::Root::BadParameter', | |
| 32 -text => "Can't open file $file", | |
| 33 -value => $file); | |
| 34 | |
| 35 # Exceptions can be used in an eval{} block as shown above or within | |
| 36 # a try{} block if you have installed the Error.pm module. | |
| 37 # Here's a brief example. For more, see Bio::Root::Exception | |
| 38 | |
| 39 use Error qw(:try); | |
| 40 | |
| 41 try { | |
| 42 $obj->throw( # arguments as above ); | |
| 43 } | |
| 44 catch Bio::Root::FileOpenException with { | |
| 45 my $err = shift; | |
| 46 print "Handling exception $err\n"; | |
| 47 }; | |
| 48 | |
| 49 =head1 DESCRIPTION | |
| 50 | |
| 51 This is a hashref-based implementation of the Bio::Root::RootI | |
| 52 interface. Most bioperl objects should inherit from this. | |
| 53 | |
| 54 See the documentation for Bio::Root::RootI for most of the methods | |
| 55 implemented by this module. Only overridden methods are described | |
| 56 here. | |
| 57 | |
| 58 =head2 Throwing Exceptions | |
| 59 | |
| 60 One of the functionalities that Bio::Root::RootI provides is the | |
| 61 ability to throw() exceptions with pretty stack traces. Bio::Root::Root | |
| 62 enhances this with the ability to use B<Error.pm> (available from CPAN) | |
| 63 if it has also been installed. | |
| 64 | |
| 65 If Error.pm has been installed, throw() will use it. This causes an | |
| 66 Error.pm-derived object to be thrown. This can be caught within a | |
| 67 C<catch{}> block, from wich you can extract useful bits of | |
| 68 information. If Error.pm is not installed, it will use the | |
| 69 Bio::Root::RootI-based exception throwing facilty. | |
| 70 | |
| 71 =head2 Typed Exception Syntax | |
| 72 | |
| 73 The typed exception syntax of throw() has the advantage of plainly | |
| 74 indicating the nature of the trouble, since the name of the class | |
| 75 is included in the title of the exception output. | |
| 76 | |
| 77 To take advantage of this capability, you must specify arguments | |
| 78 as named parameters in the throw() call. Here are the parameters: | |
| 79 | |
| 80 =over 4 | |
| 81 | |
| 82 =item -class | |
| 83 | |
| 84 name of the class of the exception. | |
| 85 This should be one of the classes defined in B<Bio::Root::Exception>, | |
| 86 or a custom error of yours that extends one of the exceptions | |
| 87 defined in B<Bio::Root::Exception>. | |
| 88 | |
| 89 =item -text | |
| 90 | |
| 91 a sensible message for the exception | |
| 92 | |
| 93 =item -value | |
| 94 | |
| 95 the value causing the exception or $!, if appropriate. | |
| 96 | |
| 97 =back | |
| 98 | |
| 99 Note that Bio::Root::Exception does not need to be imported into | |
| 100 your module (or script) namespace in order to throw exceptions | |
| 101 via Bio::Root::Root::throw(), since Bio::Root::Root imports it. | |
| 102 | |
| 103 =head2 Try-Catch-Finally Support | |
| 104 | |
| 105 In addition to using an eval{} block to handle exceptions, you can | |
| 106 also use a try-catch-finally block structure if B<Error.pm> has been | |
| 107 installed in your system (available from CPAN). See the documentation | |
| 108 for Error for more details. | |
| 109 | |
| 110 Here's an example. See the B<Bio::Root::Exception> module for | |
| 111 other pre-defined exception types: | |
| 112 | |
| 113 try { | |
| 114 open( IN, $file) || $obj->throw( -class => 'Bio::Root::FileOpenException', | |
| 115 -text => "Cannot open file $file for reading", | |
| 116 -value => $!); | |
| 117 } | |
| 118 catch Bio::Root::BadParameter with { | |
| 119 my $err = shift; # get the Error object | |
| 120 # Perform specific exception handling code for the FileOpenException | |
| 121 } | |
| 122 catch Bio::Root::Exception with { | |
| 123 my $err = shift; # get the Error object | |
| 124 # Perform general exception handling code for any Bioperl exception. | |
| 125 } | |
| 126 otherwise { | |
| 127 # A catch-all for any other type of exception | |
| 128 } | |
| 129 finally { | |
| 130 # Any code that you want to execute regardless of whether or not | |
| 131 # an exception occurred. | |
| 132 }; | |
| 133 # the ending semicolon is essential! | |
| 134 | |
| 135 | |
| 136 =head1 CONTACT | |
| 137 | |
| 138 Functions originally from Steve Chervitz. Refactored by Ewan Birney. | |
| 139 Re-refactored by Lincoln Stein. | |
| 140 | |
| 141 =head1 APPENDIX | |
| 142 | |
| 143 The rest of the documentation details each of the object | |
| 144 methods. Internal methods are usually preceded with a _ | |
| 145 | |
| 146 =cut | |
| 147 | |
| 148 #' | |
| 149 | |
| 150 use vars qw(@ISA $DEBUG $ID $Revision $VERSION $VERBOSITY $ERRORLOADED); | |
| 151 use strict; | |
| 152 use Bio::Root::RootI; | |
| 153 use Bio::Root::IO; | |
| 154 | |
| 155 @ISA = 'Bio::Root::RootI'; | |
| 156 | |
| 157 BEGIN { | |
| 158 | |
| 159 $ID = 'Bio::Root::Root'; | |
| 160 $VERSION = 1.0; | |
| 161 $Revision = '$Id: Root.pm,v 1.30 2002/12/16 09:44:28 birney Exp $ '; | |
| 162 $DEBUG = 0; | |
| 163 $VERBOSITY = 0; | |
| 164 $ERRORLOADED = 0; | |
| 165 | |
| 166 # Check whether or not Error.pm is available. | |
| 167 | |
| 168 # $main::DONT_USE_ERROR is intended for testing purposes and also | |
| 169 # when you don't want to use the Error module, even if it is installed. | |
| 170 # Just put a INIT { $DONT_USE_ERROR = 1; } at the top of your script. | |
| 171 if( not $main::DONT_USE_ERROR ) { | |
| 172 if ( eval "require Error" ) { | |
| 173 import Error qw(:try); | |
| 174 require Bio::Root::Exception; | |
| 175 $ERRORLOADED = 1; | |
| 176 $Error::Debug = 1; # enable verbose stack trace | |
| 177 } | |
| 178 } | |
| 179 if( !$ERRORLOADED ) { | |
| 180 require Carp; import Carp qw( confess ); | |
| 181 } | |
| 182 $main::DONT_USE_ERROR; # so that perl -w won't warn "used only once" | |
| 183 | |
| 184 } | |
| 185 | |
| 186 | |
| 187 | |
| 188 =head2 new | |
| 189 | |
| 190 Purpose : generic instantiation function can be overridden if | |
| 191 special needs of a module cannot be done in _initialize | |
| 192 | |
| 193 =cut | |
| 194 | |
| 195 sub new { | |
| 196 # my ($class, %param) = @_; | |
| 197 my $class = shift; | |
| 198 my $self = {}; | |
| 199 bless $self, ref($class) || $class; | |
| 200 | |
| 201 if(@_ > 1) { | |
| 202 # if the number of arguments is odd but at least 3, we'll give | |
| 203 # it a try to find -verbose | |
| 204 shift if @_ % 2; | |
| 205 my %param = @_; | |
| 206 ## See "Comments" above regarding use of _rearrange(). | |
| 207 $self->verbose($param{'-VERBOSE'} || $param{'-verbose'}); | |
| 208 } | |
| 209 return $self; | |
| 210 } | |
| 211 | |
| 212 | |
| 213 =head2 verbose | |
| 214 | |
| 215 Title : verbose | |
| 216 Usage : $self->verbose(1) | |
| 217 Function: Sets verbose level for how ->warn behaves | |
| 218 -1 = no warning | |
| 219 0 = standard, small warning | |
| 220 1 = warning with stack trace | |
| 221 2 = warning becomes throw | |
| 222 Returns : The current verbosity setting (integer between -1 to 2) | |
| 223 Args : -1,0,1 or 2 | |
| 224 | |
| 225 | |
| 226 =cut | |
| 227 | |
| 228 sub verbose { | |
| 229 my ($self,$value) = @_; | |
| 230 # allow one to set global verbosity flag | |
| 231 return $DEBUG if $DEBUG; | |
| 232 return $VERBOSITY unless ref $self; | |
| 233 | |
| 234 if (defined $value || ! defined $self->{'_root_verbose'}) { | |
| 235 $self->{'_root_verbose'} = $value || 0; | |
| 236 } | |
| 237 return $self->{'_root_verbose'}; | |
| 238 } | |
| 239 | |
| 240 sub _register_for_cleanup { | |
| 241 my ($self,$method) = @_; | |
| 242 if($method) { | |
| 243 if(! exists($self->{'_root_cleanup_methods'})) { | |
| 244 $self->{'_root_cleanup_methods'} = []; | |
| 245 } | |
| 246 push(@{$self->{'_root_cleanup_methods'}},$method); | |
| 247 } | |
| 248 } | |
| 249 | |
| 250 sub _unregister_for_cleanup { | |
| 251 my ($self,$method) = @_; | |
| 252 my @methods = grep {$_ ne $method} $self->_cleanup_methods; | |
| 253 $self->{'_root_cleanup_methods'} = \@methods; | |
| 254 } | |
| 255 | |
| 256 | |
| 257 sub _cleanup_methods { | |
| 258 my $self = shift; | |
| 259 return unless ref $self && $self->isa('HASH'); | |
| 260 my $methods = $self->{'_root_cleanup_methods'} or return; | |
| 261 @$methods; | |
| 262 | |
| 263 } | |
| 264 | |
| 265 =head2 throw | |
| 266 | |
| 267 Title : throw | |
| 268 Usage : $obj->throw("throwing exception message"); | |
| 269 or | |
| 270 $obj->throw( -class => 'Bio::Root::Exception', | |
| 271 -text => "throwing exception message", | |
| 272 -value => $bad_value ); | |
| 273 Function: Throws an exception, which, if not caught with an eval or | |
| 274 a try block will provide a nice stack trace to STDERR | |
| 275 with the message. | |
| 276 If Error.pm is installed, and if a -class parameter is | |
| 277 provided, Error::throw will be used, throwing an error | |
| 278 of the type specified by -class. | |
| 279 If Error.pm is installed and no -class parameter is provided | |
| 280 (i.e., a simple string is given), A Bio::Root::Exception | |
| 281 is thrown. | |
| 282 Returns : n/a | |
| 283 Args : A string giving a descriptive error message, optional | |
| 284 Named parameters: | |
| 285 '-class' a string for the name of a class that derives | |
| 286 from Error.pm, such as any of the exceptions | |
| 287 defined in Bio::Root::Exception. | |
| 288 Default class: Bio::Root::Exception | |
| 289 '-text' a string giving a descriptive error message | |
| 290 '-value' the value causing the exception, or $! (optional) | |
| 291 | |
| 292 Thus, if only a string argument is given, and Error.pm is available, | |
| 293 this is equivalent to the arguments: | |
| 294 -text => "message", | |
| 295 -class => Bio::Root::Exception | |
| 296 Comments : If Error.pm is installed, and you don't want to use it | |
| 297 for some reason, you can block the use of Error.pm by | |
| 298 Bio::Root::Root::throw() by defining a scalar named | |
| 299 $main::DONT_USE_ERROR (define it in your main script | |
| 300 and you don't need the main:: part) and setting it to | |
| 301 a true value; you must do this within a BEGIN subroutine. | |
| 302 | |
| 303 =cut | |
| 304 | |
| 305 #' | |
| 306 | |
| 307 sub throw{ | |
| 308 my ($self,@args) = @_; | |
| 309 | |
| 310 my ( $text, $class ) = $self->_rearrange( [qw(TEXT CLASS)], @args); | |
| 311 | |
| 312 if( $ERRORLOADED ) { | |
| 313 # print STDERR " Calling Error::throw\n\n"; | |
| 314 | |
| 315 # Enable re-throwing of Error objects. | |
| 316 # If the error is not derived from Bio::Root::Exception, | |
| 317 # we can't guarantee that the Error's value was set properly | |
| 318 # and, ipso facto, that it will be catchable from an eval{}. | |
| 319 # But chances are, if you're re-throwing non-Bio::Root::Exceptions, | |
| 320 # you're probably using Error::try(), not eval{}. | |
| 321 # TODO: Fix the MSG: line of the re-thrown error. Has an extra line | |
| 322 # containing the '----- EXCEPTION -----' banner. | |
| 323 if( ref($args[0])) { | |
| 324 if( $args[0]->isa('Error')) { | |
| 325 my $class = ref $args[0]; | |
| 326 throw $class ( @args ); | |
| 327 } else { | |
| 328 my $text .= "\nWARNING: Attempt to throw a non-Error.pm object: " . ref$args[0]; | |
| 329 my $class = "Bio::Root::Exception"; | |
| 330 throw $class ( '-text' => $text, '-value' => $args[0] ); | |
| 331 } | |
| 332 } else { | |
| 333 $class ||= "Bio::Root::Exception"; | |
| 334 | |
| 335 my %args; | |
| 336 if( @args % 2 == 0 && $args[0] =~ /^-/ ) { | |
| 337 %args = @args; | |
| 338 $args{-text} = $text; | |
| 339 $args{-object} = $self; | |
| 340 } | |
| 341 | |
| 342 throw $class ( scalar keys %args > 0 ? %args : @args ); # (%args || @args) puts %args in scalar context! | |
| 343 } | |
| 344 } | |
| 345 else { | |
| 346 # print STDERR " Not calling Error::throw\n\n"; | |
| 347 $class ||= ''; | |
| 348 my $std = $self->stack_trace_dump(); | |
| 349 my $title = "------------- EXCEPTION $class -------------"; | |
| 350 my $footer = "\n" . '-' x CORE::length($title); | |
| 351 $text ||= ''; | |
| 352 | |
| 353 my $out = "\n$title\n" . | |
| 354 "MSG: $text\n". $std . $footer . "\n"; | |
| 355 | |
| 356 die $out; | |
| 357 } | |
| 358 } | |
| 359 | |
| 360 =head2 debug | |
| 361 | |
| 362 Title : debug | |
| 363 Usage : $obj->debug("This is debugging output"); | |
| 364 Function: Prints a debugging message when verbose is > 0 | |
| 365 Returns : none | |
| 366 Args : message string(s) to print to STDERR | |
| 367 | |
| 368 =cut | |
| 369 | |
| 370 sub debug{ | |
| 371 my ($self,@msgs) = @_; | |
| 372 | |
| 373 if( $self->verbose > 0 ) { | |
| 374 print STDERR join("", @msgs); | |
| 375 } | |
| 376 } | |
| 377 | |
| 378 =head2 _load_module | |
| 379 | |
| 380 Title : _load_module | |
| 381 Usage : $self->_load_module("Bio::SeqIO::genbank"); | |
| 382 Function: Loads up (like use) the specified module at run time on demand. | |
| 383 Example : | |
| 384 Returns : TRUE on success. Throws an exception upon failure. | |
| 385 . | |
| 386 Args : The module to load (_without_ the trailing .pm). | |
| 387 | |
| 388 =cut | |
| 389 | |
| 390 sub _load_module { | |
| 391 my ($self, $name) = @_; | |
| 392 my ($module, $load, $m); | |
| 393 $module = "_<$name.pm"; | |
| 394 return 1 if $main::{$module}; | |
| 395 | |
| 396 # untaint operation for safe web-based running (modified after a fix | |
| 397 # a fix by Lincoln) HL | |
| 398 if ($name !~ /^([\w:]+)$/) { | |
| 399 $self->throw("$name is an illegal perl package name"); | |
| 400 } | |
| 401 | |
| 402 $load = "$name.pm"; | |
| 403 my $io = Bio::Root::IO->new(); | |
| 404 # catfile comes from IO | |
| 405 $load = $io->catfile((split(/::/,$load))); | |
| 406 eval { | |
| 407 require $load; | |
| 408 }; | |
| 409 if ( $@ ) { | |
| 410 $self->throw("Failed to load module $name. ".$@); | |
| 411 } | |
| 412 return 1; | |
| 413 } | |
| 414 | |
| 415 | |
| 416 sub DESTROY { | |
| 417 my $self = shift; | |
| 418 my @cleanup_methods = $self->_cleanup_methods or return; | |
| 419 for my $method (@cleanup_methods) { | |
| 420 $method->($self); | |
| 421 } | |
| 422 } | |
| 423 | |
| 424 | |
| 425 | |
| 426 1; | |
| 427 |
