File Coverage

blib/lib/Bio/Phylo/Util/Exceptions.pm
Criterion Covered Total %
statement 167 187 89.3
branch 23 50 46.0
condition 0 3 0.0
subroutine 46 49 93.8
pod 5 5 100.0
total 241 294 81.9


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