Hello community,

here is the log from the commit of package perl-Text-CSV for openSUSE:Factory 
checked in at 2019-01-05 14:41:22
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/perl-Text-CSV (Old)
 and      /work/SRC/openSUSE:Factory/.perl-Text-CSV.new.28833 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "perl-Text-CSV"

Sat Jan  5 14:41:22 2019 rev:23 rq:662642 version:1.99

Changes:
--------
--- /work/SRC/openSUSE:Factory/perl-Text-CSV/perl-Text-CSV.changes      
2018-09-11 17:12:26.987858897 +0200
+++ /work/SRC/openSUSE:Factory/.perl-Text-CSV.new.28833/perl-Text-CSV.changes   
2019-01-05 14:41:23.756529255 +0100
@@ -1,0 +2,20 @@
+Thu Jan  3 06:32:02 UTC 2019 - Stephan Kulow <[email protected]>
+
+- updated to 1.99
+   see /usr/share/doc/packages/perl-Text-CSV/Changes
+
+  1.99  2019-01-02
+      - Fixed a number of tests to skip for older perls
+
+-------------------------------------------------------------------
+Wed Jan  2 06:35:27 UTC 2019 - Stephan Kulow <[email protected]>
+
+- updated to 1.98
+   see /usr/share/doc/packages/perl-Text-CSV/Changes
+
+  1.98  2019-01-02
+      - Imported tests/fixes from Text::CSV_XS 1.38
+        - Added munge as alias for munge_column_names
+        - Added support for key-value pair and combined keys
+
+-------------------------------------------------------------------

Old:
----
  Text-CSV-1.97.tar.gz

New:
----
  Text-CSV-1.99.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ perl-Text-CSV.spec ++++++
--- /var/tmp/diff_new_pack.a1Lphg/_old  2019-01-05 14:41:24.304528790 +0100
+++ /var/tmp/diff_new_pack.a1Lphg/_new  2019-01-05 14:41:24.308528786 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package perl-Text-CSV
 #
-# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -12,18 +12,18 @@
 # license that conforms to the Open Source Definition (Version 1.9)
 # published by the Open Source Initiative.
 
-# Please submit bugfixes or comments via http://bugs.opensuse.org/
+# Please submit bugfixes or comments via https://bugs.opensuse.org/
 #
 
 
 Name:           perl-Text-CSV
-Version:        1.97
+Version:        1.99
 Release:        0
 %define cpan_name Text-CSV
 Summary:        Comma-Separated Values Manipulator (Using Xs or Pureperl)
 License:        Artistic-1.0 OR GPL-1.0-or-later
 Group:          Development/Libraries/Perl
-Url:            http://search.cpan.org/dist/Text-CSV/
+Url:            https://metacpan.org/release/%{cpan_name}
 Source0:        
https://cpan.metacpan.org/authors/id/I/IS/ISHIGAKI/%{cpan_name}-%{version}.tar.gz
 Source1:        cpanspec.yml
 BuildArch:      noarch
@@ -46,11 +46,11 @@
 %setup -q -n %{cpan_name}-%{version}
 
 %build
-%{__perl} Makefile.PL INSTALLDIRS=vendor
-%{__make} %{?_smp_mflags}
+perl Makefile.PL INSTALLDIRS=vendor
+make %{?_smp_mflags}
 
 %check
-%{__make} test
+make test
 
 %install
 %perl_make_install

++++++ Text-CSV-1.97.tar.gz -> Text-CSV-1.99.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Text-CSV-1.97/Changes new/Text-CSV-1.99/Changes
--- old/Text-CSV-1.97/Changes   2018-08-17 17:22:42.000000000 +0200
+++ new/Text-CSV-1.99/Changes   2019-01-02 12:48:53.000000000 +0100
@@ -1,5 +1,13 @@
 Revision history for Perl extension Text::CSV.
 
+1.99  2019-01-02
+    - Fixed a number of tests to skip for older perls
+
+1.98  2019-01-02
+    - Imported tests/fixes from Text::CSV_XS 1.38
+      - Added munge as alias for munge_column_names
+      - Added support for key-value pair and combined keys
+
 1.97  2018-08-17
     - Fix/add minimum perl version (GH-38, Kivanc Yazan++)
     - Updated MANIFEST
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Text-CSV-1.97/META.json new/Text-CSV-1.99/META.json
--- old/Text-CSV-1.97/META.json 2018-08-17 17:23:46.000000000 +0200
+++ new/Text-CSV-1.99/META.json 2019-01-02 12:50:22.000000000 +0100
@@ -54,6 +54,6 @@
          "url" : "https://github.com/makamaka/Text-CSV";
       }
    },
-   "version" : "1.97",
+   "version" : "1.99",
    "x_serialization_backend" : "JSON::PP version 2.94"
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Text-CSV-1.97/META.yml new/Text-CSV-1.99/META.yml
--- old/Text-CSV-1.97/META.yml  2018-08-17 17:23:46.000000000 +0200
+++ new/Text-CSV-1.99/META.yml  2019-01-02 12:50:22.000000000 +0100
@@ -28,5 +28,5 @@
   bugtracker: https://github.com/makamaka/Text-CSV/issues/
   license: http://dev.perl.org/licenses/
   repository: https://github.com/makamaka/Text-CSV
