NAME
Error::Base - Simple structured errors with full backtrace
VERSION
This document describes Error::Base version v0.1.4
SYNOPSIS
use Error::Base;
Error::Base->crash('Sanity check failed'); # die() with backtrace
my $err = Error::Base->new('Foo'); # construct object first
yourcodehere(...); # ... do other stuff
$err->crash; # as object method
my $err = Error::Base->new(
'Foo error', # odd arg is error text
-quiet => 1, # no backtrace
grink => 'grunt', # store somethings
puppy => 'dog', # your keys, no leading dash
);
$err->crash;
$err->crank; # get cranky: warn() but don't die()
my $err = Error::Base->crank('Me!'); # also a constructor
eval{ Error::Base->crash( 'car', -foo => 'bar' ) };
my $err = $@ if $@; # catch and examine the full object
my $err = Error::Base->new(
-base => 'File handler error:',
_openerr => 'Couldn\t open $file for $op',
);
{
my $file = 'z00bie.xxx'; # uh-oh, variable out of scope for new()
open my $fh, '<', $file
or $err->crash(
-type => $err->{_openerr},
'$file' => $file,
'$op' => 'reading',
); # late interpolation to the rescue
}
DESCRIPTION
J'avais cru plus difficile de mourir. -- Louis XIV
Die early, die often. Make frequent sanity checks and die when a check fails. See neat dumps of the caller stack with each error. Construct a group of error messages in one object or write error text ad hoc. Trap an error object and examine the contents; or let it tell its sad tale and end it.
Error::Base usage can be simple or complex. For quick sanity checks, construct and throw a simple fatal error in one line. At the other extreme, you can override methods in your own error subclasses.
Error::Base is lightweight. It defines no global variables, uses no non-core modules (and few of those), exports no symbols, and is purely object-oriented. I hope you will be able to use it commonly instead of a simple die()
. You are not required to subclass it.
See the Error::Base::Cookbook for examples.
METHODS
new()
my $err = Error::Base->new; # constructor
my $err = Error::Base->new(
'bartender', # lone string first okay
-base => 'Bar error:',
-type => 'last call',
-quiet => 1,
-top => 3,
-prepend => '@! Black Tie Lunch:',
-indent => '@! ',
_beer => 'out of beer', # your private attribute(s)
);
The constructor must be called as a class method; there is no mutator returning a new object based on an old one. You do have some freedom in how you call, though.
Called with an even number of args, they are all considered key/value pairs. Keys with leading dash ('-'
) are reserved for use by Error::Base; keys led by a Perlish sigil (=~ /^[\$\@%]/
) trigger late interpolation; all other keys are free to use as you see fit. Error message text is constructed as a single string.
Called with an odd number of args, the first arg is shifted off and appended to the error message text. This shorthand may be offensive to some; in which case, don't do that. Instead, pass -base
, -type
, or both.
You may stash any arbitrary data inside the returned object (during construction or later) and do whatever you like with it. You might choose to supply additional optional texts for later access.
Stringification is overridden on objects of this class. So, if you attempt to print the object, or perform an operation that causes perl to want to treat it as a string, you will get the printable error message. If you prefer to examine the object internally, access its hash values; or dump it using Data::Dumper, Devel::Comments, or Test::More::explain().
See "PARAMETERS".
crash()
Error::Base->crash('Sanity check failed'); # as class method
$err->crash; # as object method
# all the same args are okay in crash() as in new()
eval{ $err->crash }; # trap...
print STDERR $@ if $@; # ... and examine the object
crash()
and other public methods may be called as class or object methods. If called as a class method, then new()
is called internally. Call new()
first if you want to call crash()
as an object method.
crash()
is a very thin wrapper, easy to subclass. It differs from similar methods in that instead of returning its object, it die()
-s with it. If uncaught, the error will stringify; if caught, the entire object is yours.
crank()
$err->crank( -type => 'Excessive boxes' ) if $box > $max;
This is exactly like crash()
except that it warn()
s instead of die()
-ing. Therefore you may easily recover the object for later use.
cuss()
my $err = Error::Base->cuss('x%@#*!'); # also a constructor
Again, exactly like crash()
or crank()
except that it neither die()
-s nor warn()
s; it only returns the object.
The difference between new()
and the other methods is that new()
returns the constructed object containing only what was passed in as arguments. crash()
, crank()
, and cuss()
perform a full stack backtrace (if not passed -quiet) and format the result for stringified display.
You may find cuss()
useful in testing your subclass or to see how your error will be thrown without the bother of actually catching crash()
.
init()
$err->init(@args);
The calling conventions are exactly the same as for the other public methods.
init()
is called on a newly constructed object, as is conventional. If you call it a second time on an existing object, new @args
will overwrite previous values. Internally, when called on an existing object, crash()
, crank()
, and cuss()
each call init()
. When these are called as class methods, they call new()
, which calls init()
.
Therefore, the chief distinction between calling as class or object method is that if you call new() first then you can separate the definition of your error text from the actual throw.
PARAMETERS
All public methods accept the same arguments, with the same conventions. All parameter names begin with a leading dash ('-'
); please choose other names for your private keys.
If the same parameter is set multiple times, the most recent argument completely overwrites the previous value.
You are cautioned that deleting keys may be unwise.
-base
scalar string
The value of -base
is printed in the first line of the stringified error object after a call to crash()
, crank()
, or cuss()
.
-type
scalar string
This parameter is provided as a way to express a subtype of error. It is appended to -base
.
-pronto
scalar string
$err->crash( 'Pronto!' ); # emits 'Pronto!'
$err->crash(
-pronto => 'Pronto!',
); # same thing
As a convenience, if the number of arguments passed in is odd, then the first arg is shifted off and appended to the error message after -base
and -type
. This is done to simplify writing one-off, one-line sanity checks:
open( my $in_fh, '<', $filename )
or Error::Base->crash("Couldn't open $filename for reading.");
TODO: It is expected that each message argument be a single scalar. If you need to pass a multi-line string then please embed escaped newlines ('\n'
).
-quiet
scalar boolean default: undef
$err->crash( -quiet => 1, ); # no backtrace
By default, you get a full stack backtrace. If you want none, set this parameter. Only error text will be emitted.
-top
scalar unsigned integer default: 2
By default, stack frames internal to Error::Base are not traced. Set this parameter to adjust how many frames to discard.
TODO: A more elegant interface.
-prepend
scalar string default: undef
-indent
scalar string default: first char of -prepend, padded with spaces to length
-prepend_all
scalar string default: undef
The value of -prepend
is prepended to the first line of error text; -indent
to all others. If given, -prepend_all
overrides the other parameters and is prepended to all lines.
This is a highly useful feature that improves readability in the middle of a dense dump. So in future releases, the default may be changed to form -prepend
in some way for you if not defined. If you are certain you want no prepending or indentation, pass the empty string, q{}
.
LATE INTERPOLATION
It is possible to interpolate a variable that is not in scope into error message text. This is triggered by passing the value against a key whose leading character is a Perlish sigil, one of $@%
. Enclose the text (including placeholders) in single quotes. For a detailed explanation, see the Cookbook.
RESULTS
Soon, I'll write accessor methods for all of these. For now, rough it.
-msg
scalar string default: 'Undefined error.'
The error message, expanded, without -prepend
or backtrace. An empty message is not allowed; if none is provided by any means, 'Undefined error.' emits.
-lines
array of strings
The formatted error message, fully expanded, including backtrace.
-frames
array of hashrefs
The raw stack frames used to compose the backtrace.
SUBCLASSING
use base 'Error::Base';
sub init{
my $self = shift;
_munge_my_args(@_);
$self->SUPER::init(@_);
return $self;
};
While useful standing alone, Error::Base is written to be subclassed, if you so desire. Perhaps the most useful method to subclass may be init()
. You might also subclass crash()
, crank()
, or cuss()
if you want to do something first:
use base 'Error::Base';
sub crash{
my $self = _fuss(@_);
$self->a_kiss_before_dying();
die $self;
};
The author hopes that most users will not be driven to subclassing but if you do so, successfully or not, please be so kind as to notify.
SEE ALSO
Many error-related modules are available on CPAN. Some do bizarre things.
Exception::Class, Error, Exception, Carp, Test::Trap.
INSTALLATION
This module is installed using Module::Build.
DIAGNOSTICS
This module emits error messages for you; it is hoped you won't encounter any from within itself. If you do see one of these errors, kindly report to RT so maintainer can take action. Thank you for helping.
All errors internal to this module are prefixed Error::Base internal...
excessive backtrace
-
Attempted to capture too many frames of backtrace. You probably mis-set
-top
, rational values of which are perhaps0..9
. unpaired args:
-
You do not have to pass paired arguments to most public methods. Perhaps you passed an odd number of args to a private method.
bad reftype
-
You attempted to late-interpolate a reference other than to a scalar, array, or hash. Don't pass such references as values to any key with the wrong sigil.
no $self
-
Called a method without class or object. Did you call as function?
stringifing unthrown object
-
An object of this class will stringify to its printable error message (including backtrace if any) when thrown. There is nothing to see (yet) if you try to print an object that has been constructed but not (yet) thrown. This error is not fatal; it is returned as the stringification.
in _late eval:
-
Attempted to late-interpolate badly. Check your code. The interpolation failed so you cannot expect to see the correct error message text. On the offchance that you would like to see the stack backtrace anyway, this error is not fatal.
CONFIGURATION AND ENVIRONMENT
Error::Base requires no configuration files or environment variables.
DEPENDENCIES
There are no non-core dependencies.
version 0.94 # Perl extension for Version Objects
overload # Overload Perl operations
Scalar::Util # General-utility scalar subroutines
This module should work with any version of perl 5.8.8 and up.
INCOMPATIBILITIES
None known.
BUGS AND LIMITATIONS
This is an early release. Reports and suggestions will be warmly welcomed.
Please report any bugs or feature requests to bug-error-base@rt.cpan.org
, or through the web interface at http://rt.cpan.org.
THANKS
Grateful acknowledgement deserved by AMBRUS for coherent API suggestions. Any failure to grasp them is mine.
AUTHOR
Xiong Changnian <xiong@cpan.org>
LICENSE
Copyright (C) 2011 Xiong Changnian <xiong@cpan.org>
This library and its contents are released under Artistic License 2.0: