Hello community, here is the log from the commit of package perl-Text-CSV_XS for openSUSE:Factory checked in at 2014-02-24 14:13:01 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/perl-Text-CSV_XS (Old) and /work/SRC/openSUSE:Factory/.perl-Text-CSV_XS.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "perl-Text-CSV_XS" Changes: -------- --- /work/SRC/openSUSE:Factory/perl-Text-CSV_XS/perl-Text-CSV_XS.changes 2013-11-26 19:33:14.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.perl-Text-CSV_XS.new/perl-Text-CSV_XS.changes 2014-02-24 14:13:03.000000000 +0100 @@ -1,0 +2,12 @@ +Mon Feb 24 06:08:10 UTC 2014 - [email protected] + +- updated to 1.04 + * get_columnd () with no argument now returns the empty list + instead of undef when no columns defined + * fragments (rcf7111) now also support AoH (was AoA only) + * Error code conflict for fragments resolved to 2013 + * New function "csv" (not a method) + * Update copyright to 2014 + * Implement RCF7111 + +------------------------------------------------------------------- Old: ---- Text-CSV_XS-1.02.tgz New: ---- Text-CSV_XS-1.04.tgz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ perl-Text-CSV_XS.spec ++++++ --- /var/tmp/diff_new_pack.A9Z9A8/_old 2014-02-24 14:13:03.000000000 +0100 +++ /var/tmp/diff_new_pack.A9Z9A8/_new 2014-02-24 14:13:03.000000000 +0100 @@ -1,7 +1,7 @@ # # spec file for package perl-Text-CSV_XS # -# Copyright (c) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,7 +17,7 @@ Name: perl-Text-CSV_XS -Version: 1.02 +Version: 1.04 Release: 0 %define cpan_name Text-CSV_XS Summary: comma-separated values manipulation routines @@ -28,8 +28,7 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildRequires: perl BuildRequires: perl-macros -#BuildRequires: perl(Text::CSV_XS) -Recommends: perl(Encode) >= 2.55 +Recommends: perl(Encode) >= 2.57 %{perl_requires} %description ++++++ Text-CSV_XS-1.02.tgz -> Text-CSV_XS-1.04.tgz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Text-CSV_XS-1.02/CSV_XS.pm new/Text-CSV_XS-1.04/CSV_XS.pm --- old/Text-CSV_XS-1.02/CSV_XS.pm 2013-09-25 17:48:31.000000000 +0200 +++ new/Text-CSV_XS-1.04/CSV_XS.pm 2014-02-06 07:37:44.000000000 +0100 @@ -1,6 +1,6 @@ package Text::CSV_XS; -# Copyright (c) 2007-2013 H.Merijn Brand. All rights reserved. +# Copyright (c) 2007-2014 H.Merijn Brand. All rights reserved. # Copyright (c) 1998-2001 Jochen Wiedmann. All rights reserved. # Copyright (c) 1997 Alan Citterman. All rights reserved. # @@ -23,12 +23,14 @@ use strict; use warnings; +require Exporter; use DynaLoader (); use Carp; -use vars qw( $VERSION @ISA ); -$VERSION = "1.02"; -@ISA = qw( DynaLoader ); +use vars qw( $VERSION @ISA @EXPORT_OK ); +$VERSION = "1.04"; +@ISA = qw( DynaLoader Exporter ); +@EXPORT_OK = qw( csv ); bootstrap Text::CSV_XS $VERSION; sub PV { 0 } @@ -377,6 +379,25 @@ return $self->{_EOF}; } # status +sub types +{ + my $self = shift; + if (@_) { + if (my $types = shift) { + $self->{_types} = join "", map { chr $_ } @{$types}; + $self->{types} = $types; + } + else { + delete $self->{types}; + delete $self->{_types}; + undef; + } + } + else { + $self->{types}; + } + } # types + # erro_diag # # If (and only if) an error occurred, this function returns a code that @@ -556,7 +577,7 @@ { my ($self, @keys) = @_; @keys or - return defined $self->{_COLUMN_NAMES} ? @{$self->{_COLUMN_NAMES}} : undef; + return defined $self->{_COLUMN_NAMES} ? @{$self->{_COLUMN_NAMES}} : (); @keys == 1 && ! defined $keys[0] and return $self->{_COLUMN_NAMES} = undef; @@ -625,24 +646,178 @@ $self->print ($io, [ map { $hr->{$_} } $self->column_names ]); } # print_hr -sub types +sub fragment { - my $self = shift; - if (@_) { - if (my $types = shift) { - $self->{_types} = join "", map { chr $_ } @{$types}; - $self->{types} = $types; + my ($self, $io, $spec) = @_; + + my $qd = qr{\s* [0-9]+ \s* }x; + my $qr = qr{$qd (?: - (?: $qd | \s* \* \s* ))?}x; + my $qc = qr{$qr (?: ; $qr)*}x; + defined $spec && $spec =~ m{^ \s* + \x23 ? \s* # optional leading # + ( row | col | cell ) \s* = + ( $qc # for row and col + | $qd , $qd (?: - $qd , $qd)? # for cell + ) \s* $}xi or croak ($self->SetDiag (2013)); + my ($type, $range) = (lc $1, $2); + + my @h = $self->column_names (); + + my @c; + if ($type eq "cell") { + my ($tlr, $tlc, $brr, $brc) = ($range =~ m{ + ^ \s* + ([0-9]+) \s* , \s* ([0-9]+) + \s* (?: - \s* + ([0-9]+) \s* , \s* ([0-9]+) + )? + \s* $}x) or croak ($self->SetDiag (2013)); + defined $brr or ($brr, $brc) = ($tlr, $tlc); + $tlr <= 0 || $tlc <= 0 || $brr <= 0 || $brc <= 0 || + $brr < $tlr || $brc < $tlc and croak ($self->SetDiag (2013)); + $_-- for $tlc, $brc; + my $r = 0; + while (my $row = $self->getline ($io)) { + ++$r < $tlr and next; + push @c, [ @{$row}[$tlc..$brc] ]; + if (@h) { + my %h; @h{@h} = @{$c[-1]}; + $c[-1] = \%h; + } + $r >= $brr and last; + } + return \@c; + } + + # row or col + my @r; + my $eod = 0; + for (split m/\s*;\s*/ => $range) { + my ($from, $to) = m/^\s* ([0-9]+) (?: \s* - \s* ([0-9]+ | \* ))? \s* $/x + or croak ($self->SetDiag (2013)); + $to ||= $from; + $to eq "*" and ($to, $eod) = ($from, 1); + $from <= 0 || $to <= 0 || $to < $from and croak ($self->SetDiag (2013)); + $r[$_] = 1 for $from .. $to; + } + + my $r = 0; + $type eq "col" and shift @r; + $_ ||= 0 for @r; + while (my $row = $self->getline ($io)) { + $r++; + if ($type eq "row") { + if (($r > $#r && $eod) || $r[$r]) { + push @c, $row; + if (@h) { + my %h; @h{@h} = @{$c[-1]}; + $c[-1] = \%h; + } + } + next; + } + push @c, [ map { ($_ > $#r && $eod) || $r[$_] ? $row->[$_] : () } 0..$#$row ]; + if (@h) { + my %h; @h{@h} = @{$c[-1]}; + $c[-1] = \%h; + } + } + + return \@c; + } # fragment + +my $csv_usage = q{usage: my $aoa = csv (in => $file);}; + +sub _csv_attr +{ + my %attr = (@_ == 1 && ref $_[0] eq "HASH" ? %{$_[0]} : @_) or die; + + $attr{binary} = 1; + + my $enc = delete $attr{encoding} || ""; + + my $fh; + my $in = delete $attr{in} || delete $attr{file} or croak $csv_usage; + my $out = delete $attr{out} || delete $attr{file}; + if (ref $in eq "ARRAY") { + # we need an out + $out or croak qq{for CSV source, "out" is required}; + defined $attr{eol} or $attr{eol} = "\r\n"; + if (ref $out or "GLOB" eq ref \$out) { + $fh = $out; } else { - delete $self->{types}; - delete $self->{_types}; - undef; + $enc =~ m/^[-\w.]+$/ and $enc = ":encoding($enc)"; + open $fh, ">$enc", $out or croak "$out: $!"; + } + } + elsif (ref $in or "GLOB" eq ref \$in) { + if (!ref $in && $] < 5.008005) { + $fh = \*$in; + } + else { + $fh = $in; } } else { - $self->{types}; + $enc =~ m/^[-\w.]+$/ and $enc = ":encoding($enc)"; + open $fh, "<$enc", $in or croak "$in: $!"; } - } # types + $fh or croak qq{No valid source passed. "in" is required}; + + my $hdrs = delete $attr{headers}; + my $frag = delete $attr{fragment}; + + defined $attr{auto_diag} or $attr{auto_diag} = 1; + my $csv = Text::CSV_XS->new (\%attr) or croak $last_new_err; + + return { + csv => $csv, + fh => $fh, + in => $in, + out => $out, + hdrs => $hdrs, + frag => $frag, + }; + } # _csv_attr + +sub csv +{ + # This is a function, not a method + @_ && ref $_[0] ne __PACKAGE__ or croak $csv_usage; + + my $c = _csv_attr (@_); + my ($csv, $fh, $hdrs) = @{$c}{"csv", "fh", "hdrs"}; + + if ($c->{out}) { + if (ref $c->{in}[0] eq "ARRAY") { # aoa + ref $hdrs and $csv->print ($fh, $hdrs); + $csv->print ($fh, $_) for @{$c->{in}}; + } + else { # aoh + my @hdrs = ref $hdrs ? @{$hdrs} : keys %{$c->{in}[0]}; + defined $hdrs or $hdrs = "auto"; + ref $hdrs || $hdrs eq "auto" and $csv->print ($fh, \@hdrs); + $csv->print ($fh, [ @{$_}{@hdrs} ]) for @{$c->{in}}; + } + + return close $fh; + } + + if (defined $hdrs && !ref $hdrs) { + $hdrs eq "skip" and $csv->getline ($fh); + $hdrs eq "auto" and $hdrs = $csv->getline ($fh); + } + + my $frag = $c->{frag}; + # aoa + ref $hdrs or + return $frag ? $csv->fragment ($fh, $frag) : $csv->getline_all ($fh); + + # aoh + $csv->column_names ($hdrs); + return $frag ? $csv->fragment ($fh, $frag) : $csv->getline_hr_all ($fh); + } # csv 1; @@ -654,6 +829,14 @@ =head1 SYNOPSIS + # Functional interface + use Text::CSV_XS qw( csv ); + # Read whole file in memory as array of arrays + my $aoa = csv (in => "data.csv"); + # Write array of arrays as csv file + csv (in => $aoa, out => "file.csv", sep_char=> ";"); + + # Object interface use Text::CSV_XS; my @rows; @@ -831,7 +1014,7 @@ =back -=head1 FUNCTIONS +=head1 METHODS =head2 version X<version> @@ -1373,11 +1556,61 @@ $csv->print ($io, [ map { $ref->{$_} } $csv->column_names ]); +=head2 fragment + +This function tries to implement RFC7111 (URI Fragment Identifiers for the +text/csv Media Type) - http://tools.ietf.org/html/rfc7111 + + my $AoA = $csv->fragment ($io, $spec); + +In specifications, C<*> is used to specify the I<last> item, a dash (C<->) +to indicate a range. All indices are 1-based: the first row or column +has index 1. Selections on row and column can be combined with the +semi-colon (C<;>). + +When using this method in combination with L</column_names>, the returned +reference will point to a list of hashes instead of to a list of lists. + + $csv->column_names ("Name", "Age"); + my $AoH = $csv->fragment ($io, "col=3;8"); + +=over 2 + +=item row + + row=4 + row=5-7 + row=6-* + row=1-2;4;6-* + +=item col + + col=2 + col=1-3 + col=4-* + col=1-2;4;7-* + +=item cell + +In cell-based selection, the comma (C<,>) is used to pair row and column + + cell=4,1 + +The range operator using cells can be used to define top-left and bottom-right +cell location + + cell=3,1-4,6 + +=back + +RFC7111 does not allow any combination of the three selection methods. Passing +an invalid fragment specification will croak and set error 2013. + =head2 column_names X<column_names> Set the keys that will be used in the L</getline_hr> calls. If no keys -(column names) are passed, it'll return the current setting. +(column names) are passed, it'll return the current setting as a list. L</column_names> accepts a list of scalars (the column names) or a single array_ref, so you can pass L</getline> @@ -1617,6 +1850,126 @@ Use to reset the diagnostics if you are dealing with errors. +=head1 FUNCTIONS + +=head2 csv +X<csv> + +This function is not exported by default and should be explicitly requested: + + use Text::CSV_XS qw( csv ); + +This is the first draft. This function will stay, but the arguments might +change based on user feedback: esp. the C<headers> attribute is not complete. +The basics will stay. + +This is an high-level function that aims at simple interfaces. It can be used +to read/parse a CSV file or stream (the default behavior) or to produce a file +or write to a stream (define the C<out> attribute). It returns an array +reference on parsing (or undef on fail) or the numeric value of L</error_diag> +on writing. When this function fails you can get to the error using the class +call to L</error_diag> + + my $aoa = csv (in => "test.csv") or + die Text::CSV_XS->error_diag; + +This function takes the arguments as key-value pairs. It can be passed as +a list or as an anonymous hash: + + my $aoa = csv ( in => "test.csv", sep_char => ";"); + my $aoh = csv ({ in => $fh, headers => "auto" }); + +The arguments passed consist of two parts: the arguments to L</csv> itself +and the optional attributes to the CSV object used inside the function as +enumerated and explained in L</new>. + +If not overridden, the default options used for CSV are + + auto_diag => 1 + +These options are always set and cannot be altered + + binary => 1 + +=head3 in +X<in> + +Used to specify the source. C<in> can be a file name (e.g. C<"file.csv">), +which will be opened for reading and closed when finished, a file handle (e.g. +C<$fh> or C<FH>), a reference to a glob (e.g. C<\*ARGV>), or - when your +version of perl is not archaic - the glob itself (e.g. C<*STDIN>). + +When used with L</out>, it should be a reference to a CSV structure (AoA or AoH). + + my $aoa = csv (in => "file.csv"); + + open my $fh, "<", "file.csv"; + my $aoa = csv (in => $fh); + + my $csv = [ [qw( Foo Bar )], [ 1, 2 ], [ 2, 3 ]]; + my $err = csv (in => $csv, out => "file.csv"); + +=head3 out +X<out> + +In output mode, the default CSV options when producing CSV are + + eol => "\r\n" + +The L</fragment> attribute is ignored in output mode. + +C<out> can be a file name (e.g. C<"file.csv">), which will be opened for +writing and closed when finished, a file handle (e.g. C<$fh> or C<FH>), a +reference to a glob (e.g. C<\*STDOUT>), or - when your version of perl is +not archaic - the glob itself (e.g. C<*STDOUT>). + +=head3 encoding +X<encoding> + +If passed, it should be an encoding accepted by the C<:encoding()> option +to C<open>. There is no default value. This attribute does not work in +perl 5.6.x. + +=head3 headers +X<headers> + +If this attribute is not given, the default behavior is to produce an array +of arrays. + +If C<headers> is given, it should be either an anonymous list of column names +or a flag: C<auto> or C<skip>. When C<skip> is used, the header will not be +included in the output. + + my $aoa = csv (in => $fh, headers => "skip"); + +If C<auto> is used, the first line of the CSV source will be read as the list +of field headers and used to produce an array of hashes. + + my $aoh = csv (in => $fh, headers => "auto"); + +If C<headers> is an anonymous list, it will be used instead + + my $aoh = csv (in => $fh, headers => [qw( Foo Bar )]); + csv (in => $aoa, out => $fh, headers => [qw( code description price }]); + +=head3 fragment +X<fragment> + +Only output the fragment as defined in the L</fragment> method. This +attribute is ignored when generating CSV. See L</out>. + +Combining all of them could give something like + + use Text::CSV_XS qw( csv ); + my $aoh = csv ( + in => "test.txt", + encoding => "utf-8", + headers => "auto", + sep_char => "|", + fragment => "row=3;6-9;15-*", + ); + say $aoh->[15]{Foo}; + =head1 INTERNALS =over 4 @@ -1651,6 +2004,11 @@ my @column = map { $_->[3] } @{$csv->getline_all ($fh)}; close $fh or die "file.csv: $!"; +with L</csv>, you could do + + my @column = map { $_->[0] } + @{csv (in => "file.csv", fragment => "col=4")}; + =head2 Parsing CSV strings: my $csv = Text::CSV_XS->new ({ keep_meta_info => 1, binary => 1 }); @@ -1707,6 +2065,13 @@ } close $csv_fh or die "hello.csv: $!"; +=head2 Rewriting CSV + +Rewrite a CSV file with C<;> as separator character to well-formed CSV: + + use Text::CSV_XS qw( csv ); + csv (in => csv (in => "bad.csv", sep_char => ";"), out => *STDOUT); + =head2 The examples folder For more extended examples, see the F<examples/> (1) sub-directory in the @@ -1838,14 +2203,9 @@ =item next - - This might very well be 1.00 - - DIAGNOSTICS setction in pod to *describe* the errors (see below) + - DIAGNOSTICS secttion in pod to *describe* the errors (see below) - croak / carp -=item next + 1 - - - csv2csv - a script to regenerate a CSV file to follow standards - =back =head1 EBCDIC @@ -1970,6 +2330,12 @@ strings that are not required to have a trailing C<eol>. =item * +2013 "INI - Specification error for fragments RFC7111" +X<2013> + +Invalid specification for URI L</fragment> specification. + +=item * 2021 "EIQ - NL char inside quotes, binary off" X<2021> @@ -2119,7 +2485,7 @@ =head1 COPYRIGHT AND LICENSE - Copyright (C) 2007-2013 H.Merijn Brand. All rights reserved. + Copyright (C) 2007-2014 H.Merijn Brand. All rights reserved. Copyright (C) 1998-2001 Jochen Wiedmann. All rights reserved. Copyright (C) 1997 Alan Citterman. All rights reserved. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Text-CSV_XS-1.02/CSV_XS.xs new/Text-CSV_XS-1.04/CSV_XS.xs --- old/Text-CSV_XS-1.02/CSV_XS.xs 2013-09-25 17:52:46.000000000 +0200 +++ new/Text-CSV_XS-1.04/CSV_XS.xs 2014-02-01 11:00:14.000000000 +0100 @@ -1,4 +1,4 @@ -/* Copyright (c) 2007-2013 H.Merijn Brand. All rights reserved. +/* Copyright (c) 2007-2014 H.Merijn Brand. All rights reserved. * Copyright (c) 1998-2001 Jochen Wiedmann. All rights reserved. * This program is free software; you can redistribute it and/or * modify it under the same terms as Perl itself. @@ -162,6 +162,7 @@ { 2010, "ECR - QUO char inside quotes followed by CR not part of EOL" }, { 2011, "ECR - Characters after end of quoted field" }, { 2012, "EOF - End of data in parsing input stream" }, + { 2013, "ESP - Specification error for fragments RFC7111" }, /* EIQ - Error Inside Quotes */ { 2021, "EIQ - NL char inside quotes, binary off" }, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Text-CSV_XS-1.02/ChangeLog new/Text-CSV_XS-1.04/ChangeLog --- old/Text-CSV_XS-1.02/ChangeLog 2013-11-04 21:49:39.000000000 +0100 +++ new/Text-CSV_XS-1.04/ChangeLog 2014-02-01 11:02:39.000000000 +0100 @@ -1,3 +1,14 @@ +1.04 - 2014-02-01, H.Merijn Brand + * get_columnd () with no argument now returns the empty list + instead of undef when no columns defined + * fragments (rcf7111) now also support AoH (was AoA only) + * Error code conflict for fragments resolved to 2013 + * New function "csv" (not a method) + +1.03 - 2014-01-21, H.Merijn Brand + * Update copyright to 2014 + * Implement RCF7111 + 1.02 - 2013-09-25, H.Merijn Brand * Add example for reading only a single column * Don't store NULL in _ERROR_INPUT (RT#86217/Clone) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Text-CSV_XS-1.02/MANIFEST new/Text-CSV_XS-1.04/MANIFEST --- old/Text-CSV_XS-1.02/MANIFEST 2013-11-11 11:40:40.000000000 +0100 +++ new/Text-CSV_XS-1.04/MANIFEST 2014-02-06 08:47:02.000000000 +0100 @@ -26,14 +26,17 @@ t/70_rt.t Tests based on RT reports t/75_hashref.t getline_hr related tests t/76_magic.t array_ref from magic -t/77_getall.t gat all rows at once +t/77_getall.t Get all rows at once +t/78_fragment.t Get fragments according to RFC7111 specs t/80_diag.t Error diagnostics t/81_subclass.t Subclassed +t/90_csv.t Function csv () checks t/util.pl Extra test utilities examples/csv2xls Script to onvert CSV files to M$Excel examples/csv-check Script to check a CSV file/stream examples/csvdiff Script to shoff diff between sorted CSV files examples/parser-xs.pl Parse CSV stream, be forgiving on bad lines +examples/rewrite.pl Simple CSV rewriter examples/speed.pl Small benchmark script files/macosx.csv A CSV files exported on MacOSX files/utf8.csv A UTF-8 encode test file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Text-CSV_XS-1.02/META.json new/Text-CSV_XS-1.04/META.json --- old/Text-CSV_XS-1.02/META.json 2013-11-11 11:40:40.000000000 +0100 +++ new/Text-CSV_XS-1.04/META.json 2014-02-06 08:47:02.000000000 +0100 @@ -1,63 +1,63 @@ { + "generated_by" : "Author", "release_status" : "stable", - "meta-spec" : { - "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", - "version" : "2" - }, - "license" : [ - "perl_5" - ], - "name" : "Text-CSV_XS", + "dynamic_config" : 1, "prereqs" : { - "test" : { + "configure" : { "requires" : { - "Tie::Scalar" : "0", - "Test::More" : "0" + "ExtUtils::MakeMaker" : "0" } }, - "runtime" : { + "test" : { "requires" : { - "DynaLoader" : "0", - "perl" : "5.006001", - "IO::Handle" : "0" - }, - "recommends" : { - "Encode" : "2.55", - "perl" : "5.018001" + "Tie::Scalar" : "0", + "Test::More" : "0" } }, - "configure" : { + "build" : { "requires" : { - "ExtUtils::MakeMaker" : "0" + "Config" : "0" } }, - "build" : { + "runtime" : { + "recommends" : { + "perl" : "5.018001", + "Encode" : "2.57" + }, "requires" : { - "Config" : "0" + "IO::Handle" : "0", + "DynaLoader" : "0", + "perl" : "5.006001" } } }, - "generated_by" : "Author", - "version" : "1.02", - "dynamic_config" : 1, "author" : [ "H.Merijn Brand <[email protected]>" ], - "abstract" : "Comma-Separated Values manipulation routines", + "version" : "1.04", + "license" : [ + "perl_5" + ], "provides" : { "Text::CSV_XS" : { - "version" : "1.02", - "file" : "CSV_XS.pm" + "file" : "CSV_XS.pm", + "version" : "1.04" } }, + "meta-spec" : { + "version" : "2", + "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec" + }, "resources" : { - "license" : [ - "http://dev.perl.org/licenses/" - ], "repository" : { - "url" : "http://repo.or.cz/r/Text-CSV_XS.git", "web" : "http://repo.or.cz/w/Text-CSV_XS.git", + "url" : "http://repo.or.cz/r/Text-CSV_XS.git", "type" : "git" - } - } + }, + "license" : [ + "http://dev.perl.org/licenses/" + ] + }, + "abstract" : "Comma-Separated Values manipulation routines", + "name" : "Text-CSV_XS" } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Text-CSV_XS-1.02/META.yml new/Text-CSV_XS-1.04/META.yml --- old/Text-CSV_XS-1.02/META.yml 2013-11-11 11:40:40.000000000 +0100 +++ new/Text-CSV_XS-1.04/META.yml 2014-02-06 08:47:02.000000000 +0100 @@ -7,7 +7,7 @@ configure_requires: ExtUtils::MakeMaker: 0 dynamic_config: 1 -generated_by: Author, CPAN::Meta::Converter version 2.132830 +generated_by: Author, CPAN::Meta::Converter version 2.133380 license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html @@ -16,9 +16,9 @@ provides: Text::CSV_XS: file: CSV_XS.pm - version: '1.02' + version: '1.04' recommends: - Encode: '2.55' + Encode: '2.57' perl: '5.018001' requires: DynaLoader: 0 @@ -29,4 +29,4 @@ resources: license: http://dev.perl.org/licenses/ repository: http://repo.or.cz/r/Text-CSV_XS.git -version: '1.02' +version: '1.04' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Text-CSV_XS-1.02/Makefile.PL new/Text-CSV_XS-1.04/Makefile.PL --- old/Text-CSV_XS-1.02/Makefile.PL 2013-08-11 10:30:38.000000000 +0200 +++ new/Text-CSV_XS-1.04/Makefile.PL 2014-01-01 14:21:51.000000000 +0100 @@ -1,6 +1,6 @@ #!/usr/bin/perl -# Copyright PROCURA B.V. (c) 2006-2013 H.Merijn Brand +# Copyright PROCURA B.V. (c) 2006-2014 H.Merijn Brand require 5.006001; # <- also see postamble at the bottom for META.yml use strict; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Text-CSV_XS-1.02/README new/Text-CSV_XS-1.04/README --- old/Text-CSV_XS-1.02/README 2013-06-13 13:00:16.000000000 +0200 +++ new/Text-CSV_XS-1.04/README 2014-01-01 14:21:53.000000000 +0100 @@ -7,7 +7,7 @@ combine fields into a CSV string and parse a CSV string into fields. Copying: - Copyright (c) 2007-2013 H.Merijn Brand. All rights reserved. + Copyright (c) 2007-2014 H.Merijn Brand. All rights reserved. Copyright (c) 1998-2001 Jochen Wiedmann. All rights reserved. Portions Copyright (c) 1997 Alan Citterman. All rights reserved. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Text-CSV_XS-1.02/examples/csv-check new/Text-CSV_XS-1.04/examples/csv-check --- old/Text-CSV_XS-1.02/examples/csv-check 2013-07-10 19:52:09.000000000 +0200 +++ new/Text-CSV_XS-1.04/examples/csv-check 2014-01-01 14:21:49.000000000 +0100 @@ -1,7 +1,7 @@ #!/pro/bin/perl # csv-check: Check validity of CSV file and report -# (m)'13 [10 Jul 2013] Copyright H.M.Brand 2007-2013 +# (m)'13 [10 Jul 2013] Copyright H.M.Brand 2007-2014 # This code requires the defined-or feature and PerlIO diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Text-CSV_XS-1.02/examples/csv2xls new/Text-CSV_XS-1.04/examples/csv2xls --- old/Text-CSV_XS-1.02/examples/csv2xls 2013-01-13 17:14:53.000000000 +0100 +++ new/Text-CSV_XS-1.04/examples/csv2xls 2014-01-01 14:21:42.000000000 +0100 @@ -1,12 +1,12 @@ #!/pro/bin/perl # csv2xls: Convert csv to xls -# (m)'11 [06 Oct 2011] Copyright H.M.Brand 2007-2013 +# (m)'13 [04 Dec 2013] Copyright H.M.Brand 2007-2014 use strict; use warnings; -our $VERSION = "1.71"; +our $VERSION = "1.72"; sub usage { @@ -14,13 +14,13 @@ print <<EOU; usage: csv2xls [-s <sep>] [-q <quot>] [-w <width>] [-d <dtfmt>] [-o <xls>] [file.csv] - -s <sep> use <sep> as seperator char. Auto-detect, default = ',' + -s <sep> use <sep> as seperator char, auto-detect, default = ',' The string "tab" is allowed. - -e <esc> use <sep> as seperator char. Auto-detect, default = ',' + -e <esc> use <esc> as escape char, auto-detect, default = '"' The string "undef" is allowed. - -q <quot> use <quot> as quotation char. Default = '"' + -q <quot> use <quot> as quotation char, default = '"' The string "undef" will disable quotation. - -w <width> use <width> as default minimum column width (4) + -w <width> use <width> as default minimum column width default = 4 -o <xls> write output to file named <xls>, defaults to input file name with .csv replaced with .xls if from standard input, defaults to csv2xls.xls @@ -28,6 +28,7 @@ an equal sign are forced to string -f force usage of <xls> if already exists (unlink before use) -d <dtfmt> use <dtfmt> as date formats. Default = 'dd-mm-yyyy' + -C <C:fmt> use <fmt> as currency formats for currency <C>, no default -D cols only convert dates in columns <cols>. Default is everywhere. -u CSV is UTF8 -v [<lvl>] verbosity (default = 1) @@ -45,6 +46,7 @@ my $utf = 0; # Data is encoded in Unicode my $frm = 0; # Allow formula's my $dtf = "dd-mm-yyyy"; # Date format +my $crf = ""; # Currency format, e.g.: $:### ### ##0.00 my $opt_v = 1; my $dtc; @@ -58,6 +60,7 @@ "o|x=s" => \$xls, "d=s" => \$dtf, "D=s" => \$dtc, + "C=s" => \$crf, "f" => \$frc, "F" => \$frm, "u" => \$utf, @@ -79,8 +82,6 @@ use Spreadsheet::WriteExcel; use Encode qw( from_to ); -my $csv; - my $wbk = Spreadsheet::WriteExcel->new ($xls); my $wks = $wbk->add_worksheet (); $dtf =~ s/j/y/g; @@ -94,6 +95,10 @@ align => "left", ), ); +$crf =~ s/^([^:]+):(.*)/$1/ and $fmt{currency} = $wbk->add_format ( + num_format => "$1 $2", + align => "right", + ); my ($h, $w, @w) = (0, 1); # data height, -width, and default column widths my $row; @@ -117,7 +122,7 @@ last; } } -$csv = Text::CSV_XS-> new ({ +my $csv = Text::CSV_XS-> new ({ sep_char => $sep eq "tab" ? "\t" : $sep, quote_char => $quo eq "undef" ? undef : $quo, escape_char => $esc eq "undef" ? undef : $esc, @@ -187,6 +192,10 @@ next; } } + if ($crf and $val =~ m/^\s*\Q$crf\E\s*([0-9.]+)$/) { + $wks->write ($h, $c, $1 + 0, $fmt{currency}); + next; + } if (!$frm && $val =~ m/^=/) { $wks->write_string ($h, $c, $val); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Text-CSV_XS-1.02/examples/parser-xs.pl new/Text-CSV_XS-1.04/examples/parser-xs.pl --- old/Text-CSV_XS-1.02/examples/parser-xs.pl 2013-01-13 17:14:38.000000000 +0100 +++ new/Text-CSV_XS-1.04/examples/parser-xs.pl 2014-01-01 14:20:54.000000000 +0100 @@ -3,7 +3,7 @@ # This script can be used as a base to parse unreliable CSV streams # Modify to your own needs # -# (m)'08 [23 Apr 2008] Copyright H.M.Brand 2008-2013 +# (m)'08 [23 Apr 2008] Copyright H.M.Brand 2008-2014 use strict; use warnings; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Text-CSV_XS-1.02/examples/rewrite.pl new/Text-CSV_XS-1.04/examples/rewrite.pl --- old/Text-CSV_XS-1.02/examples/rewrite.pl 1970-01-01 01:00:00.000000000 +0100 +++ new/Text-CSV_XS-1.04/examples/rewrite.pl 2014-01-31 16:13:35.000000000 +0100 @@ -0,0 +1,17 @@ +#!/pro/bin/perl + +use strict; +use warnings; + +use Text::CSV_XS qw( csv ); + +my $io = shift || \*DATA; + +csv (in => csv (in => $io, sep_char => ";"), out => \*STDOUT); + +__END__ +a;b;c;d;e;f +1;2;3;4;5;6 +2;3;4;5;6;7 +3;4;5;6;7;8 +4;5;6;7;8;9 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Text-CSV_XS-1.02/examples/speed.pl new/Text-CSV_XS-1.04/examples/speed.pl --- old/Text-CSV_XS-1.02/examples/speed.pl 2013-08-12 12:22:18.000000000 +0200 +++ new/Text-CSV_XS-1.04/examples/speed.pl 2014-01-01 14:21:24.000000000 +0100 @@ -1,7 +1,7 @@ #!/usr/bin/perl -w # speed.pl: compare different versions of Text-CSV* modules -# (m)'08 [07 Apr 2008] Copyright H.M.Brand 2007-2013 +# (m)'08 [07 Apr 2008] Copyright H.M.Brand 2007-2014 require 5.006001; use strict; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Text-CSV_XS-1.02/ppport.h new/Text-CSV_XS-1.04/ppport.h --- old/Text-CSV_XS-1.02/ppport.h 2013-09-14 08:42:36.000000000 +0200 +++ new/Text-CSV_XS-1.04/ppport.h 2014-01-21 14:33:55.000000000 +0100 @@ -6,7 +6,7 @@ ppport.h -- Perl/Pollution/Portability Version 3.21 - Automatically created by Devel::PPPort running under perl 5.018000. + Automatically created by Devel::PPPort running under perl 5.018002. Do NOT edit this file directly! -- Edit PPPort_pm.PL and the includes in parts/inc/ instead. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Text-CSV_XS-1.02/t/78_fragment.t new/Text-CSV_XS-1.04/t/78_fragment.t --- old/Text-CSV_XS-1.02/t/78_fragment.t 1970-01-01 01:00:00.000000000 +0100 +++ new/Text-CSV_XS-1.04/t/78_fragment.t 2014-01-25 23:13:42.000000000 +0100 @@ -0,0 +1,75 @@ +#!/pro/bin/perl + +use strict; +use warnings; +$| = 1; + +use Config; +use Test::More; + +BEGIN { + unless (exists $Config{useperlio} && + defined $Config{useperlio} && + $] >= 5.008 && # perlio was experimental in 5.6.2, but not reliable + $Config{useperlio} eq "define") { + plan skip_all => "No reliable perlIO available"; + } + else { + plan tests => 11; + } + } + +use Text::CSV_XS; +my $csv = Text::CSV_XS->new (); + +my %test = ( + "row=1" => [[ 11,12,13,14,15,16,17,18,19 ]], + "row=2-3" => [[ 21,22,23,24,25,26,27,28,29 ], + [ 31,32,33,34,35,36,37,38,39 ]], + "row=2;4;6" => [[ 21,22,23,24,25,26,27,28,29 ], + [ 41,42,43,44,45,46,47,48,49 ], + [ 61,62,63,64,65,66,67,68,69 ]], + "row=1-2;4;6-*" => [[ 11,12,13,14,15,16,17,18,19 ], + [ 21,22,23,24,25,26,27,28,29 ], + [ 41,42,43,44,45,46,47,48,49 ], + [ 61,62,63,64,65,66,67,68,69 ], + [ 71,72,73,74,75,76,77,78,79 ], + [ 81,82,83,84,85,86,87,88,89 ], + [ 91,92,93,94,95,96,97,98,99 ]], + "col=1" => [[11],[21],[31],[41],[51],[61],[71],[81],[91]], + "col=2-3" => [[12,13],[22,23],[32,33],[42,43],[52,53], + [62,63],[72,73],[82,83],[92,93]], + "col=2;4;6" => [[12,14,16],[22,24,26],[32,34,36],[42,44,46],[52,54,56], + [62,64,66],[72,74,76],[82,84,86],[92,94,96]], + "col=1-2;4;6-*" => [[11,12,14,16,17,18,19], [21,22,24,26,27,28,29], + [31,32,34,36,37,38,39], [41,42,44,46,47,48,49], + [51,52,54,56,57,58,59], [61,62,64,66,67,68,69], + [71,72,74,76,77,78,79], [81,82,84,86,87,88,89], + [91,92,94,96,97,98,99]], + "cell=4,5" => [[ 45 ]], + "cell=4,5-5,6" => [[ 45,46 ], [ 55,56 ]], + ); +my $data = join "" => <DATA>; +foreach my $spec (keys %test) { + open my $io, "<", \$data; + my $aoa = $csv->fragment ($io, $spec); + is_deeply ($aoa, $test{$spec}, "Fragment $spec"); + } + +$csv->column_names ("c3","c4"); +open my $io, "<", \$data; +is_deeply ($csv->fragment ($io, "cell=3,2-4,3"), + [ { c3 => 32, c4 =>33 }, { c3 => 42, c4 => 43 }], "Fragment to AoH"); + +#$csv->eol ("\n"); +#foreach my $r (1..9){$csv->print(*STDOUT,[map{$r.$_}1..9])} +__END__ +11,12,13,14,15,16,17,18,19 +21,22,23,24,25,26,27,28,29 +31,32,33,34,35,36,37,38,39 +41,42,43,44,45,46,47,48,49 +51,52,53,54,55,56,57,58,59 +61,62,63,64,65,66,67,68,69 +71,72,73,74,75,76,77,78,79 +81,82,83,84,85,86,87,88,89 +91,92,93,94,95,96,97,98,99 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Text-CSV_XS-1.02/t/80_diag.t new/Text-CSV_XS-1.04/t/80_diag.t --- old/Text-CSV_XS-1.02/t/80_diag.t 2013-09-25 17:55:03.000000000 +0200 +++ new/Text-CSV_XS-1.04/t/80_diag.t 2014-02-01 11:00:07.000000000 +0100 @@ -3,7 +3,7 @@ use strict; use warnings; - use Test::More tests => 143; + use Test::More tests => 179; #use Test::More "no_plan"; my %err; @@ -146,6 +146,29 @@ is ($csv->{_ERROR_INPUT}, undef, "Undefined error_input"); } +foreach my $spec ( + undef, # No spec at all + "", # No spec at all + "row=0", # row > 0 + "col=0", # col > 0 + "cell=0", # cell = r,c + "cell=0,0", # col & row > 0 + "row=*", # * only after n- + "col=3-1", # to >= from + "cell=4,1;1", # cell has no ; + "cell=3,3-2,1", # bottom-right should be right to and below top-left + "row=/", # illegal character + "col=4;row=3", # cannot combine rows and columns + ) { + my $csv = Text::CSV_XS->new (); + my $r; + eval { $r = $csv->fragment (undef, $spec); }; + is ($r, undef, "Cannot do fragment with bad RFC7111 spec"); + my ($c_diag, $s_diag, $p_diag) = $csv->error_diag (); + is ($c_diag, 2013, "Illegal RFC7111 spec"); + is ($p_diag, 0, "Position"); + } + my $diag_file = "_$$.out"; open EH, ">&STDERR"; open STDERR, ">", $diag_file; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Text-CSV_XS-1.02/t/90_csv.t new/Text-CSV_XS-1.04/t/90_csv.t --- old/Text-CSV_XS-1.02/t/90_csv.t 1970-01-01 01:00:00.000000000 +0100 +++ new/Text-CSV_XS-1.04/t/90_csv.t 2014-02-05 18:16:45.000000000 +0100 @@ -0,0 +1,70 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +#use Test::More "no_plan"; + use Test::More tests => 16; + +BEGIN { + use_ok "Text::CSV_XS", ("csv"); + plan skip_all => "Cannot load Text::CSV_XS" if $@; + require "t/util.pl"; + } + +my $file = "_90test.csv"; END { -f $file and unlink $file } +my $data = + "foo,bar,baz\n". + "1,2,3\n". + "2,a b,\n"; +open FH, ">", $file or die "_90test.csv: $!"; +print FH $data; +close FH; + +my $aoa = [ + [qw( foo bar baz )], + [ 1, 2, 3 ], + [ 2, "a b", "" ], + ]; +my $aoh = [ + { foo => 1, bar => 2, baz => 3 }, + { foo => 2, bar => "a b", baz => "" }, + ]; + +for my $io ([ $file, "file" ], [ \*FH, "globref" ], [ *FH, "glob" ]) { + open FH, "<", $file; + is_deeply (csv ({ in => $io->[0] }), $aoa, "AOA $io->[1]"); + close FH; + } + +for my $io ([ $file, "file" ], [ \*FH, "globref" ], [ *FH, "glob" ]) { + open FH, "<", $file; + is_deeply (csv (in => $io->[0], headers => "auto"), $aoh, "AOH $io->[1]"); + close FH; + } + +my @aoa = @{$aoa}[1,2]; +is_deeply (csv (file => $file, headers => "skip"), \@aoa, "AOA skip"); +is_deeply (csv (file => $file, fragment => "row=2-3"), \@aoa, "AOA fragment"); + +if ($] >= 5.008) { + is_deeply (csv (in => $file, encoding => "utf-8", headers => ["a", "b", "c"], + fragment => "row=2", sep_char => ","), + [{ a => 1, b => 2, c => 3 }], "AOH headers fragment"); + } +else { + ok (1, q{This perl does not support open with "<:encoding(...)"}); + } + +unlink $file; +ok (csv (in => $aoa, out => $file), "AOA out file"); +is_deeply (csv (in => $file), $aoa, "AOA parse out"); + +unlink $file; +ok (csv (in => $aoh, out => $file, headers => "auto"), "AOH out file"); +is_deeply (csv (in => $file, headers => "auto"), $aoh, "AOH parse out"); + +unlink $file; +ok (csv (in => $aoh, out => $file, headers => "skip"), "AOH out file no header"); +is_deeply (csv (in => $file, headers => [keys %{$aoh->[0]}]), + $aoh, "AOH parse out no header"); -- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