-version: '1.97'
+version: '1.99'
 x_serialization_backend: 'CPAN::Meta::YAML version 0.012'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Text-CSV-1.97/lib/Text/CSV.pm 
new/Text-CSV-1.99/lib/Text/CSV.pm
--- old/Text-CSV-1.97/lib/Text/CSV.pm   2018-08-17 17:20:20.000000000 +0200
+++ new/Text-CSV-1.99/lib/Text/CSV.pm   2019-01-02 12:49:00.000000000 +0100
@@ -9,7 +9,7 @@
 @EXPORT_OK = qw( csv );
 
 BEGIN {
-    $VERSION = '1.97';
+    $VERSION = '1.99';
     $DEBUG   = 0;
 }
 
@@ -141,52 +141,40 @@
 
 =head1 SYNOPSIS
 
+This section is taken from Text::CSV_XS.
+
+ # Functional interface
+ use Text::CSV qw( csv );
+
+ # Read whole file in memory
+ my $aoa = csv (in => "data.csv");    # as array of array
+ my $aoh = csv (in => "data.csv",
+                headers => "auto");   # as array of hash
+
+ # Write array of arrays as csv file
+ csv (in => $aoa, out => "file.csv", sep_char=> ";");
+
+ # Only show lines where "code" is odd
+ csv (in => "data.csv", filter => { code => sub { $_ % 2 }});
+
+ # Object interface
  use Text::CSV;
 
  my @rows;
- my $csv = Text::CSV->new ( { binary => 1 } )  # should set binary attribute.
-                 or die "Cannot use CSV: ".Text::CSV->error_diag ();
-
+ # Read/parse CSV
+ my $csv = Text::CSV->new ({ binary => 1, auto_diag => 1 });
  open my $fh, "<:encoding(utf8)", "test.csv" or die "test.csv: $!";
- while ( my $row = $csv->getline( $fh ) ) {
+ while (my $row = $csv->getline ($fh)) {
      $row->[2] =~ m/pattern/ or next; # 3rd field should match
      push @rows, $row;
- }
- $csv->eof or $csv->error_diag();
+     }
  close $fh;
 
- $csv->eol ("\r\n");
-
+ # and write as CSV
  open $fh, ">:encoding(utf8)", "new.csv" or die "new.csv: $!";
- $csv->print ($fh, $_) for @rows;
+ $csv->say ($fh, $_) for @rows;
  close $fh or die "new.csv: $!";
 
- #
- # parse and combine style
- #
-
- $status = $csv->combine(@columns);    # combine columns into a string
- $line   = $csv->string();             # get the combined string
-
- $status  = $csv->parse($line);        # parse a CSV string into fields
- @columns = $csv->fields();            # get the parsed fields
-
- $status       = $csv->status ();      # get the most recent status
- $bad_argument = $csv->error_input (); # get the most recent bad argument
- $diag         = $csv->error_diag ();  # if an error occurred, explains WHY
-
- $status = $csv->print ($io, $colref); # Write an array of fields
-                                       # immediately to a file $io
- $colref = $csv->getline ($io);        # Read a line from file $io,
-                                       # parse it and return an array
-                                       # ref of fields
- $csv->column_names (@names);          # Set column names for getline_hr ()
- $ref = $csv->getline_hr ($io);        # getline (), but returns a hashref
- $eof = $csv->eof ();                  # Indicate if last parse or
-                                       # getline () hit End Of File
-
- $csv->types(\@t_array);               # Set column types
-
 =head1 DESCRIPTION
 
 Text::CSV is a thin wrapper for L<Text::CSV_XS>-compatible modules now.
@@ -222,7 +210,7 @@
 
 =head1 NOTES
 
-This section is taken from Text::CSV_XS.
+This section is also taken from Text::CSV_XS.
 
 =head2 Embedded newlines
 
@@ -837,6 +825,8 @@
 This attribute is useful when exporting  CSV data  to be imported in custom
 loaders, like for MySQL, that recognize special sequences for C<NULL> data.
 
+This attribute has no meaning when parsing CSV data.
+
 =head3 verbatim
 
  my $csv = Text::CSV->new ({ verbatim => 1 });
@@ -913,6 +903,8 @@
      escape_null           => 1,
      quote_binary          => 1,
      keep_meta_info        => 0,
+     strict                => 0,
+     formula               => 0,
      verbatim              => 0,
      undef_str             => undef,
      types                 => undef,
@@ -1917,9 +1909,12 @@
 =head3 key
 
 If passed,  will default  L<C<headers>|/headers>  to C<"auto"> and return a
-hashref instead of an array of hashes.
+hashref instead of an array of hashes. Allowed values are simple scalars or
+array-references where the first element is the joiner and the rest are the
+fields to join to combine the key.
 
  my $ref = csv (in => "test.csv", key => "code");
+ my $ref = csv (in => "test.csv", key => [ ":" => "code", "color" ]);
 
 with test.csv like
 
@@ -1928,7 +1923,7 @@
  2,keyboard,12,white
  3,mouse,5,black
 
-will return
+the first example will return
 
   { 1   => {
         code    => 1,
@@ -1950,6 +1945,28 @@
         }
     }
 
