r44247 - in /branches/upstream/libtry-tiny-perl: ./ current/ current/lib/ current/lib/Try/ current/t/
ansgar-guest at users.alioth.debian.org
ansgar-guest at users.alioth.debian.org
Fri Sep 18 18:30:42 UTC 2009
Author: ansgar-guest
Date: Fri Sep 18 18:30:27 2009
New Revision: 44247
URL: http://svn.debian.org/wsvn/pkg-perl/?sc=1&rev=44247
Log:
[svn-inject] Installing original source of libtry-tiny-perl
Added:
branches/upstream/libtry-tiny-perl/
branches/upstream/libtry-tiny-perl/current/
branches/upstream/libtry-tiny-perl/current/Changes
branches/upstream/libtry-tiny-perl/current/MANIFEST
branches/upstream/libtry-tiny-perl/current/MANIFEST.SKIP
branches/upstream/libtry-tiny-perl/current/META.yml
branches/upstream/libtry-tiny-perl/current/Makefile.PL
branches/upstream/libtry-tiny-perl/current/SIGNATURE
branches/upstream/libtry-tiny-perl/current/lib/
branches/upstream/libtry-tiny-perl/current/lib/Try/
branches/upstream/libtry-tiny-perl/current/lib/Try/Tiny.pm
branches/upstream/libtry-tiny-perl/current/t/
branches/upstream/libtry-tiny-perl/current/t/basic.t
branches/upstream/libtry-tiny-perl/current/t/when.t
Added: branches/upstream/libtry-tiny-perl/current/Changes
URL: http://svn.debian.org/wsvn/pkg-perl/branches/upstream/libtry-tiny-perl/current/Changes?rev=44247&op=file
==============================================================================
--- branches/upstream/libtry-tiny-perl/current/Changes (added)
+++ branches/upstream/libtry-tiny-perl/current/Changes Fri Sep 18 18:30:27 2009
@@ -1,0 +1,8 @@
+0.02
+ - Doc fixes from chromatic
+ - Various minor fixes from Adam Kennedy
+ - Additional documentation and code clarifications
+ - 5.005_04 compatibility
+
+0.01
+ - Initial release
Added: branches/upstream/libtry-tiny-perl/current/MANIFEST
URL: http://svn.debian.org/wsvn/pkg-perl/branches/upstream/libtry-tiny-perl/current/MANIFEST?rev=44247&op=file
==============================================================================
--- branches/upstream/libtry-tiny-perl/current/MANIFEST (added)
+++ branches/upstream/libtry-tiny-perl/current/MANIFEST Fri Sep 18 18:30:27 2009
@@ -1,0 +1,9 @@
+Changes
+lib/Try/Tiny.pm
+Makefile.PL
+MANIFEST This list of files
+MANIFEST.SKIP
+t/basic.t
+t/when.t
+META.yml Module meta-data (added by MakeMaker)
+SIGNATURE Public-key signature (added by MakeMaker)
Added: branches/upstream/libtry-tiny-perl/current/MANIFEST.SKIP
URL: http://svn.debian.org/wsvn/pkg-perl/branches/upstream/libtry-tiny-perl/current/MANIFEST.SKIP?rev=44247&op=file
==============================================================================
--- branches/upstream/libtry-tiny-perl/current/MANIFEST.SKIP (added)
+++ branches/upstream/libtry-tiny-perl/current/MANIFEST.SKIP Fri Sep 18 18:30:27 2009
@@ -1,0 +1,46 @@
+# Avoid version control files.
+\bRCS\b
+\bCVS\b
+\bSCCS\b
+,v$
+\B\.svn\b
+\B\.git\b
+\b_darcs\b
+
+# Avoid Makemaker generated and utility files.
+\bMANIFEST\.bak
+\bMakefile$
+\bblib/
+\bMakeMaker-\d
+\bpm_to_blib\.ts$
+\bpm_to_blib$
+\bblibdirs\.ts$ # 6.18 through 6.25 generated this
+
+# Avoid Module::Build generated and utility files.
+\bBuild$
+\b_build/
+
+# Avoid temp and backup files.
+~$
+\.old$
+\#$
+\b\.#
+\.bak$
+
+# Avoid Devel::Cover files.
+\bcover_db\b
+
+### DEFAULT MANIFEST.SKIP ENDS HERE ####
+
+\.DS_Store$
+\.sw.$
+(\w+-)*(\w+)-\d\.\d+(?:\.tar\.gz)?$
+
+\.t\.log$
+
+\.prove$
+
+# XS shit
+\.(?:bs|c|o)$
+
+\.gitignore$
Added: branches/upstream/libtry-tiny-perl/current/META.yml
URL: http://svn.debian.org/wsvn/pkg-perl/branches/upstream/libtry-tiny-perl/current/META.yml?rev=44247&op=file
==============================================================================
--- branches/upstream/libtry-tiny-perl/current/META.yml (added)
+++ branches/upstream/libtry-tiny-perl/current/META.yml Fri Sep 18 18:30:27 2009
@@ -1,0 +1,13 @@
+--- #YAML:1.0
+name: Try-Tiny
+version: 0.02
+abstract: ~
+license: ~
+author: ~
+generated_by: ExtUtils::MakeMaker version 6.42
+distribution_type: module
+requires:
+ Test::More: 0
+meta-spec:
+ url: http://module-build.sourceforge.net/META-spec-v1.3.html
+ version: 1.3
Added: branches/upstream/libtry-tiny-perl/current/Makefile.PL
URL: http://svn.debian.org/wsvn/pkg-perl/branches/upstream/libtry-tiny-perl/current/Makefile.PL?rev=44247&op=file
==============================================================================
--- branches/upstream/libtry-tiny-perl/current/Makefile.PL (added)
+++ branches/upstream/libtry-tiny-perl/current/Makefile.PL Fri Sep 18 18:30:27 2009
@@ -1,0 +1,16 @@
+use strict;
+
+use ExtUtils::MakeMaker;
+
+require 5.005_04;
+
+WriteMakefile(
+ NAME => 'Try::Tiny',
+ VERSION_FROM => 'lib/Try/Tiny.pm',
+ INSTALLDIRS => 'site',
+ SIGN => 1,
+ PL_FILES => { },
+ PREREQ_PM => {
+ 'Test::More' => 0,
+ },
+);
Added: branches/upstream/libtry-tiny-perl/current/SIGNATURE
URL: http://svn.debian.org/wsvn/pkg-perl/branches/upstream/libtry-tiny-perl/current/SIGNATURE?rev=44247&op=file
==============================================================================
--- branches/upstream/libtry-tiny-perl/current/SIGNATURE (added)
+++ branches/upstream/libtry-tiny-perl/current/SIGNATURE Fri Sep 18 18:30:27 2009
@@ -1,0 +1,31 @@
+This file contains message digests of all files listed in MANIFEST,
+signed via the Module::Signature module, version 0.55.
+
+To verify the content in this distribution, first make sure you have
+Module::Signature installed, then type:
+
+ % cpansign -v
+
+It will check each file's integrity, as well as the signature's
+validity. If "==> Signature verified OK! <==" is not displayed,
+the distribution may already have been compromised, and you should
+not run its Makefile.PL or Build.PL.
+
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA1
+
+SHA1 d150077b59fe9b327023d1b32e746c8fff661983 Changes
+SHA1 0f7f01d0d9d133529eccfe396cf4c71a37a197ad MANIFEST
+SHA1 606bd6424682249397d63caf905f651178a4d6cc MANIFEST.SKIP
+SHA1 85e16f502eb5ec72cccd91a8e25fdaf4fe88a3e1 META.yml
+SHA1 6adc37b24473f070c318abfe77a8531fbf1eefca Makefile.PL
+SHA1 10edc1903fdbc5a81a28b05a5a33ce3da9bc11bb lib/Try/Tiny.pm
+SHA1 85cdb50e91e46c74bdff5a3c147655e060190c76 t/basic.t
+SHA1 c75ffed79f4936105b81aa82443b0a0a87c78873 t/when.t
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.4.7 (Darwin)
+
+iD8DBQFKnq77VCwRwOvSdBgRAnU4AJ9TFIkNbNVAWKADeeH2E5Ug4lyC7gCfeoZu
+Bh881ePwvmPrrFSNPhgVlhM=
+=vbpJ
+-----END PGP SIGNATURE-----
Added: branches/upstream/libtry-tiny-perl/current/lib/Try/Tiny.pm
URL: http://svn.debian.org/wsvn/pkg-perl/branches/upstream/libtry-tiny-perl/current/lib/Try/Tiny.pm?rev=44247&op=file
==============================================================================
--- branches/upstream/libtry-tiny-perl/current/lib/Try/Tiny.pm (added)
+++ branches/upstream/libtry-tiny-perl/current/lib/Try/Tiny.pm Fri Sep 18 18:30:27 2009
@@ -1,0 +1,339 @@
+package Try::Tiny;
+
+use strict;
+#use warnings;
+
+use vars qw(@EXPORT @EXPORT_OK $VERSION @ISA);
+
+BEGIN {
+ require Exporter;
+ @ISA = qw(Exporter);
+}
+
+$VERSION = "0.02";
+
+$VERSION = eval $VERSION;
+
+ at EXPORT = @EXPORT_OK = qw(try catch);
+
+sub try (&;$) {
+ my ( $try, $catch ) = @_;
+
+ # we need to save this here, the eval block will be in scalar context due
+ # to $failed
+ my $wantarray = wantarray;
+
+ my ( @ret, $error, $failed );
+
+ # FIXME consider using local $SIG{__DIE__} to accumilate all errors. It's
+ # not perfect, but we could provide a list of additional errors for
+ # $catch->();
+
+ {
+ # localize $@ to prevent clobbering of previous value by a successful
+ # eval.
+ local $@;
+
+ # failed will be true if the eval dies, because 1 will not be returned
+ # from the eval body
+ $failed = not eval {
+
+ # evaluate the try block in the correct context
+ if ( $wantarray ) {
+ @ret = $try->();
+ } elsif ( defined $wantarray ) {
+ $ret[0] = $try->();
+ } else {
+ $try->();
+ };
+
+ return 1; # properly set $fail to false
+ };
+
+ # copy $@ to $error, when we leave this scope local $@ will revert $@
+ # back to its previous value
+ $error = $@;
+ }
+
+ # at this point $failed contains a true value if the eval died even if some
+ # destructor overwrite $@ as the eval was unwinding.
+ if ( $failed ) {
+ # if we got an error, invoke the catch block.
+ if ( $catch ) {
+ # This works like given($error), but is backwards compatible and
+ # sets $_ in the dynamic scope for the body of C<$catch>
+ for ($error) {
+ return $catch->($error);
+ }
+
+ # in case when() was used without an explicit return, the C<for>
+ # loop will be aborted and there's no useful return value
+ }
+
+ return;
+ } else {
+ # no failure, $@ is back to what it was, everything is fine
+ return $wantarray ? @ret : $ret[0];
+ }
+}
+
+sub catch (&) {
+ return $_[0];
+}
+
+
+__PACKAGE__
+
+__END__
+
+=pod
+
+=head1 NAME
+
+Try::Tiny - minimal try/catch with proper localization of $@
+
+=head1 SYNOPSIS
+
+ # handle errors with a catch handler
+ try {
+ die "foo";
+ } catch {
+ warn "caught error: $_";
+ };
+
+ # just silence errors
+ try {
+ die "foo";
+ };
+
+=head1 DESCRIPTION
+
+This module provides bare bones C<try>/C<catch> statements that are designed to
+minimize common mistakes with eval blocks, and NOTHING else.
+
+This is unlike L<TryCatch> which provides a nice syntax and avoids adding
+another call stack layer, and supports calling C<return> from the try block to
+return from the parent subroutine. These extra features come at a cost of a few
+dependencies, namely L<Devel::Declare> and L<Scope::Upper> which are
+occasionally problematic, and the additional catch filtering uses L<Moose>
+type constraints which may not be desirable either.
+
+The main focus of this module is to provide simple and reliable error handling
+for those having a hard time installing L<TryCatch>, but who still want to
+write correct C<eval> blocks without 5 lines of boilerplate each time.
+
+It's designed to work as correctly as possible in light of the various
+pathological edge cases (see L<BACKGROUND>) and to be compatible with any style
+of error values (simple strings, references, objects, overloaded objects, etc).
+
+=head1 EXPORTS
+
+All functions are exported by default using L<Exporter>.
+
+In the future L<Sub::Exporter> may be used to allow the keywords to be renamed,
+but this technically does not satisfy Adam Kennedy's definition of "Tiny".
+
+=over 4
+
+=item try (&;$)
+
+Takes one mandatory try subroutine and one optional catch subroutine.
+
+The mandatory subroutine is evaluated in the context of an C<eval> block.
+
+If no error occurred the value from the first block is returned, preserving
+list/scalar context.
+
+If there was an error and the second subroutine was given it will be invoked
+with the error in C<$_> (localized) and as that block's first and only
+argument.
+
+Note that the error may be false, but if that happens the C<catch> block will
+still be invoked..
+
+=item catch (&)
+
+Intended to be used in the second argument position of C<try>.
+
+Just returns the subroutine it was given.
+
+ catch { ... }
+
+is the same as
+
+ sub { ... }
+
+=back
+
+=head1 BACKGROUND
+
+There are a number of issues with C<eval>.
+
+=head2 Clobbering $@
+
+When you run an eval block and it succeeds, C<$@> will be cleared, potentially
+clobbering an error that is currently being caught.
+
+This causes action at a distance, clearing previous errors your caller may have
+not yet handled.
+
+C<$@> must be properly localized before invoking C<eval> in order to avoid this
+issue.
+
+=head2 Localizing $@ silently masks errors
+
+Inside an eval block C<die> behaves sort of like:
+
+ sub die {
+ $@_ = $_[0];
+ return_undef_from_eval();
+ }
+
+This means that if you were polite and localized C<$@> you can't die in that
+scope, or your error will be discarded (printing "Something's wrong" instead).
+
+The workaround is very ugly:
+
+ my $error = do {
+ local $@;
+ eval { ... };
+ $@;
+ };
+
+ ...
+ die $error;
+
+=head2 $@ might not be a true value
+
+This code is wrong:
+
+ if ( $@ ) {
+ ...
+ }
+
+because due to the previous caveats it may have been unset.
+
+C<$@> could also an overloaded error object that evaluates to false, but that's
+asking for trouble anyway.
+
+The classic failure mode is:
+
+ sub Object::DESTROY {
+ eval { ... }
+ }
+
+ eval {
+ my $obj = Object->new;
+
+ die "foo";
+ };
+
+ if ( $@ ) {
+
+ }
+
+In this case since C<Object::DESTROY> is not localizing C<$@> but still uses
+C<eval> it will set C<$@> to C<"">.
+
+The destructor is called when the stack is unwound, after C<die> sets C<$@> to
+C<"foo at Foo.pm line 42\n">, so by the time C<if ( $@ )> is evaluated it has
+been cleared by C<eval> in the destructor.
+
+The workaround for this is even uglier than the previous ones. Even though we
+can't save the value of C<$@> from code that doesn't localize, we can at least
+be sure the eval was aborted due to an error:
+
+ my $failed = not eval {
+ ...
+
+ return 1;
+ };
+
+This is because an C<eval> that caught a C<die> will always return a false
+value.
+
+=head1 SHINY SYNTAX
+
+Using Perl 5.10 you can use L<perlsyn/"Switch statements">.
+
+The C<catch> block is invoked in a topicalizer context (like a C<given> block),
+but note that you can't return a useful value from C<catch> using the C<when>
+blocks without an explicit C<return>.
+
+This is somewhat similar to Perl 6's C<CATCH> blocks. You can use it to
+concisely match errors:
+
+ try {
+ require Foo;
+ } catch {
+ when (/^Can't locate .*?\.pm in \@INC/) { } # ignore
+ default { die $_ }
+ };
+
+=head1 CAVEATS
+
+=over 4
+
+=item *
+
+C<try> introduces another caller stack frame. L<Sub::Uplevel> is not used. L<Carp>
+will report this when using full stack traces. This lack of magic is considered
+a feature.
+
+=item *
+
+The value of C<$_> in the C<catch> block is not guaranteed to be preserved,
+there is no safe way to ensure this if C<eval> is used unhygenically in
+destructors. It's only guaranteeed that the C<catch> will be called.
+
+=back
+
+=head1 SEE ALSO
+
+=over 4
+
+=item L<TryCatch>
+
+Much more feature complete, more convenient semantics, but at the cost of
+implementation complexity.
+
+=item L<autodie>
+
+Automatic error throwing for builtin functions and more. Also designed to
+work well with C<given>/C<when>.
+
+=item L<Throwable>
+
+A lightweight role for rolling your own exception classes.
+
+=item L<Error>
+
+Exception object implementation with a C<try> statement. Does not localize
+C<$@>.
+
+=item L<Exception::Class::TryCatch>
+
+Provides a C<catch> statement, but properly calling C<eval> is your
+responsibility.
+
+The C<try> keyword pushes C<$@> onto an error stack, avoiding some of the
+issues with C<$@> but you still need to localize to prevent clobbering.
+
+=back
+
+=head1 VERSION CONTROL
+
+L<http://github.com/nothingmuch/try-tiny/>
+
+=head1 AUTHOR
+
+Yuval Kogman E<lt>nothingmuch at woobling.orgE<gt>
+
+=head1 COPYRIGHT
+
+ Copyright (c) 2009 Yuval Kogman. All rights reserved.
+ This program is free software; you can redistribute
+ it and/or modify it under the terms of the MIT license.
+
+=cut
+
Added: branches/upstream/libtry-tiny-perl/current/t/basic.t
URL: http://svn.debian.org/wsvn/pkg-perl/branches/upstream/libtry-tiny-perl/current/t/basic.t?rev=44247&op=file
==============================================================================
--- branches/upstream/libtry-tiny-perl/current/t/basic.t (added)
+++ branches/upstream/libtry-tiny-perl/current/t/basic.t Fri Sep 18 18:30:27 2009
@@ -1,0 +1,99 @@
+#!/usr/bin/perl
+
+use strict;
+#use warnings;
+
+use Test::More tests => 15;
+
+BEGIN { use_ok 'Try::Tiny' };
+
+sub _eval {
+ local $@;
+ local $Test::Builder::Level = $Test::Builder::Level + 2;
+ return ( scalar(eval { $_[0]->(); 1 }), $@ );
+}
+
+
+sub lives_ok (&$) {
+ my ( $code, $desc ) = @_;
+ local $Test::Builder::Level = $Test::Builder::Level + 1;
+
+ my ( $ok, $error ) = _eval($code);
+
+ ok($ok, $desc );
+
+ diag "error: $@" unless $ok;
+}
+
+sub throws_ok (&$$) {
+ my ( $code, $regex, $desc ) = @_;
+ local $Test::Builder::Level = $Test::Builder::Level + 1;
+
+ my ( $ok, $error ) = _eval($code);
+
+ if ( $ok ) {
+ fail($desc);
+ } else {
+ like($error || '', $regex, $desc );
+ }
+}
+
+
+lives_ok {
+ try {
+ die "foo";
+ };
+} "basic try";
+
+throws_ok {
+ try {
+ die "foo";
+ } catch { die $_ };
+} qr/foo/, "rethrow";
+
+
+{
+ local $@ = "magic";
+ is( try { 42 }, 42, "try block evaluated" );
+ is( $@, "magic", '$@ untouched' );
+}
+
+{
+ local $@ = "magic";
+ is( try { die "foo" }, undef, "try block died" );
+ is( $@, "magic", '$@ untouched' );
+}
+
+{
+ local $@ = "magic";
+ like( (try { die "foo" } catch { $_ }), qr/foo/, "catch block evaluated" );
+ is( $@, "magic", '$@ untouched' );
+}
+
+is( scalar(try { "foo", "bar", "gorch" }), "gorch", "scalar context" );
+is_deeply( [ try {qw(foo bar gorch)} ], [qw(foo bar gorch)], "list context" );
+
+
+
+sub Evil::DESTROY {
+ eval { "oh noes" };
+}
+
+sub Evil::new { bless { }, $_[0] }
+
+{
+ local $@ = "magic";
+ local $_ = "other magic";
+
+ try {
+ my $object = Evil->new;
+ die "foo";
+ } catch {
+ pass("catch invoked");
+ local $TODO = "i don't think we can ever make this work sanely, maybe with SIG{__DIE__}";
+ like($_, qr/foo/);
+ };
+
+ is( $@, "magic", '$@ untouched' );
+ is( $_, "other magic", '$_ untouched' );
+}
Added: branches/upstream/libtry-tiny-perl/current/t/when.t
URL: http://svn.debian.org/wsvn/pkg-perl/branches/upstream/libtry-tiny-perl/current/t/when.t?rev=44247&op=file
==============================================================================
--- branches/upstream/libtry-tiny-perl/current/t/when.t (added)
+++ branches/upstream/libtry-tiny-perl/current/t/when.t Fri Sep 18 18:30:27 2009
@@ -1,0 +1,37 @@
+#!/usr/bin/perl
+
+use strict;
+#use warnings;
+
+use Test::More;
+
+BEGIN {
+ plan skip_all => "Perl 5.10 required" unless eval { require 5.010; 1 };
+ plan tests => 6;
+}
+
+
+BEGIN { use_ok 'Try::Tiny' }
+
+use 5.010;
+
+my ( $foo, $bar, $other );
+
+$_ = "magic";
+
+try {
+ die "foo";
+} catch {
+
+ like( $_, qr/foo/ );
+
+ when (/bar/) { $bar++ };
+ when (/foo/) { $foo++ };
+ default { $other++ };
+};
+
+is( $_, "magic", '$_ not clobbered' );
+
+ok( !$bar, "bar didn't match" );
+ok( $foo, "foo matched" );
+ok( !$other, "fallback didn't match" );
More information about the Pkg-perl-cvs-commits
mailing list