File Coverage

blib/lib/Bio/Phylo/Util/Exceptions.pm
Criterion Covered Total %
statement 170 190 89.4
branch 23 50 46.0
condition 0 3 0.0
subroutine 47 50 94.0
pod 5 5 100.0
total 245 298 82.2


line stmt bran cond sub pod time code
1             package Bio::Phylo::Util::Exceptions;
2 57     57   354 use strict;
  57         104  
  57         1384  
3 57     57   283 use warnings;
  57         102  
  57         1301  
4 57     57   266 use base 'Exporter';
  57         115  
  57         5538  
5 57     57   14227 use Bio::Phylo::Util::StackTrace;
  57         135  
  57         1490  
6 57     57   324 use Scalar::Util 'blessed';
  57         107  
  57         3922  
7 57     57   46478 use overload 'bool' => sub { 1 }, 'fallback' => 1, '""' => \&as_string;
  57     208   46293  
  57         498  
  208         537  
8             our ( @EXPORT_OK, $AUTOLOAD ) = qw'throw';
9              
10             sub new {
11 176     176 1 420 my $class = shift;
12 176         538 my %args = @_;
13 176         911 my $self = {
14              
15             # 'error' => $args{'error'},
16             # 'description' => $args{'description'},
17             'trace' => Bio::Phylo::Util::StackTrace->new,
18             'time' => CORE::time(),
19             'pid' => $$,
20             'uid' => $<,
21             'euid' => $>,
22             'gid' => $(,
23             'egid' => $),
24             %args
25             };
26 176         675 return bless $self, $class;
27             }
28              
29             sub as_string {
30 0     0 1 0 my $self = shift;
31 0         0 my $error = $self->error;
32 0         0 my $description = $self->description;
33 0         0 my $class = ref $self;
34 0         0 my $trace = join "\n", map { "STACK: $_" } split '\n',
  0         0  
35             $self->trace->as_string;
36 0         0 return <<"ERROR_HERE_DOC";
37             -------------------------- EXCEPTION ----------------------------
38             Message: $error
39              
40             An exception of type $class
41             was thrown.
42              
43             $description
44              
45             Refer to the Bio::Phylo::Util::Exceptions documentation for more
46             information.
47             ------------------------- STACK TRACE ---------------------------
48             $trace
49             -----------------------------------------------------------------
50             ERROR_HERE_DOC
51             }
52              
53             sub throw (@) {
54              
55             # called as static method, with odd args
56 176     176 1 292 my $self;
57 176 50       562 if ( scalar @_ % 2 ) {
58 0         0 my $class = shift;
59 0         0 $self = $class->new(@_);
60             }
61              
62             # called as function, with even args e.g. throw BadArgs => 'msg';
63             else {
64 176         326 my $type = shift;
65 176         392 my $class = __PACKAGE__ . '::' . $type;
66 176 50       1963 if ( $class->isa('Bio::Phylo::Util::Exceptions') ) {
67 176         783 $self = $class->new( 'error' => shift, @_ );
68             }
69             else {
70 0         0 $self = Bio::Phylo::Util::Exceptions::Generic->new(
71             'error' => shift,
72             @_
73             );
74             }
75             }
76              
77             # if ( not $ENV{'PERL_DL_NONLAZY'} ) {
78             # require Bio::Phylo;
79             # $Bio::Phylo::Util::Logger::TRACEBACK = 1;
80             # my $logger = Bio::Phylo->get_logger();
81             # $logger->error($self->error);
82             # $Bio::Phylo::Util::Logger::TRACEBACK = 0;
83             # }
84 176         813 die $self;
85             }
86              
87             sub rethrow {
88 0     0 1 0 my $self = shift;
89 0         0 die $self;
90             }
91              
92             sub caught {
93 0     0 1 0 my $class = shift;
94 0 0       0 if (@_) {
95 0         0 $class = shift;
96             }
97 0 0       0 if ($@) {
98 0 0 0     0 if ( blessed $@ and $@->isa($class) ) {
99 0         0 return $@;
100             }
101             else {
102 0         0 die $@;
103             }
104             }
105             }
106              
107             sub AUTOLOAD {
108 176     176   2965 my $self = shift;
109 176         328 my $field = $AUTOLOAD;
110 176         972 $field =~ s/.*://;
111 176 50       6829 return if $field eq 'DESTROY';
112 0         0 return $self->{$field};
113             }
114              
115             sub _make_exceptions {
116 57     57   131 my $class = shift;
117 57         97 my $root = shift;
118 57         658 my %exceptions = @_;
119 57         310 for my $exception ( keys %exceptions ) {
120 1026         1933 my $isa = $exceptions{$exception}->{'isa'};
121 1026 100       2791 my @isa = ref $isa ? @$isa : ($isa);
122 1026         1545 my $description = $exceptions{$exception}->{'description'};
123 1026         3102 my $class = <<"EXCEPTION_CLASS";
124             package ${exception};
125             use vars '\@ISA';
126             \@ISA=qw(@isa);
127             my \$desc;
128             sub description {
129             my \$self = shift;
130             if ( \@_ ) {
131             \$desc = shift;
132             }
133             return \$desc;
134             }
135             1;
136             EXCEPTION_CLASS
137 57 50   57   401 eval $class;
  57 50   57   131  
  57 50   57   4804  
  57 50   57   365  
  57 50   57   117  
  57 50   57   4070  
  57 50   57   361  
  57 50   57   116  
  57 50   57   3717  
  57 50   57   394  
  57 50   57   120  
  57 50   57   3896  
  57 50   57   359  
  57 50   57   107  
  57 50   57   3912  
  57 50   57   335  
  57 50   57   844  
  57 50   57   5451  
  57     57   320  
  57     57   121  
  57     57   3692  
  57     57   312  
  57     57   705  
  57     57   3745  
  57     57   344  
  57     57   501  
  57     57   3763  
  57     57   315  
  57     57   105  
  57     57   3700  
  57     57   323  
  57     57   132  
  57     57   3695  
  57     57   316  
  57     57   100  
  57     57   3735  
  57         348  
  57         142  
  57         3818  
  57         318  
  57         98  
  57         3676  
  57         319  
  57         111  
  57         3720  
  57         344  
  57         101  
  57         3757  
  57         322  
  57         108  
  57         3749  
  57         311  
  57         118  
  57         3669  
  1026         63634  
  57         184  
  57         209  
  57         122  
  57         174  
  57         167  
  57         220  
  57         116  
  57         187  
  57         165  
  57         213  
  57         110  
  57         172  
  57         190  
  57         217  
  57         111  
  57         174  
  57         186  
  57         201  
  57         106  
  57         169  
  57         186  
  57         208  
  57         109  
  57         177  
  57         208  
  57         198  
  57         106  
  57         176  
  57         176  
  57         850  
  57         113  
  57         176  
  57         183  
  57         199  
  57         112  
  57         166  
  57         206  
  57         856  
  57         110  
  57         178  
  57         193  
  57         215  
  57         115  
  57         169  
  57         189  
  57         215  
  57         120  
  57         165  
  57         190  
  57         199  
  57         102  
  57         172  
  57         215  
  57         206  
  57         104  
  57         182  
  57         240  
  57         212  
  57         108  
  57         179  
  57         212  
  57         212  
  57         108  
  57         171  
  57         177  
  57         255  
  57         120  
  57         164  
  57         182  
  57         209  
  57         130  
  57         187  
138 1026         23779 $exception->description($description);
139             }
140             }
141             __PACKAGE__->_make_exceptions(
142              
143             # root classes
144             'Bio::Phylo::Util::Exceptions',
145             'Bio::Phylo::Util::Exceptions::Generic' => {
146             'isa' => 'Bio::Phylo::Util::Exceptions',
147             'description' =>
148             "No further details about this type of error are available."
149             },
150              
151             # exceptions on method calls
152             'Bio::Phylo::Util::Exceptions::API' => {
153             'isa' => 'Bio::Phylo::Util::Exceptions::Generic',
154             'description' =>
155             "No more details about this type of error are available."
156             },
157             'Bio::Phylo::Util::Exceptions::UnknownMethod' => {
158             'isa' => 'Bio::Phylo::Util::Exceptions::API',
159             'description' =>
160             "This kind of error happens when a non-existent method is called.",
161             },
162             'Bio::Phylo::Util::Exceptions::NotImplemented' => {
163             'isa' => 'Bio::Phylo::Util::Exceptions::API',
164             'description' =>
165             "This kind of error happens when a non-implemented\n(interface) method is called.",
166             },
167             'Bio::Phylo::Util::Exceptions::Deprecated' => {
168             'isa' => 'Bio::Phylo::Util::Exceptions::API',
169             'description' =>
170             "This kind of error happens when a deprecated method is called.",
171             },
172              
173             # exceptions on arguments
174             'Bio::Phylo::Util::Exceptions::BadArgs' => {
175             'isa' => 'Bio::Phylo::Util::Exceptions::Generic',
176             'description' =>
177             "This kind of error happens when bad or incomplete arguments\nare provided.",
178             },
179             'Bio::Phylo::Util::Exceptions::BadString' => {
180             'isa' => 'Bio::Phylo::Util::Exceptions::BadArgs',
181             'description' =>
182             "This kind of error happens when an unsafe string argument is\nprovided.",
183             },
184             'Bio::Phylo::Util::Exceptions::OddHash' => {
185             'isa' => 'Bio::Phylo::Util::Exceptions::BadArgs',
186             'description' =>
187             "This kind of error happens when an uneven number\nof arguments (so no key/value pairs) was provided.",
188             },
189             'Bio::Phylo::Util::Exceptions::ObjectMismatch' => {
190             'isa' => 'Bio::Phylo::Util::Exceptions::BadArgs',
191             'description' =>
192             "This kind of error happens when an invalid object\nargument is provided.",
193             },
194             'Bio::Phylo::Util::Exceptions::InvalidData' => {
195             'isa' => [
196             'Bio::Phylo::Util::Exceptions::BadString',
197             'Bio::Phylo::Util::Exceptions::BadFormat',
198             ],
199             'description' =>
200             "This kind of error happens when invalid character data is\nprovided."
201             },
202             'Bio::Phylo::Util::Exceptions::OutOfBounds' => {
203             'isa' => 'Bio::Phylo::Util::Exceptions::BadArgs',
204             'description' =>
205             "This kind of error happens when an index is outside of its range.",
206             },
207             'Bio::Phylo::Util::Exceptions::BadNumber' => {
208             'isa' => 'Bio::Phylo::Util::Exceptions::Generic',
209             'description' =>
210             "This kind of error happens when an invalid numerical argument\nis provided.",
211             },
212             'Bio::Phylo::Util::Exceptions::NoData' => {
213             'isa' => 'Bio::Phylo::Util::Exceptions::Generic',
214             'description' =>
215             "This kind of error happens when a data source is empty.",
216             },
217              
218             # system exceptions
219             'Bio::Phylo::Util::Exceptions::System' => {
220             'isa' => 'Bio::Phylo::Util::Exceptions::Generic',
221             'description' =>
222             "This kind of error happens when there is a system misconfiguration.",
223             },
224             'Bio::Phylo::Util::Exceptions::FileError' => {
225             'isa' => 'Bio::Phylo::Util::Exceptions::System',
226             'description' =>
227             "This kind of error happens when a file can not be accessed.",
228             },
229             'Bio::Phylo::Util::Exceptions::NetworkError' => {
230             'isa' => 'Bio::Phylo::Util::Exceptions::System',
231             'description' =>
232             "This kind of error happens when a network resource can not be accessed.",
233             },
234             'Bio::Phylo::Util::Exceptions::ExtensionError' => {
235             'isa' => [
236             'Bio::Phylo::Util::Exceptions::System',
237             'Bio::Phylo::Util::Exceptions::BadFormat',
238             ],
239             'description' =>
240             "This kind of error happens when an extension module can not be\nloaded.",
241             },
242             'Bio::Phylo::Util::Exceptions::BadFormat' => {
243             'isa' => 'Bio::Phylo::Util::Exceptions::System',
244             'description' =>
245             "This kind of error happens when a bad\nparse or unparse format was specified.",
246             },
247             );
248             1;
249             __END__
250              
251             =head1 NAME
252              
253             Bio::Phylo::Util::Exceptions - Errors ($@) that are objects
254              
255             =head1 SYNOPSIS
256              
257             use Bio::Phylo::Forest::Node;
258             my $node = Bio::Phylo::Forest::Node->new;
259            
260             # now let's try something illegal
261             eval {
262             $node->set_branch_length( 'non-numerical value' );
263             };
264              
265             # have an error
266             if ( my $e = Bio::Phylo::Util::Exceptions::BadNumber->caught ) {
267              
268             # print out where the error came from
269             print $@->trace->as_string;
270            
271             # caught() returns $@, so $e and $@ are the
272             # same object in this example.
273             # Therefore, the same thing would be:
274             print $e->trace->as_string;
275             }
276              
277             =head1 DESCRIPTION
278              
279             Sometimes, Bio::Phylo dies. If this happens because you did something that
280             brought Bio::Phylo into an undefined and dangerous state (such as might happen
281             if you provide a non-numerical value for a setter that needs numbers),
282             Bio::Phylo will throw an "exception", a special form of the C<$@> variable
283             that is a blessed object with useful methods to help you diagnose the problem.
284              
285             This package defines the exceptions that can be thrown by Bio::Phylo. There are
286             no serviceable parts inside. Refer to the L<Exception::Class>
287             perldoc for more examples on how to catch exceptions and show traces.
288              
289             =head1 EXCEPTION CLASSES
290              
291             =over
292              
293             =item Bio::Phylo::Util::Exceptions::BadNumber
294              
295             Thrown when anything other than a number that passes L<Scalar::Util>'s
296             looks_like_number test is given as an argument to a method that expects a number.
297              
298             =item Bio::Phylo::Util::Exceptions::BadString
299              
300             Thrown when an incorrectly formatted string argument is provided, for example
301             a string that would be split into substrings under NEXUS tokenization rules,
302             a string that isn't an xs:NCName or a string that isn't a binomial CURIE
303              
304             =item Bio::Phylo::Util::Exceptions::BadFormat
305              
306             Thrown when a non-existing parser or unparser format is requested, in calls
307             such as C<< parse( -format => 'newik', -string => $string ) >>, where 'newik'
308             doesn't exist.
309              
310             =item Bio::Phylo::Util::Exceptions::OddHash
311              
312             Thrown when an odd number of arguments has been specified. This might happen if
313             you call a method that requires named arguments and the key/value pairs don't
314             seem to match up.
315              
316             =item Bio::Phylo::Util::Exceptions::ObjectMismatch
317              
318             Thrown when a method is called that requires an object as an argument, and the
319             wrong type of object is specified.
320              
321             =item Bio::Phylo::Util::Exceptions::UnknownMethod
322              
323             Trown when an indirect method call is attempted through the
324             C<< $obj->get('unknown_method') >> interface, and the object doesn't seem to
325             implement the requested method.
326              
327             =item Bio::Phylo::Util::Exceptions::BadArgs
328              
329             Thrown when something undefined is wrong with the supplied arguments.
330              
331             =item Bio::Phylo::Util::Exceptions::FileError
332              
333             Thrown when a file specified as an argument does not exist or is not readable.
334              
335             =item Bio::Phylo::Util::Exceptions::ExtensionError
336              
337             Thrown when there is an error loading a requested extension.
338              
339             =item Bio::Phylo::Util::Exceptions::OutOfBounds
340              
341             Thrown when an entity is requested that falls outside of the range of
342             objects contained by a L<Bio::Phylo::Listable> subclass, probably through
343             the C<< $obj->get_by_index($i) >> method call.
344              
345             =item Bio::Phylo::Util::Exceptions::NotImplemented
346              
347             Thrown when an interface method is called instead of the implementation
348             by the child class.
349              
350             =item Bio::Phylo::Util::Exceptions::Deprecated
351              
352             Thrown when a deprecated method is called.
353              
354             =back
355              
356             =head1 METHODS
357              
358             =over
359              
360             =item new()
361              
362             Constructor
363              
364             Type : Constructor
365             Title : new
366             Usage : $class->new( error => 'An exception was thrown!' );
367             Function: Constructs exception
368             Returns : A Bio::Phylo::Util::Exceptions object
369             Args : error => 'Error message'
370              
371             =item throw()
372              
373             Throws exception.
374              
375             Type : Exception
376             Title : throw
377             Usage : $class->throw( error => 'An exception was thrown!' );
378             Function: Throws exception
379             Returns : A Bio::Phylo::Util::Exceptions object
380             Args : error => 'Error message'
381              
382             =item caught()
383              
384             Catches an exception by class.
385              
386             Type : Handler
387             Title : caught
388             Usage : my $e = Bio::Phylo::Util::Exceptions->caught;
389             Function: Catches an exception
390             Returns : A Bio::Phylo::Util::Exceptions object
391             Args : None
392              
393             =item rethrow()
394              
395             Rethrows a caught exception.
396              
397             Type : Exception
398             Title : rethrow
399             Usage : $@->rethrow;
400             Function: Rethrows exception
401             Returns : A Bio::Phylo::Util::Exceptions object
402             Args : None
403              
404             =item as_string()
405              
406             Serializes exception.
407              
408             Type : Serializer
409             Title : as_string
410             Usage : print $@->as_string;
411             Function: Serializes exception with description and stack trace.
412             Returns : String
413             Args : None
414              
415             =back
416              
417             =head1 SEE ALSO
418              
419             There is a mailing list at L<https://groups.google.com/forum/#!forum/bio-phylo>
420             for any user or developer questions and discussions.
421              
422             =over
423              
424             =item L<Bio::Phylo::Manual>
425              
426             Also see the manual: L<Bio::Phylo::Manual> and L<http://rutgervos.blogspot.com>
427              
428             =back
429              
430             =head1 CITATION
431              
432             If you use Bio::Phylo in published research, please cite it:
433              
434             B<Rutger A Vos>, B<Jason Caravas>, B<Klaas Hartmann>, B<Mark A Jensen>
435             and B<Chase Miller>, 2011. Bio::Phylo - phyloinformatic analysis using Perl.
436             I<BMC Bioinformatics> B<12>:63.
437             L<http://dx.doi.org/10.1186/1471-2105-12-63>
438              
439              
440              
441             =cut
442