+the second example will return
+
+  { "1:gray"    => {
+        code    => 1,
+        color   => 'gray',
+        price   => 850,
+        product => 'pc'
+        },
+    "2:white"   => {
+        code    => 2,
+        color   => 'white',
+        price   => 12,
+        product => 'keyboard'
+        },
+    "3:black"   => {
+        code    => 3,
+        color   => 'black',
+        price   => 5,
+        product => 'mouse'
+        }
+    }
+
 The C<key> attribute can be combined with L<C<headers>|/headers> for C<CSV>
 date that has no header line, like
 
@@ -1959,6 +1976,76 @@
      key     =>     "c_foo",
      );
 
+=head3 value
+
+Used to create key-value hashes.
+
+Only allowed when C<key> is valid. A C<value> can be either a single column
+label or an anonymous list of column labels.  In the first case,  the value
+will be a simple scalar value, in the latter case, it will be a hashref.
+
+ my $ref = csv (in => "test.csv", key   => "code",
+                                  value => "price");
+ my $ref = csv (in => "test.csv", key   => "code",
+                                  value => [ "product", "price" ]);
+ my $ref = csv (in => "test.csv", key   => [ ":" => "code", "color" ],
+                                  value => "price");
+ my $ref = csv (in => "test.csv", key   => [ ":" => "code", "color" ],
+                                  value => [ "product", "price" ]);
+
+with test.csv like
+
+ code,product,price,color
+ 1,pc,850,gray
+ 2,keyboard,12,white
+ 3,mouse,5,black
+
+the first example will return
+
+  { 1 => 850,
+    2 =>  12,
+    3 =>   5,
+    }
+
+the second example will return
+
+  { 1   => {
+        price   => 850,
+        product => 'pc'
+        },
+    2   => {
+        price   => 12,
+        product => 'keyboard'
+        },
+    3   => {
+        price   => 5,
+        product => 'mouse'
+        }
+    }
+
+the third example will return
+
+  { "1:gray"    => 850,
+    "2:white"   =>  12,
+    "3:black"   =>   5,
+    }
+
+the fourth example will return
+
+  { "1:gray"    => {
+        price   => 850,
+        product => 'pc'
+        },
+    "2:white"   => {
+        price   => 12,
+        product => 'keyboard'
+        },
+    "3:black"   => {
+        price   => 5,
+        product => 'mouse'
+        }
+    }
+
 =head3 keep_headers
 
 When using hashes,  keep the column names into the arrayref passed,  so all
@@ -2516,6 +2603,16 @@
 The C<key> attribute is of an unsupported type.
 
 =item *
+1502 "PRM - The value attribute is passed without the key attribute"
+
+The C<value> attribute is only allowed when a valid key is given.
+
+=item *
+1503 "PRM - The value attribute is passed as an unsupported type"
+
+The C<value> attribute is of an unsupported type.
+
+=item *
 2010 "ECR - QUO char inside quotes followed by CR not part of EOL"
 
 When  L<C<eol>|/eol>  has  been  set  to  anything  but the  default,  like
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Text-CSV-1.97/lib/Text/CSV_PP.pm 
new/Text-CSV-1.99/lib/Text/CSV_PP.pm
--- old/Text-CSV-1.97/lib/Text/CSV_PP.pm        2018-08-17 17:20:20.000000000 
+0200
+++ new/Text-CSV-1.99/lib/Text/CSV_PP.pm        2019-01-02 12:49:00.000000000 
+0100
@@ -12,7 +12,7 @@
 use vars qw($VERSION @ISA @EXPORT_OK);
 use Carp;
 
-$VERSION = '1.97';
+$VERSION = '1.99';
 @ISA = qw(Exporter);
 @EXPORT_OK = qw(csv);
 
@@ -52,6 +52,8 @@
         # Syntax errors
         1500 => "PRM - Invalid/unsupported arguments(s)",
         1501 => "PRM - The key attribute is passed as an unsupported type",
+        1502 => "PRM - The value attribute is passed without the key 
attribute",
+        1503 => "PRM - The value attribute is passed as an unsupported type",
 
         # Parse errors
         2010 => "ECR - QUO char inside quotes followed by CR not part of EOL",
@@ -95,10 +97,7 @@
         3009 => "EHR - print_hr () called before column_names ()",
         3010 => "EHR - print_hr () called with invalid arguments",
 
-        # PP Only Error
-        4002 => "EIQ - Unescaped ESC in quoted field",
-        4003 => "EIF - ESC CR",
-        4004 => "EUF - Field is terminated by the escape character 
(escape_char)",
+        4001 => "PRM - The key does not exist as field in the data",
 
         0    => "",
 };
@@ -567,6 +566,15 @@
     $self->{strict};
     }
 
