File Coverage

blib/lib/Data/Handle/Exception.pm
Criterion Covered Total %
statement 74 76 97.3
branch 10 16 62.5
condition n/a
subroutine 13 13 100.0
pod 3 3 100.0
total 100 108 92.5


line stmt bran cond sub pod time code
1 4     4   22 use strict;
  4         10  
  4         167  
2 4     4   23 use warnings;
  4         48  
  4         196  
3              
4             package Data::Handle::Exception;
5             BEGIN {
6 4     4   163 $Data::Handle::Exception::AUTHORITY = 'cpan:KENTNL';
7             }
8             {
9             $Data::Handle::Exception::VERSION = '0.02001003';
10             }
11              
12             # ABSTRACT: Super-light Weight Dependency Free Exception base.
13              
14              
15              
16 4     4   12674 use overload '""' => \&stringify;
  4         4529  
  4         47  
17 4     4   258 use Scalar::Util qw( blessed );
  4         9  
  4         275  
18 4     4   21 use Carp 1.22;
  4         143  
  4         255  
19 4     4   4598 use Term::ANSIColor qw( :constants );
  4         40120  
  4         7440  
20              
21             if ( not defined &Carp::caller_info ) {
22             Carp::croak(q{Cannot load Data::Handle::Exception as your version of Carp does not have ::caller_info which we use for backtraces, Carp Version: } .
23             $Carp::VERSION );
24             }
25              
26              
27              
28             sub new {
29 25     25 1 42 my ($class) = @_;
30 25         47 my $self = {};
31 25         77 bless $self, $class;
32 25         55 return $self;
33             }
34              
35              
36              
37             sub throw {
38 25     25 1 41 my $self = shift;
39              
40 25 50       101 if ( not blessed $self ) {
41 25         112 $self = $self->new();
42             }
43 25         47 my $message = shift;
44              
45 25         42 my @stack = ();
46 25         44 my @stacklines = ();
47              
48             # This is mostly because want to benefit from all new fixes in carp.
49 25         55 my $callerinfo = \&Carp::caller_info;
50             { # stolen parts from Carp::ret_backtrace
51 25         92 my ($i) = 0;
  25         48  
52              
53 25         38 my $tid_msg = q{};
54 25 50       77 if ( defined &threads::tid ) {
55 0         0 my $tid = threads->tid;
56 0 0       0 $tid_msg = " thread $tid" if $tid;
57             }
58              
59 25         1905 my %i = $callerinfo->($i);
60              
61 25         78 push @stack, \%i;
62 25         225 push @stacklines, sprintf q{Exception '%s' thrown at %s line %s%s}, blessed($self), $i{file}, $i{line}, $tid_msg;
63              
64 25         1189 while ( my %j = $callerinfo->( ++$i ) ) {
65 156         2110 push @stack, \%j;
66 156         5525 push @stacklines, sprintf q{%s called at %s line %s%s}, $j{sub_name}, $j{file}, $j{line}, $tid_msg;
67             }
68             }
69 25         991 $self->{message} = $message;
70 25         49 $self->{stacklines} = \@stacklines;
71 25         85 $self->{stack} = \@stack;
72 25         668 Carp::confess($self);
73             }
74              
75             {
76             ## no critic ( RequireInterpolationOfMetachars )
77             my $s = q{(\x2F|\x5c)};
78             my $d = q{\x2E};
79             ## use critic
80             my $yellow = qr{
81             ${s}Try${s}Tiny${d}pm
82             |
83             ${s}Test${s}Fatal${d}pm
84             }x;
85             my $green = qr{
86             ${s}Data${s}Handle${d}pm
87             |
88             ${s}Data${s}Handle${s}
89             }x;
90              
91             sub _color_for_line {
92 188     188   227 my $line = shift;
93 188 100       5461 return YELLOW if ( $line =~ $yellow );
94 84 100       2603 return GREEN if ( $line =~ $green );
95 52         1106 return q{};
96             }
97             }
98              
99              
100             sub stringify {
101             ## no critic ( ProhibitPunctuationVars )
102 26     26 1 344 local $@ = undef; # Term::ANSIColour clobbers $@
103 26         37 my $self = shift;
104 26         52 my $message = $self->{message};
105 26         39 my @stacklines = @{ $self->{stacklines} };
  26         88  
106              
107 26         55 my $out = $message . "\n\n";
108 26         34 my $throwline = shift @stacklines;
109 26         62 $out .= _color_for_line($throwline) . $throwline . RESET;
110 26         2738 my $i = 2;
111 26         54 for (@stacklines) {
112 162         280 $out .= "\n " . _color_for_line($_) . "$i. " . $_ . RESET;
113 162         4346 $i++;
114             }
115 26         330 return $out . "\n\n";
116             }
117             my $dynaexceptions = { 'Data::Handle::Exception' => 1 };
118              
119             sub _gen {
120 36     36   53 my ( $self, $fullclass, $parent ) = @_;
121             ## no critic ( RequireInterpolationOfMetachars )
122 36         101 my $code = sprintf q{package %s; our @ISA=("%s"); 1;}, $fullclass, $parent;
123              
124             ## no critic ( ProhibitStringyEval RequireCarping ProhibitPunctuationVars )
125 36 50       2456 eval $code or throw(qq{ Exception generating exception :[ $@ });
126 36         131 $dynaexceptions->{$fullclass} = 1;
127 36         64 return 1;
128             }
129              
130             sub _gen_tree {
131 36     36   56 my ( $self, $class ) = @_;
132 36         43 my $parent = $class;
133              
134 36         191 $parent =~ s{
135             ::[^:]+$
136             }{}x;
137 36 100       102 if ( !exists $dynaexceptions->{$parent} ) {
138 8         30 $self->_gen_tree($parent);
139             }
140 36 50       102 if ( !exists $dynaexceptions->{$class} ) {
141 36         84 $self->_gen( $class, $parent );
142             }
143 36         71 return $class;
144             }
145              
146             for (qw( API::Invalid API::Invalid::Whence API::Invalid::Params API::NotImplemented Internal::BadGet NoSymbol BadFilePos )) {
147             __PACKAGE__->_gen_tree("Data::Handle::Exception::$_");
148             }
149              
150             1;
151              
152             __END__