ExtUtils::MakeMaker 6.54
[p5sagit/p5-mst-13.2.git] / lib / autodie / exception.pm
CommitLineData
0b09a93a 1package autodie::exception;
2use 5.008;
3use strict;
4use warnings;
5use Carp qw(croak);
6
7our $DEBUG = 0;
8
9use overload
10 q{""} => "stringify"
11;
12
13# Overload smart-match only if we're using 5.10
14
15use if ($] >= 5.010), overload => '~~' => "matches";
16
b0745470 17our $VERSION = '2.06';
0b09a93a 18
19my $PACKAGE = __PACKAGE__; # Useful to have a scalar for hash keys.
20
21=head1 NAME
22
23autodie::exception - Exceptions from autodying functions.
24
25=head1 SYNOPSIS
26
27 eval {
28 use autodie;
29
30 open(my $fh, '<', 'some_file.txt');
31
32 ...
33 };
34
35 if (my $E = $@) {
36 say "Ooops! ",$E->caller," had problems: $@";
37 }
38
39
40=head1 DESCRIPTION
41
42When an L<autodie> enabled function fails, it generates an
43C<autodie::exception> object. This can be interrogated to
44determine further information about the error that occurred.
45
46This document is broken into two sections; those methods that
47are most useful to the end-developer, and those methods for
48anyone wishing to subclass or get very familiar with
49C<autodie::exception>.
50
51=head2 Common Methods
52
53These methods are intended to be used in the everyday dealing
54of exceptions.
55
56The following assume that the error has been copied into
57a separate scalar:
58
59 if ($E = $@) {
60 ...
61 }
62
63This is not required, but is recommended in case any code
64is called which may reset or alter C<$@>.
65
66=cut
67
68=head3 args
69
70 my $array_ref = $E->args;
71
72Provides a reference to the arguments passed to the subroutine
73that died.
74
75=cut
76
77sub args { return $_[0]->{$PACKAGE}{args}; }
78
79=head3 function
80
81 my $sub = $E->function;
82
83The subroutine (including package) that threw the exception.
84
85=cut
86
87sub function { return $_[0]->{$PACKAGE}{function}; }
88
89=head3 file
90
91 my $file = $E->file;
92
93The file in which the error occurred (eg, C<myscript.pl> or
94C<MyTest.pm>).
95
96=cut
97
98sub file { return $_[0]->{$PACKAGE}{file}; }
99
100=head3 package
101
102 my $package = $E->package;
103
104The package from which the exceptional subroutine was called.
105
106=cut
107
108sub package { return $_[0]->{$PACKAGE}{package}; }
109
110=head3 caller
111
112 my $caller = $E->caller;
113
114The subroutine that I<called> the exceptional code.
115
116=cut
117
118sub caller { return $_[0]->{$PACKAGE}{caller}; }
119
120=head3 line
121
122 my $line = $E->line;
123
124The line in C<< $E->file >> where the exceptional code was called.
125
126=cut
127
128sub line { return $_[0]->{$PACKAGE}{line}; }
129
eb8d423f 130=head3 context
131
132 my $context = $E->context;
133
134The context in which the subroutine was called. This can be
135'list', 'scalar', or undefined (unknown). It will never be 'void', as
136C<autodie> always captures the return value in one way or another.
137
138=cut
139
140sub context { return $_[0]->{$PACKAGE}{context} }
141
142=head3 return
143
144 my $return_value = $E->return;
145
146The value(s) returned by the failed subroutine. When the subroutine
147was called in a list context, this will always be a reference to an
148array containing the results. When the subroutine was called in
149a scalar context, this will be the actual scalar returned.
150
151=cut
152
153sub return { return $_[0]->{$PACKAGE}{return} }
154
0b09a93a 155=head3 errno
156
157 my $errno = $E->errno;
158
159The value of C<$!> at the time when the exception occurred.
160
161B<NOTE>: This method will leave the main C<autodie::exception> class
162and become part of a role in the future. You should only call
163C<errno> for exceptions where C<$!> would reasonably have been
164set on failure.
165
166=cut
167
168# TODO: Make errno part of a role. It doesn't make sense for
169# everything.
170
171sub errno { return $_[0]->{$PACKAGE}{errno}; }
172
173=head3 matches
174
175 if ( $e->matches('open') ) { ... }
176
177 if ( $e ~~ 'open' ) { ... }
178
179C<matches> is used to determine whether a
180given exception matches a particular role. On Perl 5.10,
181using smart-match (C<~~>) with an C<autodie::exception> object
182will use C<matches> underneath.
183
184An exception is considered to match a string if:
185
186=over 4
187
188=item *
189
190For a string not starting with a colon, the string exactly matches the
191package and subroutine that threw the exception. For example,
192C<MyModule::log>. If the string does not contain a package name,
193C<CORE::> is assumed.
194
195=item *
196
197For a string that does start with a colon, if the subroutine
198throwing the exception I<does> that behaviour. For example, the
199C<CORE::open> subroutine does C<:file>, C<:io> and C<:all>.
200
201See L<autodie/CATEGORIES> for futher information.
202
203=back
204
205=cut
206
207{
208 my (%cache);
209
210 sub matches {
211 my ($this, $that) = @_;
212
9b657a62 213 # TODO - Handle references
0b09a93a 214 croak "UNIMPLEMENTED" if ref $that;
215
216 my $sub = $this->function;
217
218 if ($DEBUG) {
219 my $sub2 = $this->function;
220 warn "Smart-matching $that against $sub / $sub2\n";
221 }
222
223 # Direct subname match.
224 return 1 if $that eq $sub;
225 return 1 if $that !~ /:/ and "CORE::$that" eq $sub;
226 return 0 if $that !~ /^:/;
227
228 # Cached match / check tags.
229 require Fatal;
230
231 if (exists $cache{$sub}{$that}) {
232 return $cache{$sub}{$that};
233 }
234
235 # This rather awful looking line checks to see if our sub is in the
236 # list of expanded tags, caches it, and returns the result.
237
238 return $cache{$sub}{$that} = grep { $_ eq $sub } @{ $this->_expand_tag($that) };
239 }
240}
241
242# This exists primarily so that child classes can override or
243# augment it if they wish.
244
245sub _expand_tag {
246 my ($this, @args) = @_;
247
248 return Fatal->_expand_tag(@args);
249}
250
251=head2 Advanced methods
252
253The following methods, while usable from anywhere, are primarily
254intended for developers wishing to subclass C<autodie::exception>,
255write code that registers custom error messages, or otherwise
256work closely with the C<autodie::exception> model.
257
258=cut
259
260# The table below records customer formatters.
261# TODO - Should this be a package var instead?
262# TODO - Should these be in a completely different file, or
263# perhaps loaded on demand? Most formatters will never
264# get used in most programs.
265
266my %formatter_of = (
267 'CORE::close' => \&_format_close,
268 'CORE::open' => \&_format_open,
269 'CORE::dbmopen' => \&_format_dbmopen,
270 'CORE::flock' => \&_format_flock,
271);
272
273# TODO: Our tests only check LOCK_EX | LOCK_NB is properly
274# formatted. Try other combinations and ensure they work
275# correctly.
276
277sub _format_flock {
278 my ($this) = @_;
279
280 require Fcntl;
281
282 my $filehandle = $this->args->[0];
283 my $raw_mode = $this->args->[1];
284
285 my $mode_type;
286 my $lock_unlock;
287
288 if ($raw_mode & Fcntl::LOCK_EX() ) {
289 $lock_unlock = "lock";
290 $mode_type = "for exclusive access";
291 }
292 elsif ($raw_mode & Fcntl::LOCK_SH() ) {
293 $lock_unlock = "lock";
294 $mode_type = "for shared access";
295 }
296 elsif ($raw_mode & Fcntl::LOCK_UN() ) {
297 $lock_unlock = "unlock";
298 $mode_type = "";
299 }
300 else {
301 # I've got no idea what they're trying to do.
302 $lock_unlock = "lock";
303 $mode_type = "with mode $raw_mode";
304 }
305
306 my $cooked_filehandle;
307
308 if ($filehandle and not ref $filehandle) {
309
310 # A package filehandle with a name!
311
312 $cooked_filehandle = " $filehandle";
313 }
314 else {
315 # Otherwise we have a scalar filehandle.
316
317 $cooked_filehandle = '';
318
319 }
320
321 local $! = $this->errno;
322
323 return "Can't $lock_unlock filehandle$cooked_filehandle $mode_type: $!";
324
325}
326
327# Default formatter for CORE::dbmopen
328sub _format_dbmopen {
329 my ($this) = @_;
330 my @args = @{$this->args};
331
332 # TODO: Presently, $args flattens out the (usually empty) hash
333 # which is passed as the first argument to dbmopen. This is
334 # a bug in our args handling code (taking a reference to it would
335 # be better), but for the moment we'll just examine the end of
336 # our arguments list for message formatting.
337
338 my $mode = $args[-1];
339 my $file = $args[-2];
340
341 # If we have a mask, then display it in octal, not decimal.
342 # We don't do this if it already looks octalish, or doesn't
343 # look like a number.
344
345 if ($mode =~ /^[^\D0]\d+$/) {
346 $mode = sprintf("0%lo", $mode);
347 };
348
349 local $! = $this->errno;
350
351 return "Can't dbmopen(%hash, '$file', $mode): '$!'";
352}
353
354# Default formatter for CORE::close
355
356sub _format_close {
357 my ($this) = @_;
358 my $close_arg = $this->args->[0];
359
360 local $! = $this->errno;
361
362 # If we've got an old-style filehandle, mention it.
363 if ($close_arg and not ref $close_arg) {
364 return "Can't close filehandle '$close_arg': '$!'";
365 }
366
367 # TODO - This will probably produce an ugly error. Test and fix.
368 return "Can't close($close_arg) filehandle: '$!'";
369
370}
371
372# Default formatter for CORE::open
373
374use constant _FORMAT_OPEN => "Can't open '%s' for %s: '%s'";
375
376sub _format_open_with_mode {
377 my ($this, $mode, $file, $error) = @_;
378
379 my $wordy_mode;
380
381 if ($mode eq '<') { $wordy_mode = 'reading'; }
382 elsif ($mode eq '>') { $wordy_mode = 'writing'; }
383 elsif ($mode eq '>>') { $wordy_mode = 'appending'; }
384
385 return sprintf _FORMAT_OPEN, $file, $wordy_mode, $error if $wordy_mode;
386
387 Carp::confess("Internal autodie::exception error: Don't know how to format mode '$mode'.");
388
389}
390
391sub _format_open {
392 my ($this) = @_;
393
394 my @open_args = @{$this->args};
395
396 # Use the default formatter for single-arg and many-arg open
397 if (@open_args <= 1 or @open_args >= 4) {
398 return $this->format_default;
399 }
400
401 # For two arg open, we have to extract the mode
402 if (@open_args == 2) {
403 my ($fh, $file) = @open_args;
404
405 if (ref($fh) eq "GLOB") {
406 $fh = '$fh';
407 }
408
409 my ($mode) = $file =~ m{
410 ^\s* # Spaces before mode
411 (
412 (?> # Non-backtracking subexp.
413 < # Reading
414 |>>? # Writing/appending
415 )
416 )
417 [^&] # Not an ampersand (which means a dup)
418 }x;
419
02b13d1d 420 if (not $mode) {
421 # Maybe it's a 2-arg open without any mode at all?
422 # Detect the most simple case for this, where our
423 # file consists only of word characters.
424
425 if ( $file =~ m{^\s*\w+\s*$} ) {
426 $mode = '<'
427 }
428 else {
429 # Otherwise, we've got no idea what's going on.
430 # Use the default.
431 return $this->format_default;
432 }
433 }
0b09a93a 434
435 # Localising $! means perl make make it a pretty error for us.
436 local $! = $this->errno;
437
438 return $this->_format_open_with_mode($mode, $file, $!);
439 }
440
441 # Here we must be using three arg open.
442
443 my $file = $open_args[2];
444
445 local $! = $this->errno;
446
447 my $mode = $open_args[1];
448
449 local $@;
450
451 my $msg = eval { $this->_format_open_with_mode($mode, $file, $!); };
452
453 return $msg if $msg;
454
455 # Default message (for pipes and odd things)
456
457 return "Can't open '$file' with mode '$open_args[1]': '$!'";
458}
459
460=head3 register
461
462 autodie::exception->register( 'CORE::open' => \&mysub );
463
464The C<register> method allows for the registration of a message
465handler for a given subroutine. The full subroutine name including
466the package should be used.
467
468Registered message handlers will receive the C<autodie::exception>
469object as the first parameter.
470
471=cut
472
473sub register {
474 my ($class, $symbol, $handler) = @_;
475
476 croak "Incorrect call to autodie::register" if @_ != 3;
477
478 $formatter_of{$symbol} = $handler;
479
480}
481
482=head3 add_file_and_line
483
484 say "Problem occurred",$@->add_file_and_line;
485
486Returns the string C< at %s line %d>, where C<%s> is replaced with
487the filename, and C<%d> is replaced with the line number.
488
489Primarily intended for use by format handlers.
490
491=cut
492
493# Simply produces the file and line number; intended to be added
494# to the end of error messages.
495
496sub add_file_and_line {
497 my ($this) = @_;
498
499 return sprintf(" at %s line %d\n", $this->file, $this->line);
500}
501
502=head3 stringify
503
504 say "The error was: ",$@->stringify;
505
506Formats the error as a human readable string. Usually there's no
507reason to call this directly, as it is used automatically if an
508C<autodie::exception> object is ever used as a string.
509
510Child classes can override this method to change how they're
511stringified.
512
513=cut
514
515sub stringify {
516 my ($this) = @_;
517
518 my $call = $this->function;
519
520 if ($DEBUG) {
521 my $dying_pkg = $this->package;
522 my $sub = $this->function;
523 my $caller = $this->caller;
524 warn "Stringifing exception for $dying_pkg :: $sub / $caller / $call\n";
525 }
526
527 # TODO - This isn't using inheritance. Should it?
528 if ( my $sub = $formatter_of{$call} ) {
529 return $sub->($this) . $this->add_file_and_line;
530 }
531
02b13d1d 532 return $this->format_default . $this->add_file_and_line;
0b09a93a 533
534}
535
536=head3 format_default
537
538 my $error_string = $E->format_default;
539
540This produces the default error string for the given exception,
541I<without using any registered message handlers>. It is primarily
542intended to be called from a message handler when they have
543been passed an exception they don't want to format.
544
545Child classes can override this method to change how default
546messages are formatted.
547
548=cut
549
550# TODO: This produces ugly errors. Is there any way we can
551# dig around to find the actual variable names? I know perl 5.10
552# does some dark and terrible magicks to find them for undef warnings.
553
554sub format_default {
555 my ($this) = @_;
556
557 my $call = $this->function;
558
559 local $! = $this->errno;
560
561 # TODO: This is probably a good idea for CORE, is it
562 # a good idea for other subs?
563
564 # Trim package name off dying sub for error messages.
565 $call =~ s/.*:://;
566
567 # Walk through all our arguments, and...
568 #
569 # * Replace undef with the word 'undef'
570 # * Replace globs with the string '$fh'
571 # * Quote all other args.
572
573 my @args = @{ $this->args() };
574
575 foreach my $arg (@args) {
576 if (not defined($arg)) { $arg = 'undef' }
577 elsif (ref($arg) eq "GLOB") { $arg = '$fh' }
578 else { $arg = qq{'$arg'} }
579 }
580
581 # Format our beautiful error.
582
02b13d1d 583 return "Can't $call(". join(q{, }, @args) . "): $!" ;
0b09a93a 584
585 # TODO - Handle user-defined errors from hash.
586
587 # TODO - Handle default error messages.
588
589}
590
591=head3 new
592
593 my $error = autodie::exception->new(
594 args => \@_,
595 function => "CORE::open",
596 errno => $!,
eb8d423f 597 context => 'scalar',
598 return => undef,
0b09a93a 599 );
600
601
602Creates a new C<autodie::exception> object. Normally called
603directly from an autodying function. The C<function> argument
604is required, its the function we were trying to call that
605generated the exception. The C<args> parameter is optional.
606
607The C<errno> value is optional. In versions of C<autodie::exception>
6081.99 and earlier the code would try to automatically use the
609current value of C<$!>, but this was unreliable and is no longer
610supported.
611
612Atrributes such as package, file, and caller are determined
613automatically, and cannot be specified.
614
615=cut
616
617sub new {
618 my ($class, @args) = @_;
619
620 my $this = {};
621
622 bless($this,$class);
623
624 # I'd love to use EVERY here, but it causes our code to die
625 # because it wants to stringify our objects before they're
626 # initialised, causing everything to explode.
627
628 $this->_init(@args);
629
630 return $this;
631}
632
633sub _init {
634
635 my ($this, %args) = @_;
636
637 # Capturing errno here is not necessarily reliable.
638 my $original_errno = $!;
639
640 our $init_called = 1;
641
642 my $class = ref $this;
643
644 # We're going to walk up our call stack, looking for the
645 # first thing that doesn't look like our exception
646 # code, autodie/Fatal, or some whacky eval.
647
648 my ($package, $file, $line, $sub);
649
650 my $depth = 0;
651
652 while (1) {
653 $depth++;
654
655 ($package, $file, $line, $sub) = CORE::caller($depth);
656
657 # Skip up the call stack until we find something outside
658 # of the Fatal/autodie/eval space.
659
660 next if $package->isa('Fatal');
661 next if $package->isa($class);
662 next if $package->isa(__PACKAGE__);
663 next if $file =~ /^\(eval\s\d+\)$/;
664
665 last;
666
667 }
668
db4e6d09 669 # We now have everything correct, *except* for our subroutine
670 # name. If it's __ANON__ or (eval), then we need to keep on
671 # digging deeper into our stack to find the real name. However we
672 # don't update our other information, since that will be correct
673 # for our current exception.
674
675 my $first_guess_subroutine = $sub;
676
677 while (defined $sub and $sub =~ /^\(eval\)$|::__ANON__$/) {
678 $depth++;
679
680 $sub = (CORE::caller($depth))[3];
681 }
682
683 # If we end up falling out the bottom of our stack, then our
684 # __ANON__ guess is the best we can get. This includes situations
9b657a62 685 # where we were called from the top level of a program.
db4e6d09 686
687 if (not defined $sub) {
688 $sub = $first_guess_subroutine;
689 }
690
0b09a93a 691 $this->{$PACKAGE}{package} = $package;
692 $this->{$PACKAGE}{file} = $file;
693 $this->{$PACKAGE}{line} = $line;
694 $this->{$PACKAGE}{caller} = $sub;
695 $this->{$PACKAGE}{package} = $package;
696
697 $this->{$PACKAGE}{errno} = $args{errno} || 0;
698
eb8d423f 699 $this->{$PACKAGE}{context} = $args{context};
700 $this->{$PACKAGE}{return} = $args{return};
701
0b09a93a 702 $this->{$PACKAGE}{args} = $args{args} || [];
703 $this->{$PACKAGE}{function}= $args{function} or
704 croak("$class->new() called without function arg");
705
706 return $this;
707
708}
709
7101;
711
712__END__
713
714=head1 SEE ALSO
715
716L<autodie>, L<autodie::exception::system>
717
718=head1 LICENSE
719
720Copyright (C)2008 Paul Fenwick
721
722This is free software. You may modify and/or redistribute this
723code under the same terms as Perl 5.10 itself, or, at your option,
724any later version of Perl 5.
725
726=head1 AUTHOR
727
728Paul Fenwick E<lt>pjf@perltraining.com.auE<gt>