+sub _SetDiagInfo {
+     my ($self, $err, $msg) = @_;
+     $self->SetDiag ($err);
+     my $em  = $self->error_diag;
+     $em =~ s/^\d+$// and $msg =~ s/^/# /;
+     my $sep = $em =~ m/[;\n]$/ ? "\n\t" : ": ";
+     join $sep => grep m/\S\S\S/ => $em, $msg;
+     }
+
 sub _supported_formula {
     my ($self, $f) = @_;
     defined $f or return 5;
@@ -576,10 +584,9 @@
     $f =~ m/^(?: 3 | diag    )$/xi ? 3 :
     $f =~ m/^(?: 4 | empty | )$/xi ? 4 :
     $f =~ m/^(?: 5 | undef   )$/xi ? 5 : do {
-       $self ||= "Text::CSV_PP";
-       $self->SetDiag (1500);
-       croak "formula-handling '$f' is not supported\n";
-       };
+        $self ||= "Text::CSV_PP";
+        croak ($self->_SetDiagInfo (1500, "formula-handling '$f' is not 
supported"));
+        };
     }
 
 sub formula {
@@ -940,6 +947,8 @@
         croak (q{usage: $csv->header ($fh, [ seps ], { options })});
         }
 
+    defined $args{munge} && !defined $args{munge_column_names} and
+        $args{munge_column_names} = $args{munge}; # munge as alias
     defined $args{detect_bom}         or $args{detect_bom}         = 1;
     defined $args{set_column_names}   or $args{set_column_names}   = 1;
     defined $args{munge_column_names} or $args{munge_column_names} = "lc";
@@ -953,7 +962,7 @@
 
     if (defined $args{sep_set}) {
         ref $args{sep_set} eq "ARRAY" or
-        croak ($self->SetDiag (1500, "sep_set should be an array ref"));
+            croak ($self->_SetDiagInfo (1500, "sep_set should be an array 
ref"));
         @seps =  @{$args{sep_set}};
     }
 
@@ -1030,9 +1039,12 @@
         @hdr = map { $args{munge_column_names}->($_)       } @hdr;
     ref $args{munge_column_names} eq "HASH" and
         @hdr = map { $args{munge_column_names}->{$_} || $_ } @hdr;
-    my %hdr = map { $_ => 1 } @hdr;
-    exists $hdr{""}   and croak ($self->SetDiag (1012));
-    keys %hdr == @hdr or  croak ($self->SetDiag (1013));
+    my %hdr; $hdr{$_}++ for @hdr;
+    exists $hdr{""} and croak ($self->SetDiag (1012));
+    unless (keys %hdr == @hdr) {
+        croak ($self->_SetDiagInfo (1013, join ", " =>
+            map { "$_ ($hdr{$_})" } grep { $hdr{$_} > 1 } keys %hdr));
+        }
     $args{set_column_names} and $self->column_names (@hdr);
     wantarray ? @hdr : $self;
     }
@@ -1271,6 +1283,7 @@
     my $hdrs = delete $attr{headers};
     my $frag = delete $attr{fragment};
     my $key  = delete $attr{key};
+    my $val  = delete $attr{value};
     my $kh   = delete $attr{keep_headers}      ||
           delete $attr{keep_column_names}      ||
           delete $attr{kh};
@@ -1330,6 +1343,7 @@
         enc  => $enc,
         hdrs => $hdrs,
         key  => $key,
+        val  => $val,
         kh   => $kh,
         frag => $frag,
         fltr => $fltr,
@@ -1413,15 +1427,20 @@
         }
 
     if ($c->{kh}) {
-        ref $c->{kh} eq "ARRAY" or croak ($csv->SetDiag (1501, "1501 - PRM"));
+        ref $c->{kh} eq "ARRAY" or croak ($csv->SetDiag (1501));
         $hdrs ||= "auto";
         }
 
     my $key = $c->{key};
     if ($key) {
-        ref $key and croak ($csv->SetDiag (1501, "1501 - PRM"));
+       !ref $key or ref $key eq "ARRAY" && @$key > 1 or croak ($csv->SetDiag 
(1501));
         $hdrs ||= "auto";
         }
+    my $val = $c->{val};
+    if ($val) {
+       $key                                          or croak ($csv->SetDiag 
(1502));
+       !ref $val or ref $val eq "ARRAY" && @$val > 0 or croak ($csv->SetDiag 
(1503));
+       }
 
     $c->{fltr} && grep m/\D/ => keys %{$c->{fltr}} and $hdrs ||= "auto";
     if (defined $hdrs) {
@@ -1476,9 +1495,30 @@
     my $ref = ref $hdrs
         ? # aoh
           do {
-            $csv->column_names ($hdrs);
+            my @h = $csv->column_names ($hdrs);
+            my %h; $h{$_}++ for @h;
+            exists $h{""} and croak ($csv->SetDiag (1012));
+            unless (keys %h == @h) {
+                croak ($csv->_SetDiagInfo (1013, join ", " =>
+                    map { "$_ ($h{$_})" } grep { $h{$_} > 1 } keys %h));
+                }
             $frag ? $csv->fragment ($fh, $frag) :
-            $key  ? { map { $_->{$key} => $_ } @{$csv->getline_hr_all ($fh)} }
+            $key  ? do {
+                        my ($k, $j, @f) = ref $key ? (undef, @$key) : ($key);
+                        if (my @mk = grep { !exists $h{$_} } grep { defined } 
$k, @f) {
+                            croak ($csv->_SetDiagInfo (4001, join ", " => 
@mk));
+                            }
+                        +{ map {
+                            my $r = $_;
+                            my $K = defined $k ? $r->{$k} : join $j => 
@{$r}{@f};
+                            ( $K => (
+                            $val
+                                ? ref $val
+                                    ? { map { $_ => $r->{$_} } @$val }
+                                    : $r->{$val}
+                                : $r ));
+                            } @{$csv->getline_hr_all ($fh)} }
+                        }
                   : $csv->getline_hr_all ($fh);
             }
         : # aoa
@@ -1721,7 +1761,7 @@
     $self->__cache_show_char(escape_char => $cache->{escape_char});
     $self->__cache_show_char(sep_char => $cache->{sep});
     for (qw/
-        binary decode_utf8 allow_loose_escapes allow_loose_quotes
+        binary decode_utf8 allow_loose_escapes allow_loose_quotes 
allow_unquoted_escape
         allow_whitespace always_quote quote_empty quote_space
         escape_null quote_binary auto_diag diag_verbose formula strict
         has_error_input blank_is_undef empty_is_undef has_ahead
@@ -2874,33 +2914,39 @@
 
 =head1 SYNOPSIS
 
+This section is taken from Text::CSV_XS.
+
+ # Functional interface
+ use Text::CSV_PP qw( csv );
+
+ # Read whole file in memory
+ my $aoa = csv (in => "data.csv");    # as array of array
+ my $aoh = csv (in => "data.csv",
+                headers => "auto");   # as array of hash
+
+ # Write array of arrays as csv file
+ csv (in => $aoa, out => "file.csv", sep_char=> ";");
+
+ # Only show lines where "code" is odd
+ csv (in => "data.csv", filter => { code => sub { $_ % 2 }});
+
+ # Object interface
  use Text::CSV_PP;
 
- $csv = Text::CSV_PP->new();     # create a new object
- # If you want to handle non-ascii char.
- $csv = Text::CSV_PP->new({binary => 1});
-
- $status = $csv->combine(@columns);    # combine columns into a string
- $line   = $csv->string();             # get the combined string
-
- $status  = $csv->parse($line);        # parse a CSV string into fields
- @columns = $csv->fields();            # get the parsed fields
-
- $status       = $csv->status ();      # get the most recent status
- $bad_argument = $csv->error_input (); # get the most recent bad argument
- $diag         = $csv->error_diag ();  # if an error occurred, explains WHY
-
- $status = $csv->print ($io, $colref); # Write an array of fields
-                                       # immediately to a file $io
- $colref = $csv->getline ($io);        # Read a line from file $io,
-                                       # parse it and return an array
-                                       # ref of fields
- $csv->column_names (@names);          # Set column names for getline_hr ()
- $ref = $csv->getline_hr ($io);        # getline (), but returns a hashref
- $eof = $csv->eof ();                  # Indicate if last parse or
-                                       # getline () hit End Of File
+ my @rows;
+ # Read/parse CSV
+ my $csv = Text::CSV_PP->new ({ binary => 1, auto_diag => 1 });
+ open my $fh, "<:encoding(utf8)", "test.csv" or die "test.csv: $!";
+ while (my $row = $csv->getline ($fh)) {
+     $row->[2] =~ m/pattern/ or next; # 3rd field should match
+     push @rows, $row;
+     }
+ close $fh;
 
- $csv->types(\@t_array);               # Set column types
+ # and write as CSV
+ open $fh, ">:encoding(utf8)", "new.csv" or die "new.csv: $!";
+ $csv->say ($fh, $_) for @rows;
+ close $fh or die "new.csv: $!";
 
 =head1 DESCRIPTION
 
@@ -3018,7 +3064,7 @@
 
 =head1 METHODS
 
-This section is taken from Text::CSV_XS.
+This section is also taken from Text::CSV_XS.
 
 =head2 version
 
@@ -3528,6 +3574,8 @@
 This attribute is useful when exporting  CSV data  to be imported in custom
 loaders, like for MySQL, that recognize special sequences for C<NULL> data.
 
+This attribute has no meaning when parsing CSV data.
+
 =head3 verbatim
 
  my $csv = Text::CSV_PP->new ({ verbatim => 1 });
@@ -3604,6 +3652,8 @@
      escape_null           => 1,
      quote_binary          => 1,
      keep_meta_info        => 0,
+     strict                => 0,
+     formula               => 0,
      verbatim              => 0,
      undef_str             => undef,
      types                 => undef,
@@ -4589,9 +4639,12 @@
 =head3 key
 
 If passed,  will default  L<C<headers>|/headers>  to C<"auto"> and return a
-hashref instead of an array of hashes.
+hashref instead of an array of hashes. Allowed values are simple scalars or
+array-references where the first element is the joiner and the rest are the
+fields to join to combine the key.
 
  my $ref = csv (in => "test.csv", key => "code");
+ my $ref = csv (in => "test.csv", key => [ ":" => "code", "color" ]);
 
 with test.csv like
 
@@ -4600,7 +4653,7 @@
  2,keyboard,12,white
  3,mouse,5,black
 
-will return
+the first example will return
 
   { 1   => {
         code    => 1,
@@ -4622,6 +4675,28 @@
         }
     }
 
+the second example will return
+
+  { "1:gray"    => {
+        code    => 1,
+        color   => 'gray',
+        price   => 850,
+        product => 'pc'
+        },
+    "2:white"   => {
+        code    => 2,
+        color   => 'white',
+        price   => 12,
+        product => 'keyboard'
+        },
+    "3:black"   => {
+        code    => 3,
+        color   => 'black',
+        price   => 5,
+        product => 'mouse'
+        }
+    }
+
 The C<key> attribute can be combined with L<C<headers>|/headers> for C<CSV>
 date that has no header line, like
 
@@ -4631,6 +4706,76 @@
      key     =>     "c_foo",
      );
 
+=head3 value
+
+Used to create key-value hashes.
+
+Only allowed when C<key> is valid. A C<value> can be either a single column
+label or an anonymous list of column labels.  In the first case,  the value
+will be a simple scalar value, in the latter case, it will be a hashref.
+
+ my $ref = csv (in => "test.csv", key   => "code",
+                                  value => "price");
+ my $ref = csv (in => "test.csv", key   => "code",
+                                  value => [ "product", "price" ]);
+ my $ref = csv (in => "test.csv", key   => [ ":" => "code", "color" ],
+                                  value => "price");
+ my $ref = csv (in => "test.csv", key   => [ ":" => "code", "color" ],
+                                  value => [ "product", "price" ]);
+
+with test.csv like
+
+ code,product,price,color
+ 1,pc,850,gray
+ 2,keyboard,12,white
+ 3,mouse,5,black
+
+the first example will return
+
+  { 1 => 850,
+    2 =>  12,
+    3 =>   5,
+    }
+
+the second example will return
+
+  { 1   => {
+        price   => 850,
+        product => 'pc'
+        },
+    2   => {
+        price   => 12,
+        product => 'keyboard'
+        },
+    3   => {
+        price   => 5,
+        product => 'mouse'
+        }
+    }
+
+the third example will return
+
+  { "1:gray"    => 850,
+    "2:white"   =>  12,
+    "3:black"   =>   5,
+    }
+
+the fourth example will return
+
+  { "1:gray"    => {
+        price   => 850,
+        product => 'pc'
+        },
+    "2:white"   => {
+        price   => 12,
+        product => 'keyboard'
+        },
+    "3:black"   => {
+        price   => 5,
+        product => 'mouse'
+        }
+    }
+
 =head3 keep_headers
 
 When using hashes,  keep the column names into the arrayref passed,  so all
@@ -5188,6 +5333,16 @@
 The C<key> attribute is of an unsupported type.
 
 =item *
+1502 "PRM - The value attribute is passed without the key attribute"
+
+The C<value> attribute is only allowed when a valid key is given.
+
+=item *
+1503 "PRM - The value attribute is passed as an unsupported type"
+
+The C<value> attribute is of an unsupported type.
+
+=item *
 2010 "ECR - QUO char inside quotes followed by CR not part of EOL"
 
 When  L<C<eol>|/eol>  has  been  set  to  anything  but the  default,  like
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Text-CSV-1.97/t/66_formula.t 
new/Text-CSV-1.99/t/66_formula.t
--- old/Text-CSV-1.97/t/66_formula.t    2018-08-14 13:38:11.000000000 +0200
+++ new/Text-CSV-1.99/t/66_formula.t    2019-01-02 12:47:34.000000000 +0100
@@ -39,7 +39,7 @@
 
 foreach my $f (-1, 9, "xxx", "DIAX", [], {}, sub {}) {
     eval { $csv->formula ($f); };
-    like ($@, qr/^formula-handling '\Q$f\E' is not supported/, "$f in 
invalid");
+    like ($@, qr/\bformula-handling '\Q$f\E' is not supported/, "$f in 
invalid");
     }
 
 my %f = qw(
@@ -55,7 +55,7 @@
     is ($p->formula, $f{$f}, "Set to $f{$f}");
     }
 eval { Text::CSV->new ({ formula => "xxx" }); };
-like ($@, qr/^formula-handling 'xxx' is not supported/, "xxx in invalid");
+like ($@, qr/\bformula-handling 'xxx' is not supported/, "xxx is invalid");
 
 # Parser
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Text-CSV-1.97/t/80_diag.t 
new/Text-CSV-1.99/t/80_diag.t
--- old/Text-CSV-1.97/t/80_diag.t       2018-08-14 13:38:11.000000000 +0200
+++ new/Text-CSV-1.99/t/80_diag.t       2019-01-02 12:47:34.000000000 +0100
@@ -3,7 +3,7 @@
 use strict;
 $^W = 1;
 
- use Test::More tests => 288;
+ use Test::More tests => 303;
 #use Test::More "no_plan";
 
 my %err;
@@ -280,4 +280,30 @@
        }
     }
 
+SKIP: {
+    $] < 5.008 and skip qq{$] does not support ScalarIO}, 14;
+    foreach my $key ({}, sub {}, []) {
+       my $csv = Text::CSV->new;
+       my $x = eval { $csv->csv (in => \"a,b", key => $key) };
+       is ($x, undef, "Invalid key");
+       my @diag = $csv->error_diag;
+       is ($diag[0], 1501, "Invalid key type");
+       }
+
+    {   my $csv = Text::CSV->new;
+       my $x = eval { $csv->csv (in => \"a,b", value => "b") };
+       is ($x, undef, "Value without key");
+       my @diag = $csv->error_diag;
+       is ($diag[0], 1502, "No key");
+       }
+
+    foreach my $val ({}, sub {}, []) {
+       my $csv = Text::CSV->new;
+       my $x = eval { $csv->csv (in => \"a,b", key => "a", value => $val) };
+       is ($x, undef, "Invalid value");
+       my @diag = $csv->error_diag;
+       is ($diag[0], 1503, "Invalid value type");
+       }
+    }
+
 1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Text-CSV-1.97/t/85_util.t 
