Skip Menu |

This queue is for tickets about the Iterator-Diamond CPAN distribution.

Report information
The Basics
Id: 79486
Status: resolved
Priority: 0/
Queue: Iterator-Diamond

People
Owner: jv [...] cpan.org
Requestors: mhasch-cpanbugs [...] cozap.com
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in: 0.03
Fixed in: 1.00



Subject: [PATCH] does not read from pipes
Johan: Due to an inadequate size check, input from pipes would be skipped. The patch supplied here tests and fixes this. I have also added a couple of other small improvements: $^I should only turn on inline-editing if explicitly enabled; this feature is too dangerous to hide it. An empty argument list should trigger STDIN processing if stdin magic is in effect. It should be documented that inline-editing without backup files is not supported. The -I command line option mentioned in the documentation is actually -i. The unit test failure rt-56053 seems harmless; that particular test should be ignored. Thank you for this module; I consider it very useful. -Martin
And here is the patch. -Martin
Subject: Iterator-Diamond-0.03-MHASCH-01.patch
diff -Nrup Iterator-Diamond-0.03.orig/Changes Iterator-Diamond-0.03/Changes --- Iterator-Diamond-0.03.orig/Changes 2008-08-07 22:36:01.000000000 +0200 +++ Iterator-Diamond-0.03/Changes 2012-09-06 19:25:21.000000000 +0200 @@ -1,5 +1,13 @@ Revision history for Iterator-Diamond +0.03_01 2012-09-06 + Suggestions by Martin Becker (rt-79486): + - read from STDIN if @ARGV is empty + - explicitly enable $^I feature + - read from pipes (inadequate size check hampered this) + - document that suffix must be non-empty + - fix failed test rt-56053 + 0.03 2008-08-07 Fixes. diff -Nrup Iterator-Diamond-0.03.orig/MANIFEST Iterator-Diamond-0.03/MANIFEST --- Iterator-Diamond-0.03.orig/MANIFEST 2008-08-04 22:32:20.000000000 +0200 +++ Iterator-Diamond-0.03/MANIFEST 2012-09-06 17:54:41.000000000 +0200 @@ -8,7 +8,10 @@ t/00-load.t t/01-ref.t t/02-ref.t t/10-stdin.t +t/11-pipe.t +t/12-noargs.t t/20-user.t t/30-edit.t +t/31-i_option.t Makefile.PL META.yml diff -Nrup Iterator-Diamond-0.03.orig/lib/Iterator/Diamond.pm Iterator-Diamond-0.03/lib/Iterator/Diamond.pm --- Iterator-Diamond-0.03.orig/lib/Iterator/Diamond.pm 2008-08-04 22:32:20.000000000 +0200 +++ Iterator-Diamond-0.03/lib/Iterator/Diamond.pm 2012-09-06 18:53:30.000000000 +0200 @@ -13,7 +13,8 @@ Iterator::Diamond - Iterate through the =cut -our $VERSION = '0.02'; +our $VERSION = '0.03_01'; +$VERSION =~ tr/_//d; =head1 SYNOPSIS @@ -136,21 +137,37 @@ unsafe again, just like the built-in C<< Enables in-place editing of files, just as the built-in C<< <> >> operator. -Using the perl command line option C<-I>I<suffix> has the same effect. +Unlike the built-in operator semantics, an empty suffix to discard backup +files is not supported. + +=item B<< use_i_option >> I<boolean> + +If set to true, and if B<edit> is not specified, the perl command line +option C<-i>I<suffix> will be used to enable or disable in-place editing. +By default, perl command line options are ignored. =item B<< files => >> I<aref> Use this list of files instead of @ARGV. +If C<files> are not specified and C<stdin> or C<all> magic is in effect, +an empty @ARGV will be treated as a list containing a single dash C<< - >>. + =back =cut sub new { my ($pkg, %args) = @_; + my $use_i_option = delete $args{use_i_option}; + if ($use_i_option && !exists($args{edit}) && defined $^I) { + $args{edit} = $^I; + } my $self = $pkg->SUPER::new( files => \@ARGV, %args ); + if ( !exists($args{files}) && !@ARGV && $self->_magic_stdin ) { + @ARGV = qw(-); + } $self->{_current_file} = \$ARGV; - $self->{_edit} = $^I unless defined $self->{_edit}; return $self; } diff -Nrup Iterator-Diamond-0.03.orig/lib/Iterator/Files.pm Iterator-Diamond-0.03/lib/Iterator/Files.pm --- Iterator-Diamond-0.03.orig/lib/Iterator/Files.pm 2008-08-07 22:36:32.000000000 +0200 +++ Iterator-Diamond-0.03/lib/Iterator/Files.pm 2012-09-06 18:53:51.000000000 +0200 @@ -12,7 +12,8 @@ Iterator::Files - Iterate through the co =cut -our $VERSION = '0.03'; +our $VERSION = '0.03_01'; +$VERSION =~ tr/_//d; =head1 SYNOPSIS @@ -135,7 +136,8 @@ unsafe again, just like the built-in C<< Enables in-place editing of files, just as the built-in C<< <> >> operator. -Using the perl command line option C<-I>I<suffix> has the same effect. +Unlike the built-in operator semantics, an empty suffix to discard backup +files is not supported. =item B<< files => >> I<aref> @@ -161,7 +163,7 @@ sub new { if ( exists $args{edit} ) { $self->{_edit} = delete $args{edit}; croak($pkg."::new: Value for 'edit' option (backup suffix) may not be empty") - if $self->{_edit} eq ''; + if defined($self->{_edit}) && $self->{_edit} eq ''; } if ( exists $args{files} ) { $self->{_files} = delete $args{files}; @@ -229,12 +231,18 @@ sub readline { # called only once and with scalar context. use overload '<>' => \&readline; +sub _magic_stdin { + my $self = shift; + my $magic = $self->{_magic}; + return 'stdin' eq $magic || 'all' eq $magic; +} + sub _advance { my $self = shift; $self->{_init} = 1; - if ( $self->{_edit} && defined($self->{_rewrite_fh}) ) { + if ( defined($self->{_edit}) && defined($self->{_rewrite_fh}) ) { close($self->{_rewrite_fh}) or croak("Error rewriting $self->current_file: $!"); undef $self->{_rewrite_fh}; @@ -259,7 +267,14 @@ sub _advance { or croak("$self->current_file: $!"); } - if ( $self->{_edit} ) { + if ( eof($self->{_current_fh}) ) { + close $self->{_current_fh}; + undef $self->{_current_fh}; + undef ${ $self->{_current_file} }; + CORE::next; + } + + if ( defined $self->{_edit} ) { my $fname = $self->current_file; my $backup = $fname; if ( $self->{_edit} !~ /\*/ ) { @@ -276,7 +291,7 @@ sub _advance { $self->{_reset_fh} = select($self->{_rewrite_fh}); } - return -t $self->{_current_fh} || -s $self->{_current_fh}; + return 1; } } diff -Nrup Iterator-Diamond-0.03.orig/t/01-ref.t Iterator-Diamond-0.03/t/01-ref.t --- Iterator-Diamond-0.03.orig/t/01-ref.t 2008-08-04 22:32:20.000000000 +0200 +++ Iterator-Diamond-0.03/t/01-ref.t 2012-09-06 14:58:39.000000000 +0200 @@ -2,7 +2,7 @@ use strict; use warnings; -use Test::More tests => 21; +use Test::More tests => 20; -d 't' && chdir 't'; @@ -20,8 +20,10 @@ close($f); ok(!defined $ARGV, "\$ARGV not set yet"); ok(@ARGV != 0, "\@ARGV pristine"); -# Initially, eof is false, $ARGV and @ARGV untouched. -ok(eof, "eof at start"); +# There used to be a test of eof here, but the state of eof +# before anything has been read by user code can vary. + +# Initially, $ARGV and @ARGV are untouched. ok(!defined $ARGV, "\$ARGV not set yet"); ok(@ARGV != 0, "\@ARGV pristine"); diff -Nrup Iterator-Diamond-0.03.orig/t/11-pipe.t Iterator-Diamond-0.03/t/11-pipe.t --- Iterator-Diamond-0.03.orig/t/11-pipe.t 1970-01-01 01:00:00.000000000 +0100 +++ Iterator-Diamond-0.03/t/11-pipe.t 2012-09-06 15:54:46.000000000 +0200 @@ -0,0 +1,42 @@ +#! perl + +use strict; +use warnings; +use Test::More; +use File::Spec; +use Iterator::Diamond; + +my @payload = ( + "This comes from the pipe\n", + "Another line from the pipe\n", +); + +my $pipe = undef; +my $pid = eval { open $pipe, '-|' }; +if (!defined $pid) { + plan skip_all => 'fork/pipe not supported here'; +} +elsif ($pid) { + plan tests => 1 + @payload; +} +else { + open STDIN, '<', File::Spec->devnull; + print @payload; + exit; +} + +@ARGV = ('-'); +open STDIN, '<&', $pipe or die "cannot redirect STDIN: $!\n"; + +my $it = Iterator::Diamond->new( magic => "stdin" ); + +my @lines = (); +while ( <$it> ) { + push(@lines, $_); +} + +is(0+@lines, 0+@payload, 'number of lines'); +for my $i ( 0..$#payload ) { + my $j = $i + 1; + is($lines[$i], $payload[$i], "line $j"); +} diff -Nrup Iterator-Diamond-0.03.orig/t/12-noargs.t Iterator-Diamond-0.03/t/12-noargs.t --- Iterator-Diamond-0.03.orig/t/12-noargs.t 1970-01-01 01:00:00.000000000 +0100 +++ Iterator-Diamond-0.03/t/12-noargs.t 2012-09-06 15:54:55.000000000 +0200 @@ -0,0 +1,42 @@ +#! perl + +use strict; +use warnings; +use Test::More; +use File::Spec; +use Iterator::Diamond; + +my @payload = ( + "This comes from the pipe\n", + "Another line from the pipe\n", +); + +my $pipe = undef; +my $pid = eval { open $pipe, '-|' }; +if (!defined $pid) { + plan skip_all => 'fork/pipe not supported here'; +} +elsif ($pid) { + plan tests => 1 + @payload; +} +else { + open STDIN, '<', File::Spec->devnull; + print @payload; + exit; +} + +@ARGV = (); +open STDIN, '<&', $pipe or die "cannot redirect STDIN: $!\n"; + +my $it = Iterator::Diamond->new( magic => "stdin" ); + +my @lines = (); +while ( <$it> ) { + push(@lines, $_); +} + +is(0+@lines, 0+@payload, 'number of lines'); +for my $i ( 0..$#payload ) { + my $j = $i + 1; + is($lines[$i], $payload[$i], "line $j"); +} diff -Nrup Iterator-Diamond-0.03.orig/t/31-i_option.t Iterator-Diamond-0.03/t/31-i_option.t --- Iterator-Diamond-0.03.orig/t/31-i_option.t 1970-01-01 01:00:00.000000000 +0100 +++ Iterator-Diamond-0.03/t/31-i_option.t 2012-09-06 17:52:51.000000000 +0200 @@ -0,0 +1,60 @@ +#! perl + +use strict; +use warnings; +use Test::More tests => 9; +use File::Spec; +use Iterator::Diamond; + +-d 't' && chdir 't'; + +my $id = "31-i_option"; + +unlink( "$id.tmp", "$id.tmp~" ); + +open(my $f, '>', "$id.tmp") + or die("$id.tmp: $!\n"); +print { $f } "Hello, World1!\n"; +print { $f } "Hello, World2!\n"; +print { $f } "Hello, World3!\n"; +ok(close($f), "creating $id.tmp"); + +@ARGV = ( "$id.tmp" ); +$^I = '~'; +my $it = Iterator::Diamond->new( use_i_option => 1 ); +my @lines = (); +while ( <$it> ) { + s/ll/xx/g; + print; +} + +@ARGV = ( "$id.tmp" ); +$it = Iterator::Diamond->new; +@lines = (); +while ( <$it> ) { + push(@lines, $_); +} + +for my $j ( 1 .. 3 ) { + is(shift(@lines), "Hexxo, World$j!\n", "line$j"); +} + +@ARGV = ( "$id.tmp~" ); +$it = Iterator::Diamond->new; +@lines = (); +while ( <$it> ) { + push(@lines, $_); +} + +for my $j ( 1 .. 3 ) { + is(shift(@lines), "Hello, World$j!\n", "line$j"); +} + +@ARGV = ( "$id.tmp" ); +$^I = ''; +my $msg = q{Value for 'edit' option (backup suffix) may not be empty}; +my $r = eval { Iterator::Diamond->new( use_i_option => 1 ) }; +is($r, undef, 'empty suffix rejected'); +like($@, qr/ \Q$msg\E /, 'diagnostics'); + +unlink( "$id.tmp", "$id.tmp~" );
Subject: Re: [rt.cpan.org #79486] [PATCH] does not read from pipes
Date: Thu, 6 Sep 2012 20:49:15 +0200
To: bug-Iterator-Diamond [...] rt.cpan.org
From: Johan Vromans <jvromans [...] squirrel.nl>
[Quoting Martin Becker via RT, on September 6 2012, 13:23, in "[rt.cpan.org #794> Due to an inadequate size check, input from pipes would be Show quoted text
> skipped. The patch supplied here tests and fixes this. > > I have also added a couple of other small improvements:
Thanks for your patch. I'll take a look! -- Johan