File Coverage

blib/lib/Data/Handle/Exception.pm
Criterion Covered Total %
statement 75 77 97.4
branch 10 16 62.5
condition n/a
subroutine 13 13 100.0
pod 3 3 100.0
total 101 109 92.6


line stmt bran cond sub pod time code
1 6     6   432 use 5.008; # _use_carp_version
  6         15  
2 6     6   20 use strict;
  6         8  
  6         112  
3 6     6   26 use warnings;
  6         6  
  6         385  
4              
5             package Data::Handle::Exception;
6              
7             our $VERSION = '1.000001';
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   4385 use overload '""' => \&stringify;
  6         6795  
  6         47  
43 6     6   343 use Scalar::Util qw( blessed );
  6         7  
  6         330  
44 6     6   20 use Carp 1.22;
  6         107  
  6         293  
45 6     6   3192 use Term::ANSIColor qw( YELLOW GREEN RESET );
  6         29610  
  6         6732  
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 46 my ($class) = @_;
64 25         45 my $self = {};
65 25         51 bless $self, $class;
66 25         56 return $self;
67             }
68              
69              
70              
71              
72              
73              
74              
75             sub throw {
76 25     25 1 53 my $self = shift;
77              
78 25 50       116 if ( not blessed $self ) {
79 25         98 $self = $self->new();
80             }
81 25         41 my $message = shift;
82              
83 25         46 my @stack = ();
84 25         47 my @stacklines = ();
85              
86             # This is mostly because want to benefit from all new fixes in carp.
87 25         89 my $callerinfo = \&Carp::caller_info; ## no critic (Subroutines)
88              
89             { # stolen parts from Carp::ret_backtrace
90 25         34 my ($i) = 0;
  25         37  
91              
92 25         39 my $tid_msg = q{};
93 25 50       73 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         2135 my %i = $callerinfo->($i);
100              
101 25         80 push @stack, \%i;
102 25         280 push @stacklines, sprintf q{Exception '%s' thrown at %s line %s%s}, blessed($self), $i{file}, $i{line}, $tid_msg;
103              
104 25         1408 while ( my %j = $callerinfo->( ++$i ) ) {
105 156         2378 push @stack, \%j;
106 156         6551 push @stacklines, sprintf q{%s called at %s line %s%s}, $j{sub_name}, $j{file}, $j{line}, $tid_msg;
107             }
108             }
109 25         368 $self->{message} = $message;
110 25         60 $self->{stacklines} = \@stacklines;
111 25         48 $self->{stack} = \@stack;
112 25         699 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   209 my $line = shift;
133 188 100       4997 return YELLOW if ( $line =~ $yellow );
134 84 100       2846 return GREEN if ( $line =~ $green );
135 52         1083 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 453 local $@ = undef; # Term::ANSIColour clobbers $@
175 26         45 my $self = shift;
176 26         53 my $message = $self->{message};
177 26         34 my @stacklines = @{ $self->{stacklines} };
  26         90  
178              
179 26         90 my $out = $message . "\n\n";
180 26         39 my $throwline = shift @stacklines;
181 26         73 $out .= _color_for_line($throwline) . $throwline . RESET;
182 26         2103 my $i = 2;
183 26         60 for (@stacklines) {
184 162         253 $out .= "\n " . _color_for_line($_) . "$i. " . $_ . RESET;
185 162         3881 $i++;
186             }
187 26         378 return $out . "\n\n";
188             }
189             my $dynaexceptions = { 'Data::Handle::Exception' => 1 };
190              
191             sub _gen {
192 54     54   71 my ( undef, $fullclass, $parent ) = @_;
193             ## no critic ( RequireInterpolationOfMetachars )
194 54         137 my $code = sprintf q{package %s; our @ISA=("%s"); 1;}, $fullclass, $parent;
195              
196             ## no critic ( ProhibitStringyEval RequireCarping ProhibitPunctuationVars )
197 54 50       3322 eval $code or throw(qq{ Exception generating exception :[ $@ });
198 54         127 $dynaexceptions->{$fullclass} = 1;
199 54         72 return 1;
200             }
201              
202             sub _gen_tree {
203 54     54   57 my ( $self, $class ) = @_;
204 54         80 my $parent = $class;
205              
206 54         214 $parent =~ s{
207             ::[^:]+$
208             }{}x;
209 54 100       119 if ( !exists $dynaexceptions->{$parent} ) {
210 12         36 $self->_gen_tree($parent);
211             }
212 54 50       97 if ( !exists $dynaexceptions->{$class} ) {
213 54         75 $self->_gen( $class, $parent );
214             }
215 54         71 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__