new/Text-CSV-1.99/t/85_util.t
--- old/Text-CSV-1.97/t/85_util.t       2018-08-14 13:38:11.000000000 +0200
+++ new/Text-CSV-1.99/t/85_util.t       2019-01-02 12:47:34.000000000 +0100
@@ -14,7 +14,7 @@
         plan skip_all => "This test unit requires perl-5.8.2 or higher";
         }
     else {
-       my $n = 1370;
+       my $n = 1442;
        $pu and $n -= 120;
        plan tests => $n;
        }
@@ -279,7 +279,7 @@
            $csv = Text::CSV->new ({ binary => 1, auto_diag => 9 });
 
            SKIP: {
-               $has_enc or skip "Encoding $enc not supported", 7;
+               $has_enc or skip "Encoding $enc not supported", $enc =~ /^utf/ 
? 10 : 9;
                $csv->column_names (undef);
                open my $fh, "<", $fnm;
                binmode $fh;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Text-CSV-1.97/t/90_csv.t new/Text-CSV-1.99/t/90_csv.t
--- old/Text-CSV-1.97/t/90_csv.t        2018-08-14 13:38:11.000000000 +0200
+++ new/Text-CSV-1.99/t/90_csv.t        2019-01-02 12:47:34.000000000 +0100
@@ -5,7 +5,7 @@
 use Config;
 
 #use Test::More "no_plan";
- use Test::More tests => 88;
+ use Test::More tests => 105;
 
 BEGIN {
     $ENV{PERL_TEXT_CSV} = 0;
@@ -117,11 +117,35 @@
 
 # Basic "key" checks
 SKIP: {
-    $] < 5.008 and skip "No ScalarIO support for $]", 2;
+    $] < 5.008 and skip "No ScalarIO support for $]", 4;
+    # Simple key
     is_deeply (csv (in => \"key,value\n1,2\n", key => "key"),
                    { 1 => { key => 1, value => 2 }}, "key");
     is_deeply (csv (in => \"1,2\n", key => "key", headers => [qw( key value 
)]),
                    { 1 => { key => 1, value => 2 }}, "key");
+    # Combined key
+    is_deeply (csv (in => \"a,b,value\n1,1,2\n", key => [ ":" => "a", "b" ]),
+                   { "1:1" => { a => 1, b => 1, value => 2 }}, "key list");
+    is_deeply (csv (in => \"2,3,2\n", key => [ ":" => "a", "b" ], headers => 
[qw( a b value )]),
+                   { "2:3" => { a => 2, b => 3, value => 2 }}, "key list");
+    }
+# Basic "value" checks
+SKIP: {
+    $] < 5.008001 and skip "No ScalarIO support for 'value's in $]", 5;
+    # Simple key simple value
+    is_deeply (csv (in => \"key,value\n1,2\n", key => "key", value => "value"),
+                   { 1 => 2 }, "key:value");
+    is_deeply (csv (in => \"1,2\n", key => "key", headers => [qw( key value 
)], value => "value"),
+                   { 1 => 2 }, "key:value");
+    # Simple key combined value
+    is_deeply (csv (in => \"key,v1,v2\n1,2,3\n", key => "key", value => [ 
"v1", "v2" ]),
+                   { 1 => { v1 => 2, v2 => 3 }}, "key:value");
+    # Combined key simple value
+    is_deeply (csv (in => \"a,b,value\n1,1,2\n", key => [ ":" => "a", "b" ], 
value => "value"),
+                   { "1:1" => 2 }, "[key]:value");
+    # Combined key combined value
+    is_deeply (csv (in => \"a,b,v1,v2\n1,1,2,2\n", key => [ ":" => "a", "b" ], 
value => [ "v1", "v2" ]),
+                   { "1:1" => { v1 => 2, v2 => 2 }}, "[key]:[value]");
     }
 
 # Some "out" checks
