1package autodie::hints; 2 3use strict; 4use warnings; 5 6use constant PERL58 => ( $] < 5.009 ); 7 8our $VERSION = '2.23'; # VERSION: Generated by DZP::OurPkg:Version 9 10# ABSTRACT: Provide hints about user subroutines to autodie 11 12=head1 NAME 13 14autodie::hints - Provide hints about user subroutines to autodie 15 16=head1 SYNOPSIS 17 18 package Your::Module; 19 20 our %DOES = ( 'autodie::hints::provider' => 1 ); 21 22 sub AUTODIE_HINTS { 23 return { 24 foo => { scalar => HINTS, list => SOME_HINTS }, 25 bar => { scalar => HINTS, list => MORE_HINTS }, 26 } 27 } 28 29 # Later, in your main program... 30 31 use Your::Module qw(foo bar); 32 use autodie qw(:default foo bar); 33 34 foo(); # succeeds or dies based on scalar hints 35 36 # Alternatively, hints can be set on subroutines we've 37 # imported. 38 39 use autodie::hints; 40 use Some::Module qw(think_positive); 41 42 BEGIN { 43 autodie::hints->set_hints_for( 44 \&think_positive, 45 { 46 fail => sub { $_[0] <= 0 } 47 } 48 ) 49 } 50 use autodie qw(think_positive); 51 52 think_positive(...); # Returns positive or dies. 53 54 55=head1 DESCRIPTION 56 57=head2 Introduction 58 59The L<autodie> pragma is very smart when it comes to working with 60Perl's built-in functions. The behaviour for these functions are 61fixed, and C<autodie> knows exactly how they try to signal failure. 62 63But what about user-defined subroutines from modules? If you use 64C<autodie> on a user-defined subroutine then it assumes the following 65behaviour to demonstrate failure: 66 67=over 68 69=item * 70 71A false value, in scalar context 72 73=item * 74 75An empty list, in list context 76 77=item * 78 79A list containing a single undef, in list context 80 81=back 82 83All other return values (including the list of the single zero, and the 84list containing a single empty string) are considered successful. However, 85real-world code isn't always that easy. Perhaps the code you're working 86with returns a string containing the word "FAIL" upon failure, or a 87two element list containing C<(undef, "human error message")>. To make 88autodie work with these sorts of subroutines, we have 89the I<hinting interface>. 90 91The hinting interface allows I<hints> to be provided to C<autodie> 92on how it should detect failure from user-defined subroutines. While 93these I<can> be provided by the end-user of C<autodie>, they are ideally 94written into the module itself, or into a helper module or sub-class 95of C<autodie> itself. 96 97=head2 What are hints? 98 99A I<hint> is a subroutine or value that is checked against the 100return value of an autodying subroutine. If the match returns true, 101C<autodie> considers the subroutine to have failed. 102 103If the hint provided is a subroutine, then C<autodie> will pass 104the complete return value to that subroutine. If the hint is 105any other value, then C<autodie> will smart-match against the 106value provided. In Perl 5.8.x there is no smart-match operator, and as such 107only subroutine hints are supported in these versions. 108 109Hints can be provided for both scalar and list contexts. Note 110that an autodying subroutine will never see a void context, as 111C<autodie> always needs to capture the return value for examination. 112Autodying subroutines called in void context act as if they're called 113in a scalar context, but their return value is discarded after it 114has been checked. 115 116=head2 Example hints 117 118Hints may consist of scalars, array references, regular expressions and 119subroutine references. You can specify different hints for how 120failure should be identified in scalar and list contexts. 121 122These examples apply for use in the C<AUTODIE_HINTS> subroutine and when 123calling C<autodie::hints->set_hints_for()>. 124 125The most common context-specific hints are: 126 127 # Scalar failures always return undef: 128 { scalar => undef } 129 130 # Scalar failures return any false value [default expectation]: 131 { scalar => sub { ! $_[0] } } 132 133 # Scalar failures always return zero explicitly: 134 { scalar => '0' } 135 136 # List failures always return an empty list: 137 { list => [] } 138 139 # List failures return () or (undef) [default expectation]: 140 { list => sub { ! @_ || @_ == 1 && !defined $_[0] } } 141 142 # List failures return () or a single false value: 143 { list => sub { ! @_ || @_ == 1 && !$_[0] } } 144 145 # List failures return (undef, "some string") 146 { list => sub { @_ == 2 && !defined $_[0] } } 147 148 # Unsuccessful foo() returns 'FAIL' or '_FAIL' in scalar context, 149 # returns (-1) in list context... 150 autodie::hints->set_hints_for( 151 \&foo, 152 { 153 scalar => qr/^ _? FAIL $/xms, 154 list => [-1], 155 } 156 ); 157 158 # Unsuccessful foo() returns 0 in all contexts... 159 autodie::hints->set_hints_for( 160 \&foo, 161 { 162 scalar => 0, 163 list => [0], 164 } 165 ); 166 167This "in all contexts" construction is very common, and can be 168abbreviated, using the 'fail' key. This sets both the C<scalar> 169and C<list> hints to the same value: 170 171 # Unsuccessful foo() returns 0 in all contexts... 172 autodie::hints->set_hints_for( 173 \&foo, 174 { 175 fail => sub { @_ == 1 and defined $_[0] and $_[0] == 0 } 176 } 177 ); 178 179 # Unsuccessful think_positive() returns negative number on failure... 180 autodie::hints->set_hints_for( 181 \&think_positive, 182 { 183 fail => sub { $_[0] < 0 } 184 } 185 ); 186 187 # Unsuccessful my_system() returns non-zero on failure... 188 autodie::hints->set_hints_for( 189 \&my_system, 190 { 191 fail => sub { $_[0] != 0 } 192 } 193 ); 194 195=head1 Manually setting hints from within your program 196 197If you are using a module which returns something special on failure, then 198you can manually create hints for each of the desired subroutines. Once 199the hints are specified, they are available for all files and modules loaded 200thereafter, thus you can move this work into a module and it will still 201work. 202 203 use Some::Module qw(foo bar); 204 use autodie::hints; 205 206 autodie::hints->set_hints_for( 207 \&foo, 208 { 209 scalar => SCALAR_HINT, 210 list => LIST_HINT, 211 } 212 ); 213 autodie::hints->set_hints_for( 214 \&bar, 215 { fail => SOME_HINT, } 216 ); 217 218It is possible to pass either a subroutine reference (recommended) or a fully 219qualified subroutine name as the first argument. This means you can set hints 220on modules that I<might> get loaded: 221 222 use autodie::hints; 223 autodie::hints->set_hints_for( 224 'Some::Module:bar', { fail => SCALAR_HINT, } 225 ); 226 227This technique is most useful when you have a project that uses a 228lot of third-party modules. You can define all your possible hints 229in one-place. This can even be in a sub-class of autodie. For 230example: 231 232 package my::autodie; 233 234 use parent qw(autodie); 235 use autodie::hints; 236 237 autodie::hints->set_hints_for(...); 238 239 1; 240 241You can now C<use my::autodie>, which will work just like the standard 242C<autodie>, but is now aware of any hints that you've set. 243 244=head1 Adding hints to your module 245 246C<autodie> provides a passive interface to allow you to declare hints for 247your module. These hints will be found and used by C<autodie> if it 248is loaded, but otherwise have no effect (or dependencies) without autodie. 249To set these, your module needs to declare that it I<does> the 250C<autodie::hints::provider> role. This can be done by writing your 251own C<DOES> method, using a system such as C<Class::DOES> to handle 252the heavy-lifting for you, or declaring a C<%DOES> package variable 253with a C<autodie::hints::provider> key and a corresponding true value. 254 255Note that checking for a C<%DOES> hash is an C<autodie>-only 256short-cut. Other modules do not use this mechanism for checking 257roles, although you can use the C<Class::DOES> module from the 258CPAN to allow it. 259 260In addition, you must define a C<AUTODIE_HINTS> subroutine that returns 261a hash-reference containing the hints for your subroutines: 262 263 package Your::Module; 264 265 # We can use the Class::DOES from the CPAN to declare adherence 266 # to a role. 267 268 use Class::DOES 'autodie::hints::provider' => 1; 269 270 # Alternatively, we can declare the role in %DOES. Note that 271 # this is an autodie specific optimisation, although Class::DOES 272 # can be used to promote this to a true role declaration. 273 274 our %DOES = ( 'autodie::hints::provider' => 1 ); 275 276 # Finally, we must define the hints themselves. 277 278 sub AUTODIE_HINTS { 279 return { 280 foo => { scalar => HINTS, list => SOME_HINTS }, 281 bar => { scalar => HINTS, list => MORE_HINTS }, 282 baz => { fail => HINTS }, 283 } 284 } 285 286This allows your code to set hints without relying on C<autodie> and 287C<autodie::hints> being loaded, or even installed. In this way your 288code can do the right thing when C<autodie> is installed, but does not 289need to depend upon it to function. 290 291=head1 Insisting on hints 292 293When a user-defined subroutine is wrapped by C<autodie>, it will 294use hints if they are available, and otherwise reverts to the 295I<default behaviour> described in the introduction of this document. 296This can be problematic if we expect a hint to exist, but (for 297whatever reason) it has not been loaded. 298 299We can ask autodie to I<insist> that a hint be used by prefixing 300an exclamation mark to the start of the subroutine name. A lone 301exclamation mark indicates that I<all> subroutines after it must 302have hints declared. 303 304 # foo() and bar() must have their hints defined 305 use autodie qw( !foo !bar baz ); 306 307 # Everything must have hints (recommended). 308 use autodie qw( ! foo bar baz ); 309 310 # bar() and baz() must have their hints defined 311 use autodie qw( foo ! bar baz ); 312 313 # Enable autodie for all of Perl's supported built-ins, 314 # as well as for foo(), bar() and baz(). Everything must 315 # have hints. 316 use autodie qw( ! :all foo bar baz ); 317 318If hints are not available for the specified subroutines, this will cause a 319compile-time error. Insisting on hints for Perl's built-in functions 320(eg, C<open> and C<close>) is always successful. 321 322Insisting on hints is I<strongly> recommended. 323 324=cut 325 326# TODO: implement regular expression hints 327 328use constant UNDEF_ONLY => sub { not defined $_[0] }; 329use constant EMPTY_OR_UNDEF => sub { 330 ! @_ or 331 @_==1 && !defined $_[0] 332}; 333 334use constant EMPTY_ONLY => sub { @_ == 0 }; 335use constant EMPTY_OR_FALSE => sub { 336 ! @_ or 337 @_==1 && !$_[0] 338}; 339 340use constant SINGLE_TRUE => sub { @_ == 1 and not $_[0] }; 341 342use constant DEFAULT_HINTS => { 343 scalar => UNDEF_ONLY, 344 list => EMPTY_OR_UNDEF, 345}; 346 347 348use constant HINTS_PROVIDER => 'autodie::hints::provider'; 349 350use base qw(Exporter); 351 352our $DEBUG = 0; 353 354# Only ( undef ) is a strange but possible situation for very 355# badly written code. It's not supported yet. 356 357my %Hints = ( 358 'File::Copy::copy' => { scalar => SINGLE_TRUE, list => SINGLE_TRUE }, 359 'File::Copy::move' => { scalar => SINGLE_TRUE, list => SINGLE_TRUE }, 360 'File::Copy::cp' => { scalar => SINGLE_TRUE, list => SINGLE_TRUE }, 361 'File::Copy::mv' => { scalar => SINGLE_TRUE, list => SINGLE_TRUE }, 362); 363 364# Start by using Sub::Identify if it exists on this system. 365 366eval { require Sub::Identify; Sub::Identify->import('get_code_info'); }; 367 368# If it doesn't exist, we'll define our own. This code is directly 369# taken from Rafael Garcia's Sub::Identify 0.04, used under the same 370# license as Perl itself. 371 372if ($@) { 373 require B; 374 375 no warnings 'once'; 376 377 *get_code_info = sub ($) { 378 379 my ($coderef) = @_; 380 ref $coderef or return; 381 my $cv = B::svref_2object($coderef); 382 $cv->isa('B::CV') or return; 383 # bail out if GV is undefined 384 $cv->GV->isa('B::SPECIAL') and return; 385 386 return ($cv->GV->STASH->NAME, $cv->GV->NAME); 387 }; 388 389} 390 391sub sub_fullname { 392 return join( '::', get_code_info( $_[1] ) ); 393} 394 395my %Hints_loaded = (); 396 397sub load_hints { 398 my ($class, $sub) = @_; 399 400 my ($package) = ( $sub =~ /(.*)::/ ); 401 402 if (not defined $package) { 403 require Carp; 404 Carp::croak( 405 "Internal error in autodie::hints::load_hints - no package found. 406 "); 407 } 408 409 # Do nothing if we've already tried to load hints for 410 # this package. 411 return if $Hints_loaded{$package}++; 412 413 my $hints_available = 0; 414 415 { 416 no strict 'refs'; ## no critic 417 418 if ($package->can('DOES') and $package->DOES(HINTS_PROVIDER) ) { 419 $hints_available = 1; 420 } 421 elsif ( PERL58 and $package->isa(HINTS_PROVIDER) ) { 422 $hints_available = 1; 423 } 424 elsif ( ${"${package}::DOES"}{HINTS_PROVIDER.""} ) { 425 $hints_available = 1; 426 } 427 } 428 429 return if not $hints_available; 430 431 my %package_hints = %{ $package->AUTODIE_HINTS }; 432 433 foreach my $sub (keys %package_hints) { 434 435 my $hint = $package_hints{$sub}; 436 437 # Ensure we have a package name. 438 $sub = "${package}::$sub" if $sub !~ /::/; 439 440 # TODO - Currently we don't check for conflicts, should we? 441 $Hints{$sub} = $hint; 442 443 $class->normalise_hints(\%Hints, $sub); 444 } 445 446 return; 447 448} 449 450sub normalise_hints { 451 my ($class, $hints, $sub) = @_; 452 453 if ( exists $hints->{$sub}->{fail} ) { 454 455 if ( exists $hints->{$sub}->{scalar} or 456 exists $hints->{$sub}->{list} 457 ) { 458 # TODO: Turn into a proper diagnostic. 459 require Carp; 460 local $Carp::CarpLevel = 1; 461 Carp::croak("fail hints cannot be provided with either scalar or list hints for $sub"); 462 } 463 464 # Set our scalar and list hints. 465 466 $hints->{$sub}->{scalar} = 467 $hints->{$sub}->{list} = delete $hints->{$sub}->{fail}; 468 469 return; 470 471 } 472 473 # Check to make sure all our hints exist. 474 475 foreach my $hint (qw(scalar list)) { 476 if ( not exists $hints->{$sub}->{$hint} ) { 477 # TODO: Turn into a proper diagnostic. 478 require Carp; 479 local $Carp::CarpLevel = 1; 480 Carp::croak("$hint hint missing for $sub"); 481 } 482 } 483 484 return; 485} 486 487sub get_hints_for { 488 my ($class, $sub) = @_; 489 490 my $subname = $class->sub_fullname( $sub ); 491 492 # If we have hints loaded for a sub, then return them. 493 494 if ( exists $Hints{ $subname } ) { 495 return $Hints{ $subname }; 496 } 497 498 # If not, we try to load them... 499 500 $class->load_hints( $subname ); 501 502 # ...and try again! 503 504 if ( exists $Hints{ $subname } ) { 505 return $Hints{ $subname }; 506 } 507 508 # It's the caller's responsibility to use defaults if desired. 509 # This allows on autodie to insist on hints if needed. 510 511 return; 512 513} 514 515sub set_hints_for { 516 my ($class, $sub, $hints) = @_; 517 518 if (ref $sub) { 519 $sub = $class->sub_fullname( $sub ); 520 521 require Carp; 522 523 $sub or Carp::croak("Attempts to set_hints_for unidentifiable subroutine"); 524 } 525 526 if ($DEBUG) { 527 warn "autodie::hints: Setting $sub to hints: $hints\n"; 528 } 529 530 $Hints{ $sub } = $hints; 531 532 $class->normalise_hints(\%Hints, $sub); 533 534 return; 535} 536 5371; 538 539__END__ 540 541 542=head1 Diagnostics 543 544=over 4 545 546=item Attempts to set_hints_for unidentifiable subroutine 547 548You've called C<< autodie::hints->set_hints_for() >> using a subroutine 549reference, but that reference could not be resolved back to a 550subroutine name. It may be an anonymous subroutine (which can't 551be made autodying), or may lack a name for other reasons. 552 553If you receive this error with a subroutine that has a real name, 554then you may have found a bug in autodie. See L<autodie/BUGS> 555for how to report this. 556 557=item fail hints cannot be provided with either scalar or list hints for %s 558 559When defining hints, you can either supply both C<list> and 560C<scalar> keywords, I<or> you can provide a single C<fail> keyword. 561You can't mix and match them. 562 563=item %s hint missing for %s 564 565You've provided either a C<scalar> hint without supplying 566a C<list> hint, or vice-versa. You I<must> supply both C<scalar> 567and C<list> hints, I<or> a single C<fail> hint. 568 569=back 570 571=head1 ACKNOWLEDGEMENTS 572 573=over 574 575=item * 576 577Dr Damian Conway for suggesting the hinting interface and providing the 578example usage. 579 580=item * 581 582Jacinta Richardson for translating much of my ideas into this 583documentation. 584 585=back 586 587=head1 AUTHOR 588 589Copyright 2009, Paul Fenwick E<lt>pjf@perltraining.com.auE<gt> 590 591=head1 LICENSE 592 593This module is free software. You may distribute it under the 594same terms as Perl itself. 595 596=head1 SEE ALSO 597 598L<autodie>, L<Class::DOES> 599 600=for Pod::Coverage get_hints_for load_hints normalise_hints sub_fullname 601 602=cut 603