File Coverage

lib/Data/Handle/Exception.pm
Criterion Covered Total %
statement 76 78 97.4
branch 10 16 62.5
condition n/a
subroutine 13 13 100.0
pod 3 3 100.0
total 102 110 92.7


line stmt bran cond sub pod time code
1 6     6   843 use 5.008; # _use_carp_version
  6         18  
  6         228  
2 6     6   23 use strict;
  6         6  
  6         148  
3 6     6   27 use warnings;
  6         8  
  6         352  
4              
5             package Data::Handle::Exception;
6              
7             our $VERSION = '1.000000';
8              
9             # ABSTRACT: Super-light Weight Dependency Free Exception base.
10              
11             our $AUTHORITY = 'cpan:KENTNL'; # AUTHORITY
12              
13              
14              
15              
16              
17              
18              
19              
20              
21              
22              
23              
24              
25              
26              
27              
28              
29              
30              
31              
32              
33              
34              
35              
36              
37              
38              
39              
40              
41              
42 6     6   4088 use overload '""' => \&stringify;
  6         3381  
  6         40  
43 6     6   302 use Scalar::Util qw( blessed );
  6         6  
  6         299  
44 6     6   22 use Carp 1.22;
  6         106  
  6         288  
45 6     6   3522 use Term::ANSIColor qw( YELLOW GREEN RESET );
  6         35645  
  6         5824  
46              
47             if ( not defined &Carp::caller_info ) { ## no critic (Subroutines)
48             Carp::croak(<<"EOF");
49             Cannot load Data::Handle::Exception as your version of Carp does not have
50             ::caller_info which we use for backtraces.
51             Carp Version: $Carp::VERSION
52             EOF
53             }
54              
55              
56              
57              
58              
59              
60              
61              
62             sub new {
63 25     25 1 35 my ($class) = @_;
64 25         35 my $self = {};
65 25         52 bless $self, $class;
66 25         50 return $self;
67             }
68              
69              
70              
71              
72              
73              
74              
75             sub throw {
76 25     25 1 34 my $self = shift;
77              
78 25 50       80 if ( not blessed $self ) {
79 25         84 $self = $self->new();
80             }
81 25         37 my $message = shift;
82              
83 25         35 my @stack = ();
84 25         34 my @stacklines = ();
85              
86             # This is mostly because want to benefit from all new fixes in carp.
87 25         47 my $callerinfo = \&Carp::caller_info; ## no critic (Subroutines)
88              
89             { # stolen parts from Carp::ret_backtrace
90 25         29 my ($i) = 0;
  25         35  
91              
92 25         29 my $tid_msg = q{};
93 25 50       64 if ( defined &threads::tid ) { ## no critic (Subroutines)
94              
95 0         0 my $tid = threads->tid;
96 0 0       0 $tid_msg = " thread $tid" if $tid;
97             }
98              
99 25         1665 my %i = $callerinfo->($i);
100              
101 25         70 push @stack, \%i;
102 25         212 push @stacklines, sprintf q{Exception '%s' thrown at %s line %s%s}, blessed($self), $i{file}, $i{line}, $tid_msg;
103              
104 25         1042 while ( my %j = $callerinfo->( ++$i ) ) {
105 156         1736 push @stack, \%j;
106 156         4385 push @stacklines, sprintf q{%s called at %s line %s%s}, $j{sub_name}, $j{file}, $j{line}, $tid_msg;
107             }
108             }
109 25         798 $self->{message} = $message;
110 25         45 $self->{stacklines} = \@stacklines;
111 25         44 $self->{stack} = \@stack;
112 25         579 Carp::confess($self);
113             }
114              
115             {
116             ## no critic ( RequireInterpolationOfMetachars )
117             my $s = q{(\x2F|\x5c)};
118             my $d = q{\x2E};
119             ## use critic
120             my $yellow = qr{
121             ${s}Try${s}Tiny${d}pm
122             |
123             ${s}Test${s}Fatal${d}pm
124             }x;
125             my $green = qr{
126             ${s}Data${s}Handle${d}pm
127             |
128             ${s}Data${s}Handle${s}
129             }x;
130              
131             sub _color_for_line {
132 188     188   177 my $line = shift;
133 188 100       4430 return YELLOW if ( $line =~ $yellow );
134 84 100       2029 return GREEN if ( $line =~ $green );
135 52         966 return q{};
136             }
137             }
138              
139              
140              
141              
142              
143              
144              
145              
146              
147              
148              
149              
150              
151              
152              
153              
154              
155              
156              
157              
158              
159              
160              
161              
162              
163              
164              
165              
166              
167              
168              
169              
170              
171              
172             sub stringify {
173             ## no critic ( ProhibitPunctuationVars )
174 26     26 1 299 local $@ = undef; # Term::ANSIColour clobbers $@
175 26         36 my $self = shift;
176 26         46 my $message = $self->{message};
177 26         28 my @stacklines = @{ $self->{stacklines} };
  26         123  
178              
179 26         50 my $out = $message . "\n\n";
180 26         33 my $throwline = shift @stacklines;
181 26         52 $out .= _color_for_line($throwline) . $throwline . RESET;
182 26         2023 my $i = 2;
183 26         52 for (@stacklines) {
184 162         260 $out .= "\n " . _color_for_line($_) . "$i. " . $_ . RESET;
185 162         3401 $i++;
186             }
187 26         268 return $out . "\n\n";
188             }
189             my $dynaexceptions = { 'Data::Handle::Exception' => 1 };
190              
191             sub _gen {
192 54     54   75 my ( undef, $fullclass, $parent ) = @_;
193             ## no critic ( RequireInterpolationOfMetachars )
194 54         155 my $code = sprintf q{package %s; our @ISA=("%s"); 1;}, $fullclass, $parent;
195              
196             ## no critic ( ProhibitStringyEval RequireCarping ProhibitPunctuationVars )
197 54 50       3113 eval $code or throw(qq{ Exception generating exception :[ $@ });
198 54         139 $dynaexceptions->{$fullclass} = 1;
199 54         72 return 1;
200             }
201              
202             sub _gen_tree {
203 54     54   56 my ( $self, $class ) = @_;
204 54         61 my $parent = $class;
205              
206 54         232 $parent =~ s{
207             ::[^:]+$
208             }{}x;
209 54 100       106 if ( !exists $dynaexceptions->{$parent} ) {
210 12         27 $self->_gen_tree($parent);
211             }
212 54 50       105 if ( !exists $dynaexceptions->{$class} ) {
213 54         80 $self->_gen( $class, $parent );
214             }
215 54         87 return $class;
216             }
217              
218             for (qw( API::Invalid API::Invalid::Whence API::Invalid::Params API::NotImplemented Internal::BadGet NoSymbol BadFilePos )) {
219             __PACKAGE__->_gen_tree("Data::Handle::Exception::$_");
220             }
221              
222             1;
223              
224             __END__