@@ -164,24 +188,56 @@
 $] < 5.008 and unlink glob "SCALAR(*)";
 
 # errors
-{   my $err;
+{   my $err = "";
     local $SIG{__DIE__} = sub { $err = shift; };
     my $r = eval { csv (in => undef); };
     is ($r, undef, "csv needs in or file");
     like ($err, qr{^usage:}, "error");
-    undef $err;
+    $err = "";
 
-    $r = eval { csv (in => $tfn, key => ["foo"], auto_diag => 0); };
-    is ($r, undef, "Fail call with bad key type");
-    like ($err, qr{1501 - PRM}, "Error 1501");
-    undef $err;
+    $r = eval { csv (in => $tfn, key => [ ":" ], auto_diag => 0); };
+    $err =~ s{\s+at\s+\S+\s+line\s+\d+\.\r?\n?\Z}{};
+    is ($r, undef, "Fail call with key with not enough fields");
+    like ($err, qr{PRM.*unsupported type}, $err);
+    $err = "";
+
+    $r = eval { csv (in => $tfn, key => { "fx" => 1 }, auto_diag => 0); };
+    $err =~ s{\s+at\s+\S+\s+line\s+\d+\.\r?\n?\Z}{};
+    is ($r, undef, "Fail call with unsupported key type");
+    like ($err, qr{PRM.*unsupported type}, $err);
+    $err = "";
+
+    $r = eval { csv (in => $tfn, key => sub { "foo" }, auto_diag => 0); };
+    $err =~ s{\s+at\s+\S+\s+line\s+\d+\.\r?\n?\Z}{};
+    is ($r, undef, "Fail call with bad unsupported type");
+    like ($err, qr{PRM.*unsupported type}, $err);
+    $err = "";
+
+    $r = eval { csv (in => $tfn, key => "xyz", auto_diag => 0); };
+    $err =~ s{\s+at\s+\S+\s+line\s+\d+\.\r?\n?\Z}{};
+    is ($r, undef, "Fail call with nonexisting key");
+    like ($err, qr{PRM.*xyz}, $err);
+    $err = "";
+
+    $r = eval { csv (in => $tfn, key => [ "x" ], auto_diag => 0); };
+    $err =~ s{\s+at\s+\S+\s+line\s+\d+\.\r?\n?\Z}{};
+    is ($r, undef, "Fail call with no key in keylist");
+    like ($err, qr{PRM.*unsupported type}, $err);
+    $err = "";
+
+    $r = eval { csv (in => $tfn, key => [ ":", "a", "xyz" ], auto_diag => 0); 
};
+    $err =~ s{\s+at\s+\S+\s+line\s+\d+\.\r?\n?\Z}{};
+    is ($r, undef, "Fail call with nonexisting key in keylist");
+    like ($err, qr{PRM.*xyz}, $err);
+    $err = "";
 
     local $SIG{__DIE__} = sub { $err = shift; };
     foreach my $hr (1, "foo", \my %hr, sub { 42; }, *STDOUT) {
        $r = eval { csv (in => $tfn, kh => $hr, auto_diag => 0); };
+       $err =~ s{\s+at\s+\S+\s+line\s+\d+\.\r?\n?\Z}{};
        is ($r, undef, "Fail call with bad keep_header type");
-       like ($err, qr{1501 - PRM}, "Error 1501");
-       undef $err;
+       like ($err, qr{PRM.*unsupported type}, $err);
+       $err = "";
        }
 
 #   $r = eval { csv (in => +{}, auto_diag => 0); };
@@ -190,42 +246,49 @@
 #   undef $err;
 
     $r = eval { csv (in => undef, auto_diag => 0); };
+    $err =~ s{\s+at\s+\S+\s+line\s+\d+\.\r?\n?\Z}{};
     is ($r, undef, "Cannot read from undef");
     like ($err, qr{^usage}, "Remind them of correct syntax");
-    undef $err;
+    $err = "";
 
     $r = eval { csv (in => "", auto_diag => 0); };
+    $err =~ s{\s+at\s+\S+\s+line\s+\d+\.\r?\n?\Z}{};
     is ($r, undef, "Cannot read from empty");
     like ($err, qr{^usage}, "Remind them of correct syntax");
-    undef $err;
+    $err = "";
 
     my $fn = "./dev/foo/bar/\x99\x99/\x88\x88/".
        (join "\x99" => map { chr (128 + int rand 128) } 0..100).".csv";
     $r = eval { csv (in => $fn, auto_diag => 0); };
+    $err =~ s{\s+at\s+\S+\s+line\s+\d+\.\r?\n?\Z}{};
     is ($r, undef, "Cannot read from impossible file");
     like ($err, qr{/foo/bar}, "No such file or directory");
-    undef $err;
+    $err = "";
 
     $r = eval { csv (in => [[1,2]], out => $fn, auto_diag => 0); };
+    $err =~ s{\s+at\s+\S+\s+line\s+\d+\.\r?\n?\Z}{};
     is ($r, undef, "Cannot write to impossible file");
     like ($err, qr{/foo/bar}, "No such file or directory");
-    undef $err;
+    $err = "";
 
     my %x;
     $r = eval { csv (in => $tfn, out => \%x, auto_diag => 0); };
+    $err =~ s{\s+at\s+\S+\s+line\s+\d+\.\r?\n?\Z}{};
     is ($r, undef, "Cannot write to hashref");
     like ($err, qr{Not a GLOB}i, "Not a GLOB");
-    undef $err;
+    $err = "";
 
     $r = eval { csv (); };
+    $err =~ s{\s+at\s+\S+\s+line\s+\d+\.\r?\n?\Z}{};
     is ($r, undef, "Needs arguments");
     like ($err, qr{^usage}i, "Don't know what to do");
-    undef $err;
+    $err = "";
 
     $r = eval { csv (in => "in.csv", out => "out.csv"); };
+    $err =~ s{\s+at\s+\S+\s+line\s+\d+\.\r?\n?\Z}{};
     is ($r, undef, "Cannot use strings for both");
     like ($err, qr{^cannot}i, "Explicitely unsupported");
-    undef $err;
+    $err = "";
     }
 
 eval {


Reply via email to