diff options
author | Steffen Mueller <smueller@cpan.org> | 2009-05-17 11:55:50 +0200 |
---|---|---|
committer | Steffen Mueller <smueller@cpan.org> | 2009-05-17 11:55:50 +0200 |
commit | de044c3605bd12a0b679b024ec9c16b44093c54b (patch) | |
tree | 4994a58d2c64657aa2dcc3f3b8d502f7c1d1fc23 /lib | |
parent | 19e87f221220123fd05380fca766d035586f60bf (diff) | |
download | perl-de044c3605bd12a0b679b024ec9c16b44093c54b.tar.gz |
Upgrade to Parse::CPAN::Meta 1.38
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Parse/CPAN/Meta.pm | 862 | ||||
-rw-r--r-- | lib/Parse/CPAN/Meta/Changes | 8 | ||||
-rw-r--r-- | lib/Parse/CPAN/Meta/t/02_basic.t | 15 | ||||
-rw-r--r-- | lib/Parse/CPAN/Meta/t/03_regression.t | 339 | ||||
-rw-r--r-- | lib/Parse/CPAN/Meta/t/05_export.t | 29 | ||||
-rw-r--r-- | lib/Parse/CPAN/Meta/t/11_meta_yml.t | 139 | ||||
-rw-r--r-- | lib/Parse/CPAN/Meta/t/12_plagger.t | 4 | ||||
-rw-r--r-- | lib/Parse/CPAN/Meta/t/13_perl_smith.t | 2 | ||||
-rw-r--r-- | lib/Parse/CPAN/Meta/t/14_yaml_org.t | 2 | ||||
-rw-r--r-- | lib/Parse/CPAN/Meta/t/15_multibyte.t | 3 | ||||
-rw-r--r-- | lib/Parse/CPAN/Meta/t/17_toolbar.t | 1 | ||||
-rw-r--r-- | lib/Parse/CPAN/Meta/t/18_tap.t | 90 | ||||
-rw-r--r-- | lib/Parse/CPAN/Meta/t/19_errors.t | 43 | ||||
-rw-r--r-- | lib/Parse/CPAN/Meta/t/21_bom.t | 39 | ||||
-rw-r--r-- | lib/Parse/CPAN/Meta/t/data/Spreadsheet-Read.yml | 61 |
15 files changed, 1166 insertions, 471 deletions
diff --git a/lib/Parse/CPAN/Meta.pm b/lib/Parse/CPAN/Meta.pm index afbb587bfd..d65d7bb59f 100644 --- a/lib/Parse/CPAN/Meta.pm +++ b/lib/Parse/CPAN/Meta.pm @@ -1,425 +1,437 @@ -package Parse::CPAN::Meta; - -use strict; -use Carp 'croak'; -BEGIN { - require 5.004; - require Exporter; - $Parse::CPAN::Meta::VERSION = '0.05'; - @Parse::CPAN::Meta::ISA = qw{ Exporter }; - @Parse::CPAN::Meta::EXPORT_OK = qw{ Load LoadFile }; -} - -# Prototypes -sub LoadFile ($); -sub Load ($); -sub _scalar ($$$); -sub _array ($$$); -sub _hash ($$$); - -# Printable characters for escapes -my %UNESCAPES = ( - z => "\x00", a => "\x07", t => "\x09", - n => "\x0a", v => "\x0b", f => "\x0c", - r => "\x0d", e => "\x1b", '\\' => '\\', -); - - -my %BOM = ( - "\357\273\277" => 'UTF-8', - "\376\377" => 'UTF-16BE', - "\377\376" => 'UTF-16LE', - "\0\0\376\377" => 'UTF-32BE', - "\377\376\0\0" => 'UTF-32LE' -); - -sub BOM_MIN_LENGTH () { 2 } -sub BOM_MAX_LENGTH () { 4 } -sub HAVE_UTF8 () { $] >= 5.007003 } - -BEGIN { require utf8 if HAVE_UTF8 } - - -##################################################################### -# Implementation - -# Create an object from a file -sub LoadFile ($) { - # Check the file - my $file = shift; - croak('You did not specify a file name') unless $file; - croak( "File '$file' does not exist" ) unless -e $file; - croak( "'$file' is a directory, not a file" ) unless -f _; - croak( "Insufficient permissions to read '$file'" ) unless -r _; - - # Slurp in the file - local $/ = undef; - open( CFG, $file ) or croak("Failed to open file '$file': $!"); - my $yaml = <CFG>; - close CFG or croak("Failed to close file '$file': $!"); - - # Hand off to the actual parser - Load( $yaml ); -} - -# Parse a document from a string. -# Doing checks on $_[0] prevents us having to do a string copy. -sub Load ($) { - - my $str = $_[0]; - - # Handle special cases - foreach my $length ( BOM_MIN_LENGTH .. BOM_MAX_LENGTH ) { - if ( my $enc = $BOM{substr($str, 0, $length)} ) { - croak("Stream has a non UTF-8 BOM") unless $enc eq 'UTF-8'; - substr($str, 0, $length) = ''; # strip UTF-8 bom if found, we'll just ignore it - } - } - - if ( HAVE_UTF8 ) { - utf8::decode($str); # try to decode as utf8 - } - - unless ( defined $str ) { - croak("Did not provide a string to Load"); - } - return() unless length $str; - unless ( $str =~ /[\012\015]+$/ ) { - croak("Stream does not end with newline character"); - } - - # Split the file into lines - my @lines = grep { ! /^\s*(?:\#.*)?$/ } - split /(?:\015{1,2}\012|\015|\012)/, $str; - - # A nibbling parser - my @documents = (); - while ( @lines ) { - # Do we have a document header? - if ( $lines[0] =~ /^---\s*(?:(.+)\s*)?$/ ) { - # Handle scalar documents - shift @lines; - if ( defined $1 and $1 !~ /^(?:\#.+|\%YAML:[\d\.]+)$/ ) { - push @documents, _scalar( "$1", [ undef ], \@lines ); - next; - } - } - - if ( ! @lines or $lines[0] =~ /^---\s*(?:(.+)\s*)?$/ ) { - # A naked document - push @documents, undef; - - } elsif ( $lines[0] =~ /^\s*\-/ ) { - # An array at the root - my $document = [ ]; - push @documents, $document; - _array( $document, [ 0 ], \@lines ); - - } elsif ( $lines[0] =~ /^(\s*)\w/ ) { - # A hash at the root - my $document = { }; - push @documents, $document; - _hash( $document, [ length($1) ], \@lines ); - - } else { - croak("Parse::CPAN::Meta does not support the line '$lines[0]'"); - } - } - - if ( wantarray ) { - return @documents; - } else { - return $documents[-1]; - } -} - -# Deparse a scalar string to the actual scalar -sub _scalar ($$$) { - my $string = shift; - my $indent = shift; - my $lines = shift; - - # Trim trailing whitespace - $string =~ s/\s*$//; - - # Explitic null/undef - return undef if $string eq '~'; - - # Quotes - if ( $string =~ /^\'(.*?)\'$/ ) { - return '' unless defined $1; - my $rv = $1; - $rv =~ s/\'\'/\'/g; - return $rv; - } - if ( $string =~ /^\"((?:\\.|[^\"])*)\"$/ ) { - my $str = $1; - $str =~ s/\\"/"/g; - $str =~ s/\\([never\\fartz]|x([0-9a-fA-F]{2}))/(length($1)>1)?pack("H2",$2):$UNESCAPES{$1}/gex; - return $str; - } - if ( $string =~ /^[\'\"]/ ) { - # A quote with folding... we don't support that - croak("Parse::CPAN::Meta does not support multi-line quoted scalars"); - } - - # Null hash and array - if ( $string eq '{}' ) { - # Null hash - return {}; - } - if ( $string eq '[]' ) { - # Null array - return []; - } - - # Regular unquoted string - return $string unless $string =~ /^[>|]/; - - # Error - croak("Multi-line scalar content missing") unless @$lines; - - # Check the indent depth - $lines->[0] =~ /^(\s*)/; - $indent->[-1] = length("$1"); - if ( defined $indent->[-2] and $indent->[-1] <= $indent->[-2] ) { - croak("Illegal line indenting"); - } - - # Pull the lines - my @multiline = (); - while ( @$lines ) { - $lines->[0] =~ /^(\s*)/; - last unless length($1) >= $indent->[-1]; - push @multiline, substr(shift(@$lines), length($1)); - } - - my $j = (substr($string, 0, 1) eq '>') ? ' ' : "\n"; - my $t = (substr($string, 1, 1) eq '-') ? '' : "\n"; - return join( $j, @multiline ) . $t; -} - -# Parse an array -sub _array ($$$) { - my $array = shift; - my $indent = shift; - my $lines = shift; - - while ( @$lines ) { - # Check for a new document - return 1 if $lines->[0] =~ /^---\s*(?:(.+)\s*)?$/; - - # Check the indent level - $lines->[0] =~ /^(\s*)/; - if ( length($1) < $indent->[-1] ) { - return 1; - } elsif ( length($1) > $indent->[-1] ) { - croak("Hash line over-indented"); - } - - if ( $lines->[0] =~ /^(\s*\-\s+)[^\'\"]\S*\s*:(?:\s+|$)/ ) { - # Inline nested hash - my $indent2 = length("$1"); - $lines->[0] =~ s/-/ /; - push @$array, { }; - _hash( $array->[-1], [ @$indent, $indent2 ], $lines ); - - } elsif ( $lines->[0] =~ /^\s*\-(\s*)(.+?)\s*$/ ) { - # Array entry with a value - shift @$lines; - push @$array, _scalar( "$2", [ @$indent, undef ], $lines ); - - } elsif ( $lines->[0] =~ /^\s*\-\s*$/ ) { - shift @$lines; - unless ( @$lines ) { - push @$array, undef; - return 1; - } - if ( $lines->[0] =~ /^(\s*)\-/ ) { - my $indent2 = length("$1"); - if ( $indent->[-1] == $indent2 ) { - # Null array entry - push @$array, undef; - } else { - # Naked indenter - push @$array, [ ]; - _array( $array->[-1], [ @$indent, $indent2 ], $lines ); - } - - } elsif ( $lines->[0] =~ /^(\s*)\w/ ) { - push @$array, { }; - _hash( $array->[-1], [ @$indent, length("$1") ], $lines ); - - } else { - croak("Parse::CPAN::Meta does not support the line '$lines->[0]'"); - } - - } elsif ( defined $indent->[-2] and $indent->[-1] == $indent->[-2] ) { - # This is probably a structure like the following... - # --- - # foo: - # - list - # bar: value - # - # ... so lets return and let the hash parser handle it - return 1; - - } else { - croak("Parse::CPAN::Meta does not support the line '$lines->[0]'"); - } - } - - return 1; -} - -# Parse an array -sub _hash ($$$) { - my $hash = shift; - my $indent = shift; - my $lines = shift; - - while ( @$lines ) { - # Check for a new document - return 1 if $lines->[0] =~ /^---\s*(?:(.+)\s*)?$/; - - # Check the indent level - $lines->[0] =~/^(\s*)/; - if ( length($1) < $indent->[-1] ) { - return 1; - } elsif ( length($1) > $indent->[-1] ) { - croak("Hash line over-indented"); - } - - # Get the key - unless ( $lines->[0] =~ s/^\s*([^\'\"][^\n]*?)\s*:(\s+|$)// ) { - croak("Bad hash line"); - } - my $key = $1; - - # Do we have a value? - if ( length $lines->[0] ) { - # Yes - $hash->{$key} = _scalar( shift(@$lines), [ @$indent, undef ], $lines ); - next; - } - - # An indent - shift @$lines; - unless ( @$lines ) { - $hash->{$key} = undef; - return 1; - } - if ( $lines->[0] =~ /^(\s*)-/ ) { - $hash->{$key} = []; - _array( $hash->{$key}, [ @$indent, length($1) ], $lines ); - } elsif ( $lines->[0] =~ /^(\s*)./ ) { - my $indent2 = length("$1"); - if ( $indent->[-1] >= $indent2 ) { - # Null hash entry - $hash->{$key} = undef; - } else { - $hash->{$key} = {}; - _hash( $hash->{$key}, [ @$indent, length($1) ], $lines ); - } - } - } - - return 1; -} - -1; - -__END__ - -=pod - -=head1 NAME - -Parse::CPAN::Meta - Parse META.yml and other similar CPAN metadata files - -=head1 SYNOPSIS - - ############################################# - # In your file - - --- - rootproperty: blah - section: - one: two - three: four - Foo: Bar - empty: ~ - - - - ############################################# - # In your program - - use Parse::CPAN::Meta; - - # Create a YAML file - my @yaml = Parse::CPAN::Meta::LoadFile( 'Meta.yml' ); - - # Reading properties - my $root = $yaml[0]->{rootproperty}; - my $one = $yaml[0]->{section}->{one}; - my $Foo = $yaml[0]->{section}->{Foo}; - -=head1 DESCRIPTION - -B<Parse::CPAN::Meta> is a parser for META.yml files, based on the -parser half of L<YAML::Tiny>. - -It supports a basic subset of the full YAML specification, enough to -implement parsing of typical META.yml files, and other similarly simple -YAML files. - -If you need something with more power, move up to a full YAML parser such -as L<YAML>, L<YAML::Syck> or L<YAML::LibYAML>. - -Parse::CPAN::Meta provides a very simply API of only two functions, based -on the YAML functions of the same name. Wherever possible, identical -calling semantics are used. - -All error reporting is done with exceptions (dieing). - -=head1 FUNCTIONS - -For maintenance clarity, no functions are exported. - -=head2 Load( $string ) - - my @documents = Load( $string ); - -Parses a string containing a valid YAML stream into a list of Perl data -structures. - -=head2 LoadFile( $file_name ) - -Reads the YAML stream from a file instead of a string. - -=head1 SUPPORT - -Bugs should be reported via the CPAN bug tracker at - -L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Parse-CPAN-Meta> - -=head1 AUTHOR - -Adam Kennedy E<lt>adamk@cpan.orgE<gt> - -=head1 SEE ALSO - -L<YAML::Tiny>, L<YAML>, L<YAML::Syck> - -=head1 COPYRIGHT - -Copyright 2006 - 2009 Adam Kennedy. - -This program is free software; you can redistribute -it and/or modify it under the same terms as Perl itself. - -The full text of the license can be found in the -LICENSE file included with this module. - -=cut +package Parse::CPAN::Meta;
+
+use strict;
+use Carp 'croak';
+
+# UTF Support?
+sub HAVE_UTF8 () { $] >= 5.007003 }
+BEGIN {
+ if ( HAVE_UTF8 ) {
+ # The string eval helps hide this from Test::MinimumVersion
+ eval "require utf8;";
+ die "Failed to load UTF-8 support" if $@;
+ }
+
+ # Class structure
+ require 5.004;
+ require Exporter;
+ $Parse::CPAN::Meta::VERSION = '1.38';
+ @Parse::CPAN::Meta::ISA = qw{ Exporter };
+ @Parse::CPAN::Meta::EXPORT_OK = qw{ Load LoadFile };
+}
+
+# Prototypes
+sub LoadFile ($);
+sub Load ($);
+sub _scalar ($$$);
+sub _array ($$$);
+sub _hash ($$$);
+
+# Printable characters for escapes
+my %UNESCAPES = (
+ z => "\x00", a => "\x07", t => "\x09",
+ n => "\x0a", v => "\x0b", f => "\x0c",
+ r => "\x0d", e => "\x1b", '\\' => '\\',
+);
+
+
+
+
+
+#####################################################################
+# Implementation
+
+# Create an object from a file
+sub LoadFile ($) {
+ # Check the file
+ my $file = shift;
+ croak('You did not specify a file name') unless $file;
+ croak( "File '$file' does not exist" ) unless -e $file;
+ croak( "'$file' is a directory, not a file" ) unless -f _;
+ croak( "Insufficient permissions to read '$file'" ) unless -r _;
+
+ # Slurp in the file
+ local $/ = undef;
+ local *CFG;
+ unless ( open( CFG, $file ) ) {
+ croak("Failed to open file '$file': $!");
+ }
+ my $yaml = <CFG>;
+ unless ( close(CFG) ) {
+ croak("Failed to close file '$file': $!");
+ }
+
+ # Hand off to the actual parser
+ Load( $yaml );
+}
+
+# Parse a document from a string.
+# Doing checks on $_[0] prevents us having to do a string copy.
+sub Load ($) {
+ my $string = $_[0];
+ unless ( defined $string ) {
+ croak("Did not provide a string to load");
+ }
+
+ # Byte order marks
+ if ( $string =~ /^(?:\376\377|\377\376|\377\376\0\0|\0\0\376\377)/ ) {
+ croak("Stream has a non UTF-8 Unicode Byte Order Mark");
+ } else {
+ # Strip UTF-8 bom if found, we'll just ignore it
+ $string =~ s/^\357\273\277//;
+ }
+
+ # Try to decode as utf8
+ utf8::decode($string) if HAVE_UTF8;
+
+ # Check for some special cases
+ return () unless length $string;
+ unless ( $string =~ /[\012\015]+\z/ ) {
+ croak("Stream does not end with newline character");
+ }
+
+ # Split the file into lines
+ my @lines = grep { ! /^\s*(?:\#.*)?\z/ }
+ split /(?:\015{1,2}\012|\015|\012)/, $string;
+
+ # Strip the initial YAML header
+ @lines and $lines[0] =~ /^\%YAML[: ][\d\.]+.*\z/ and shift @lines;
+
+ # A nibbling parser
+ my @documents = ();
+ while ( @lines ) {
+ # Do we have a document header?
+ if ( $lines[0] =~ /^---\s*(?:(.+)\s*)?\z/ ) {
+ # Handle scalar documents
+ shift @lines;
+ if ( defined $1 and $1 !~ /^(?:\#.+|\%YAML[: ][\d\.]+)\z/ ) {
+ push @documents, _scalar( "$1", [ undef ], \@lines );
+ next;
+ }
+ }
+
+ if ( ! @lines or $lines[0] =~ /^(?:---|\.\.\.)/ ) {
+ # A naked document
+ push @documents, undef;
+ while ( @lines and $lines[0] !~ /^---/ ) {
+ shift @lines;
+ }
+
+ } elsif ( $lines[0] =~ /^\s*\-/ ) {
+ # An array at the root
+ my $document = [ ];
+ push @documents, $document;
+ _array( $document, [ 0 ], \@lines );
+
+ } elsif ( $lines[0] =~ /^(\s*)\S/ ) {
+ # A hash at the root
+ my $document = { };
+ push @documents, $document;
+ _hash( $document, [ length($1) ], \@lines );
+
+ } else {
+ croak("Parse::CPAN::Meta failed to classify line '$lines[0]'");
+ }
+ }
+
+ if ( wantarray ) {
+ return @documents;
+ } else {
+ return $documents[-1];
+ }
+}
+
+# Deparse a scalar string to the actual scalar
+sub _scalar ($$$) {
+ my ($string, $indent, $lines) = @_;
+
+ # Trim trailing whitespace
+ $string =~ s/\s*\z//;
+
+ # Explitic null/undef
+ return undef if $string eq '~';
+
+ # Quotes
+ if ( $string =~ /^\'(.*?)\'\z/ ) {
+ return '' unless defined $1;
+ $string = $1;
+ $string =~ s/\'\'/\'/g;
+ return $string;
+ }
+ if ( $string =~ /^\"((?:\\.|[^\"])*)\"\z/ ) {
+ # Reusing the variable is a little ugly,
+ # but avoids a new variable and a string copy.
+ $string = $1;
+ $string =~ s/\\"/"/g;
+ $string =~ s/\\([never\\fartz]|x([0-9a-fA-F]{2}))/(length($1)>1)?pack("H2",$2):$UNESCAPES{$1}/gex;
+ return $string;
+ }
+
+ # Special cases
+ if ( $string =~ /^[\'\"!&]/ ) {
+ croak("Parse::CPAN::Meta does not support a feature in line '$lines->[0]'");
+ }
+ return {} if $string eq '{}';
+ return [] if $string eq '[]';
+
+ # Regular unquoted string
+ return $string unless $string =~ /^[>|]/;
+
+ # Error
+ croak("Parse::CPAN::Meta failed to find multi-line scalar content") unless @$lines;
+
+ # Check the indent depth
+ $lines->[0] =~ /^(\s*)/;
+ $indent->[-1] = length("$1");
+ if ( defined $indent->[-2] and $indent->[-1] <= $indent->[-2] ) {
+ croak("Parse::CPAN::Meta found bad indenting in line '$lines->[0]'");
+ }
+
+ # Pull the lines
+ my @multiline = ();
+ while ( @$lines ) {
+ $lines->[0] =~ /^(\s*)/;
+ last unless length($1) >= $indent->[-1];
+ push @multiline, substr(shift(@$lines), length($1));
+ }
+
+ my $j = (substr($string, 0, 1) eq '>') ? ' ' : "\n";
+ my $t = (substr($string, 1, 1) eq '-') ? '' : "\n";
+ return join( $j, @multiline ) . $t;
+}
+
+# Parse an array
+sub _array ($$$) {
+ my ($array, $indent, $lines) = @_;
+
+ while ( @$lines ) {
+ # Check for a new document
+ if ( $lines->[0] =~ /^(?:---|\.\.\.)/ ) {
+ while ( @$lines and $lines->[0] !~ /^---/ ) {
+ shift @$lines;
+ }
+ return 1;
+ }
+
+ # Check the indent level
+ $lines->[0] =~ /^(\s*)/;
+ if ( length($1) < $indent->[-1] ) {
+ return 1;
+ } elsif ( length($1) > $indent->[-1] ) {
+ croak("Parse::CPAN::Meta found bad indenting in line '$lines->[0]'");
+ }
+
+ if ( $lines->[0] =~ /^(\s*\-\s+)[^\'\"]\S*\s*:(?:\s+|$)/ ) {
+ # Inline nested hash
+ my $indent2 = length("$1");
+ $lines->[0] =~ s/-/ /;
+ push @$array, { };
+ _hash( $array->[-1], [ @$indent, $indent2 ], $lines );
+
+ } elsif ( $lines->[0] =~ /^\s*\-(\s*)(.+?)\s*\z/ ) {
+ # Array entry with a value
+ shift @$lines;
+ push @$array, _scalar( "$2", [ @$indent, undef ], $lines );
+
+ } elsif ( $lines->[0] =~ /^\s*\-\s*\z/ ) {
+ shift @$lines;
+ unless ( @$lines ) {
+ push @$array, undef;
+ return 1;
+ }
+ if ( $lines->[0] =~ /^(\s*)\-/ ) {
+ my $indent2 = length("$1");
+ if ( $indent->[-1] == $indent2 ) {
+ # Null array entry
+ push @$array, undef;
+ } else {
+ # Naked indenter
+ push @$array, [ ];
+ _array( $array->[-1], [ @$indent, $indent2 ], $lines );
+ }
+
+ } elsif ( $lines->[0] =~ /^(\s*)\S/ ) {
+ push @$array, { };
+ _hash( $array->[-1], [ @$indent, length("$1") ], $lines );
+
+ } else {
+ croak("Parse::CPAN::Meta failed to classify line '$lines->[0]'");
+ }
+
+ } elsif ( defined $indent->[-2] and $indent->[-1] == $indent->[-2] ) {
+ # This is probably a structure like the following...
+ # ---
+ # foo:
+ # - list
+ # bar: value
+ #
+ # ... so lets return and let the hash parser handle it
+ return 1;
+
+ } else {
+ croak("Parse::CPAN::Meta failed to classify line '$lines->[0]'");
+ }
+ }
+
+ return 1;
+}
+
+# Parse an array
+sub _hash ($$$) {
+ my ($hash, $indent, $lines) = @_;
+
+ while ( @$lines ) {
+ # Check for a new document
+ if ( $lines->[0] =~ /^(?:---|\.\.\.)/ ) {
+ while ( @$lines and $lines->[0] !~ /^---/ ) {
+ shift @$lines;
+ }
+ return 1;
+ }
+
+ # Check the indent level
+ $lines->[0] =~ /^(\s*)/;
+ if ( length($1) < $indent->[-1] ) {
+ return 1;
+ } elsif ( length($1) > $indent->[-1] ) {
+ croak("Parse::CPAN::Meta found bad indenting in line '$lines->[0]'");
+ }
+
+ # Get the key
+ unless ( $lines->[0] =~ s/^\s*([^\'\" ][^\n]*?)\s*:(\s+|$)// ) {
+ if ( $lines->[0] =~ /^\s*[?\'\"]/ ) {
+ croak("Parse::CPAN::Meta does not support a feature in line '$lines->[0]'");
+ }
+ croak("Parse::CPAN::Meta failed to classify line '$lines->[0]'");
+ }
+ my $key = $1;
+
+ # Do we have a value?
+ if ( length $lines->[0] ) {
+ # Yes
+ $hash->{$key} = _scalar( shift(@$lines), [ @$indent, undef ], $lines );
+ } else {
+ # An indent
+ shift @$lines;
+ unless ( @$lines ) {
+ $hash->{$key} = undef;
+ return 1;
+ }
+ if ( $lines->[0] =~ /^(\s*)-/ ) {
+ $hash->{$key} = [];
+ _array( $hash->{$key}, [ @$indent, length($1) ], $lines );
+ } elsif ( $lines->[0] =~ /^(\s*)./ ) {
+ my $indent2 = length("$1");
+ if ( $indent->[-1] >= $indent2 ) {
+ # Null hash entry
+ $hash->{$key} = undef;
+ } else {
+ $hash->{$key} = {};
+ _hash( $hash->{$key}, [ @$indent, length($1) ], $lines );
+ }
+ }
+ }
+ }
+
+ return 1;
+}
+
+1;
+
+__END__
+
+=pod
+
+=head1 NAME
+
+Parse::CPAN::Meta - Parse META.yml and other similar CPAN metadata files
+
+=head1 SYNOPSIS
+
+ #############################################
+ # In your file
+
+ ---
+ rootproperty: blah
+ section:
+ one: two
+ three: four
+ Foo: Bar
+ empty: ~
+
+
+
+ #############################################
+ # In your program
+
+ use Parse::CPAN::Meta;
+
+ # Create a YAML file
+ my @yaml = Parse::CPAN::Meta::LoadFile( 'Meta.yml' );
+
+ # Reading properties
+ my $root = $yaml[0]->{rootproperty};
+ my $one = $yaml[0]->{section}->{one};
+ my $Foo = $yaml[0]->{section}->{Foo};
+
+=head1 DESCRIPTION
+
+B<Parse::CPAN::Meta> is a parser for F<META.yml> files, based on the
+parser half of L<YAML::Tiny>.
+
+It supports a basic subset of the full YAML specification, enough to
+implement parsing of typical F<META.yml> files, and other similarly simple
+YAML files.
+
+If you need something with more power, move up to a full YAML parser such
+as L<YAML>, L<YAML::Syck> or L<YAML::LibYAML>.
+
+B<Parse::CPAN::Meta> provides a very simply API of only two functions,
+based on the YAML functions of the same name. Wherever possible,
+identical calling semantics are used.
+
+All error reporting is done with exceptions (die'ing).
+
+=head1 FUNCTIONS
+
+For maintenance clarity, no functions are exported.
+
+=head2 Load
+
+ my @yaml = Load( $string );
+
+Parses a string containing a valid YAML stream into a list of Perl data
+structures.
+
+=head2 LoadFile
+
+ my @yaml = LoadFile( 'META.yml' );
+
+Reads the YAML stream from a file instead of a string.
+
+=head1 SUPPORT
+
+Bugs should be reported via the CPAN bug tracker at
+
+L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Parse-CPAN-Meta>
+
+=head1 AUTHOR
+
+Adam Kennedy E<lt>adamk@cpan.orgE<gt>
+
+=head1 SEE ALSO
+
+L<YAML>, L<YAML::Syck>, L<Config::Tiny>, L<CSS::Tiny>,
+L<http://use.perl.org/~Alias/journal/29427>, L<http://ali.as/>
+
+=head1 COPYRIGHT
+
+Copyright 2006 - 2009 Adam Kennedy.
+
+This program is free software; you can redistribute
+it and/or modify it under the same terms as Perl itself.
+
+The full text of the license can be found in the
+LICENSE file included with this module.
+
+=cut
diff --git a/lib/Parse/CPAN/Meta/Changes b/lib/Parse/CPAN/Meta/Changes index d602d4a58c..21fc89605c 100644 --- a/lib/Parse/CPAN/Meta/Changes +++ b/lib/Parse/CPAN/Meta/Changes @@ -1,5 +1,13 @@ Revision history for Perl extension Parse-CPAN-Meta +1.38 Sat 16 May 2009 + - Synchorised version numbers with YAML::Tiny + - Code shrinkages to the bloaty Unicode/BOM code + - Merging a ton more tests from YAML::Tiny + - Added back some pointless options to yaml_ok that keep our + codebase closer to YAML::Tiny (which should help with syncing) + - Changed exceptions to be closer to YAML::Tiny + 0.05 Wed 11 Mar 2009 - Upgrade previous release to a stable release. diff --git a/lib/Parse/CPAN/Meta/t/02_basic.t b/lib/Parse/CPAN/Meta/t/02_basic.t index 6b65e0261a..f6a91c1707 100644 --- a/lib/Parse/CPAN/Meta/t/02_basic.t +++ b/lib/Parse/CPAN/Meta/t/02_basic.t @@ -56,26 +56,31 @@ yaml_ok( "---\n", [ undef ], 'only_header', + noyamlperl => 1, ); yaml_ok( "---\n---\n", [ undef, undef ], 'two_header', + noyamlperl => 1, ); yaml_ok( "--- ~\n", [ undef ], 'one_undef', + noyamlperl => 1, ); yaml_ok( "--- ~\n", [ undef ], 'one_undef2', + noyamlperl => 1, ); yaml_ok( "--- ~\n---\n", [ undef, undef ], 'two_undef', + noyamlperl => 1, ); # Just a scalar @@ -110,6 +115,7 @@ yaml_ok( "---\n- ~\n- bar\n", [ [ undef, 'bar' ] ], 'one_listundef', + noyamlperl => 1, ); # Simple hashs @@ -123,6 +129,7 @@ yaml_ok( "---\nfoo: bar\nthis: ~\n", [ { this => undef, foo => 'bar' } ], 'one_hash2', + noyamlperl => 1, ); # Simple array inside a hash with an undef @@ -136,6 +143,7 @@ foo: END_YAML [ { foo => [ 'bar', undef, 'baz' ] } ], 'array_in_hash', + noyamlperl => 1, ); # Simple hash inside a hash with an undef @@ -148,6 +156,7 @@ bar: END_YAML [ { foo => undef, bar => { foo => 'bar' } } ], 'hash_in_hash', + noyamlperl => 1, ); # Mixed hash and scalars inside an array @@ -170,6 +179,7 @@ END_YAML { foo => 'bar', this => 'that' }, ] ], 'hash_in_array', + noyamlperl => 1, ); # Simple single quote @@ -194,12 +204,16 @@ yaml_ok( "--- \" \"\n", [ ' ' ], "only_spaces", + noyamlpm => 1, + noyamlperl => 1, ); yaml_ok( "--- \" foo\"\n--- \"bar \"\n", [ " foo", "bar " ], "leading_trailing_spaces", + noyamlpm => 1, + noyamlperl => 1, ); # Implicit document start @@ -225,6 +239,7 @@ yaml_ok( END_YAML [ [ undef, { foo => 'bar', this => 'that' }, 'baz' ] ], 'inline_nested_hash', + noyamlperl => 1, ); # Empty comments diff --git a/lib/Parse/CPAN/Meta/t/03_regression.t b/lib/Parse/CPAN/Meta/t/03_regression.t index 1a1436a9d7..e9fb70a8fb 100644 --- a/lib/Parse/CPAN/Meta/t/03_regression.t +++ b/lib/Parse/CPAN/Meta/t/03_regression.t @@ -20,7 +20,7 @@ BEGIN { use File::Spec::Functions ':ALL'; use Parse::CPAN::Meta::Test; -use Test::More tests(20); +use Test::More tests(37); @@ -62,42 +62,91 @@ yaml_ok( ); # Piped multi-line scalar -yaml_ok( <<'END_YAML', [ [ "foo\nbar\n", 1 ] ], 'indented', nosyck => 1 ); +yaml_ok( + <<'END_YAML', --- - | foo bar - 1 END_YAML + [ [ "foo\nbar\n", 1 ] ], + 'indented', +); # ... with a pointless hyphen -yaml_ok( <<'END_YAML', [ [ "foo\nbar", 1 ] ], 'indented', nosyck => 1 ); +yaml_ok( <<'END_YAML', --- - |- foo bar - 1 END_YAML - + [ [ "foo\nbar", 1 ] ], + 'indented', +); ##################################################################### -# Support for YAML document version declarations +# Support for YAML version directives -# Simple case +# Simple inline case (comment variant) yaml_ok( <<'END_YAML', --- #YAML:1.0 foo: bar END_YAML [ { foo => 'bar' } ], - 'simple_doctype', + 'simple_doctype_comment', + nosyck => 1, +); + +# Simple inline case (percent variant) +yaml_ok( + <<'END_YAML', +--- %YAML:1.0 +foo: bar +END_YAML + [ { foo => 'bar' } ], + 'simple_doctype_percent', + noyamlpm => 1, + noxs => 1, + noyamlperl => 1, +); + +# Simple header (comment variant) +yaml_ok( + <<'END_YAML', +%YAML:1.0 +--- +foo: bar +END_YAML + [ { foo => 'bar' } ], + 'predocument_1_0', + noyamlpm => 1, + nosyck => 1, + noxs => 1, + noyamlperl => 1, ); -# Multiple documents +# Simple inline case (comment variant) +yaml_ok( + <<'END_YAML', +%YAML 1.1 +--- +foo: bar +END_YAML + [ { foo => 'bar' } ], + 'predocument_1_1', + noyamlpm => 1, + nosyck => 1, + noyamlperl => 1, +); + +# Multiple inline documents (comment variant) yaml_ok( <<'END_YAML', --- #YAML:1.0 @@ -108,7 +157,32 @@ foo: bar foo: bar END_YAML [ { foo => 'bar' }, [ 1 ], { foo => 'bar' } ], - 'multi_doctype', + 'multi_doctype_comment', +); + +# Simple pre-document case (comment variant) +yaml_ok( + <<'END_YAML', +%YAML 1.1 +--- +foo: bar +END_YAML + [ { foo => 'bar' } ], + 'predocument_percent', + noyamlpm => 1, + nosyck => 1, + noyamlperl => 1, +); + +# Simple pre-document case (comment variant) +yaml_ok( + <<'END_YAML', +#YAML 1.1 +--- +foo: bar +END_YAML + [ { foo => 'bar' } ], + 'predocument_comment', ); @@ -192,8 +266,13 @@ arr: - ~ - 'bar' END_YAML - [ { abstract => 'Generate fractal curves', foo => undef, arr => [ 'foo', undef, 'bar' ] } ], + [ { + abstract => 'Generate fractal curves', + foo => undef, + arr => [ 'foo', undef, 'bar' ], + } ], 'trailing whitespace', + noyamlperl => 1, ); @@ -218,15 +297,35 @@ END_YAML ##################################################################### -# Single Quote Idiosyncracy +# Quote and Escaping Idiosyncracies + +yaml_ok( + <<'END_YAML', +--- +name1: 'O''Reilly' +name2: 'O''Reilly O''Tool' +name3: 'Double '''' Quote' +END_YAML + [ { + name1 => "O'Reilly", + name2 => "O'Reilly O'Tool", + name3 => "Double '' Quote", + } ], + 'single quote subtleties', +); yaml_ok( <<'END_YAML', --- -slash: '\\' -name: 'O''Reilly' +slash1: '\\' +slash2: '\\foo' +slash3: '\\foo\\\\' END_YAML - [ { slash => "\\\\", name => "O'Reilly" } ], + [ { + slash1 => "\\\\", + slash2 => "\\\\foo", + slash3 => "\\\\foo\\\\\\\\", + } ], 'single quote subtleties', ); @@ -246,6 +345,8 @@ build_requires: END_YAML [ { foo => 0, requires => undef, build_requires => undef } ], 'empty hash keys', + noyamlpm => 1, + noyamlperl => 1, ); yaml_ok( @@ -257,6 +358,8 @@ yaml_ok( END_YAML [ [ 'foo', undef, undef ] ], 'empty array keys', + noyamlpm => 1, + noyamlperl => 1, ); @@ -273,6 +376,8 @@ foo: bar END_YAML [ { foo => 'bar' } ], 'comment header', + noyamlpm => 1, + noyamlperl => 1, ); @@ -295,6 +400,163 @@ END_YAML +##################################################################### +# Confirm we can read the synopsis + +yaml_ok( + <<'END_YAML', +--- +rootproperty: blah +section: + one: two + three: four + Foo: Bar + empty: ~ +END_YAML + [ { + rootproperty => 'blah', + section => { + one => 'two', + three => 'four', + Foo => 'Bar', + empty => undef, + }, + } ], + 'synopsis', + noyamlperl => 1, +); + + + + + +##################################################################### +# Unprintable Characters + +yaml_ok( + "--- \"foo\\n\\x00\"\n", + [ "foo\n\0" ], + 'unprintable', +); + + + + + +##################################################################### +# Empty Quote Line + +yaml_ok( + <<'END_YAML', +--- +- foo +# +- bar +END_YAML + [ [ "foo", "bar" ] ], +); + + + + + +##################################################################### +# Indentation after empty hash value + +yaml_ok( + <<'END_YAML', +--- +Test: + optmods: + Bad: 0 + Foo: 1 + Long: 0 + version: 5 +Test_IncludeA: + optmods: +Test_IncludeB: + optmods: +_meta: + name: 'test profile' + note: 'note this test profile' +END_YAML + [ { + Test => { + optmods => { + Bad => 0, + Foo => 1, + Long => 0, + }, + version => 5, + }, + Test_IncludeA => { + optmods => undef, + }, + Test_IncludeB => { + optmods => undef, + }, + _meta => { + name => 'test profile', + note => 'note this test profile', + }, + } ], + 'Indentation after empty hash value', + noyamlperl => 1, +); + + + + + +##################################################################### +# Spaces in the Key + +yaml_ok( + <<'END_YAML', +--- +the key: the value +END_YAML + [ { 'the key' => 'the value' } ], +); + + + + + +##################################################################### +# Ticker #32402 + +# Tests a particular pathological case + +yaml_ok( + <<'END_YAML', +--- +- value +- '><' +END_YAML + [ [ 'value', '><' ] ], + 'Pathological >< case', +); + + + + + +##################################################################### +# Special Characters + +#yaml_ok( +# <<'END_YAML', +#--- +#- "Ingy d\xC3\xB6t Net" +#END_YAML +# [ [ "Ingy d\xC3\xB6t Net" ] ], +#); + + + + + ###################################################################### # Non-Indenting Sub-List @@ -308,4 +570,53 @@ bar: value END_YAML [ { foo => [ 'list' ], bar => 'value' } ], 'Non-indenting sub-list', + noyamlpm => 1, + noyamlperl => 1, +); + + + + + + +##################################################################### +# Check Multiple-Escaping + +# RT #42119: write of two single quotes +yaml_ok( + "--- \"A'B'C\"\n", + [ "A'B'C" ], + 'Multiple escaping of quote ok', +); + +# Escapes without whitespace +yaml_ok( + "--- A\\B\\C\n", + [ "A\\B\\C" ], + 'Multiple escaping of escape ok', +); + +# Escapes with whitespace +yaml_ok( + "--- 'A\\B \\C'\n", + [ "A\\B \\C" ], + 'Multiple escaping of escape with whitespace ok', +); + + + + + +###################################################################### +# Check illegal characters that are in legal places + +yaml_ok( + "--- 'Wow!'\n", + [ "Wow!" ], + 'Bang in a quote', +); +yaml_ok( + "--- 'This&that'\n", + [ "This&that" ], + 'Ampersand in a quote', ); diff --git a/lib/Parse/CPAN/Meta/t/05_export.t b/lib/Parse/CPAN/Meta/t/05_export.t new file mode 100644 index 0000000000..f82cc91cf6 --- /dev/null +++ b/lib/Parse/CPAN/Meta/t/05_export.t @@ -0,0 +1,29 @@ +#!/usr/bin/perl + +# Testing of basic document structures + +BEGIN { + if( $ENV{PERL_CORE} ) { + chdir 't'; + @INC = ('../lib', 'lib'); + } + else { + unshift @INC, 't/lib/'; + } +} + +use strict; +BEGIN { + $| = 1; + $^W = 1; +} + +use Test::More tests => 4; +use Parse::CPAN::Meta; + + + +ok not(defined &main::Load), 'Load is not exported'; +ok not(defined &main::Dump), 'Dump is not exported'; +ok not(defined &main::LoadFile), 'LoadFile is not exported'; +ok not(defined &main::DumpFile), 'DumpFile is not exported'; diff --git a/lib/Parse/CPAN/Meta/t/11_meta_yml.t b/lib/Parse/CPAN/Meta/t/11_meta_yml.t index c5a493467d..fe95d1abef 100644 --- a/lib/Parse/CPAN/Meta/t/11_meta_yml.t +++ b/lib/Parse/CPAN/Meta/t/11_meta_yml.t @@ -20,14 +20,14 @@ BEGIN { use File::Spec::Functions ':ALL'; use Parse::CPAN::Meta::Test; -use Test::More tests(8, 2); +use Test::More tests(8, 3); ##################################################################### -# Testing YAML::Tiny's META.yml file +# Testing YAML::Tiny's own META.yml file yaml_ok( <<'END_YAML', @@ -198,6 +198,7 @@ END_YAML generated_by => 'ExtUtils::MakeMaker version 6.17', } ], 'Acme-Time-Baby', + noyamlperl => 1, ); @@ -209,30 +210,6 @@ END_YAML yaml_ok( <<'END_YAML', ---- %YAML:1.0 -name: Data-Swap -version: 0.05 -license: perl -distribution_type: module -requires: - perl: 5.6.0 -dynamic_config: 0 -END_YAML - [ { - name => 'Data-Swap', - version => '0.05', - license => 'perl', - distribution_type => 'module', - requires => { - perl => '5.6.0', - }, - dynamic_config => '0', - } ], - 'Data-Swap', -); - -yaml_ok( - <<'END_YAML', --- #YAML:1.0 name: Data-Swap version: 0.05 @@ -253,6 +230,7 @@ END_YAML dynamic_config => '0', } ], 'Data-Swap', + nosyck => 1, ); @@ -293,6 +271,7 @@ SCOPE: { version => '1.2.1', } ], 'Template-Provider-Unicode-Japanese', + noyamlperl => 1, ); } @@ -314,5 +293,113 @@ SCOPE: { version => '0.04', } ], 'HTML-WebDAO', + nosyck => 1, + ); +} + +SCOPE: { + my $content = load_ok( + 'Spreadsheet-Read.yml', + catfile( test_data_directory(), 'Spreadsheet-Read.yml' ), + 100 + ); + yaml_ok( + $content, + [ { + 'resources' => { + 'license' => 'http://dev.perl.org/licenses/' + }, + 'meta-spec' => { + 'version' => '1.4', + 'url' => 'http://module-build.sourceforge.net/META-spec-v1.4.html' + }, + 'distribution_type' => 'module', + 'generated_by' => 'Author', + 'version' => 'VERSION', + 'name' => 'Read', + 'author' => [ + 'H.Merijn Brand <h.m.brand@xs4all.nl>' + ], + 'license' => 'perl', + 'build_requires' => { + 'Test::More' => '0', + 'Test::Harness' => '0', + 'perl' => '5.006' + }, + 'provides' => { + 'Spreadsheet::Read' => { + 'version' => 'VERSION', + 'file' => 'Read.pm' + } + }, + 'optional_features' => [ + { + 'opt_csv' => { + 'requires' => { + 'Text::CSV_XS' => '0.23' + }, + 'recommends' => { + 'Text::CSV_PP' => '1.10', + 'Text::CSV_XS' => '0.58', + 'Text::CSV' => '1.10' + }, + 'description' => 'Provides parsing of CSV streams' + } + }, + { + 'opt_excel' => { + 'requires' => { + 'Spreadsheet::ParseExcel' => '0.26', + 'Spreadsheet::ParseExcel::FmtDefault' => '0' + }, + 'recommends' => { + 'Spreadsheet::ParseExcel' => '0.42' + }, + 'description' => 'Provides parsing of Microsoft Excel files' + } + }, + { + 'opt_excelx' => { + 'requires' => { + 'Spreadsheet::XLSX' => '0.07' + }, + 'description' => 'Provides parsing of Microsoft Excel 2007 files' + } + }, + { + 'opt_oo' => { + 'requires' => { + 'Spreadsheet::ReadSXC' => '0.2' + }, + 'description' => 'Provides parsing of OpenOffice spreadsheets' + } + }, + { + 'opt_tools' => { + 'recommends' => { + 'Tk::TableMatrix::Spreadsheet' => '0', + 'Tk::NoteBook' => '0', + 'Tk' => '0' + }, + 'description' => 'Spreadsheet tools' + } + } + ], + 'requires' => { + 'perl' => '5.006', + 'Data::Dumper' => '0', + 'Exporter' => '0', + 'Carp' => '0' + }, + 'recommends' => { + 'perl' => '5.008005', + 'IO::Scalar' => '0', + 'File::Temp' => '0.14' + }, + 'abstract' => 'Meta-Wrapper for reading spreadsheet data' + } ], + 'Spreadsheet-Read', + noyamlpm => 1, + noyamlperl => 1, ); } diff --git a/lib/Parse/CPAN/Meta/t/12_plagger.t b/lib/Parse/CPAN/Meta/t/12_plagger.t index 68f3761417..5e186f3bc6 100644 --- a/lib/Parse/CPAN/Meta/t/12_plagger.t +++ b/lib/Parse/CPAN/Meta/t/12_plagger.t @@ -101,8 +101,8 @@ plugins: nickname: plaggerbot server_host: chat.freenode.net server_channels: - - #plagger-ja - - #plagger + - '#plagger-ja' + - '#plagger' END_YAML diff --git a/lib/Parse/CPAN/Meta/t/13_perl_smith.t b/lib/Parse/CPAN/Meta/t/13_perl_smith.t index 557f9bbf9b..9a8b8be709 100644 --- a/lib/Parse/CPAN/Meta/t/13_perl_smith.t +++ b/lib/Parse/CPAN/Meta/t/13_perl_smith.t @@ -153,4 +153,6 @@ yaml_ok( }, } ], 'vanilla.yml', + nosyck => 1, + noyamlperl => 1, ); diff --git a/lib/Parse/CPAN/Meta/t/14_yaml_org.t b/lib/Parse/CPAN/Meta/t/14_yaml_org.t index 5f01274457..254bd7a547 100644 --- a/lib/Parse/CPAN/Meta/t/14_yaml_org.t +++ b/lib/Parse/CPAN/Meta/t/14_yaml_org.t @@ -68,5 +68,5 @@ Late afternoon is best. Backup contact is Nancy Billsmer @ 338-4338. END_TEXT } ], 'sample.yml', - + # nosyck => 1, ); diff --git a/lib/Parse/CPAN/Meta/t/15_multibyte.t b/lib/Parse/CPAN/Meta/t/15_multibyte.t index a67c0f989a..214b8b0c26 100644 --- a/lib/Parse/CPAN/Meta/t/15_multibyte.t +++ b/lib/Parse/CPAN/Meta/t/15_multibyte.t @@ -51,6 +51,3 @@ SKIP: { skip "no utf8 support", 1 unless Parse::CPAN::Meta::HAVE_UTF8(); ok( utf8::is_utf8($yaml[0]->{author}), "utf8 decoded" ); } - -exit(0); - diff --git a/lib/Parse/CPAN/Meta/t/17_toolbar.t b/lib/Parse/CPAN/Meta/t/17_toolbar.t index 2b2e06ec83..e0d3cf9876 100644 --- a/lib/Parse/CPAN/Meta/t/17_toolbar.t +++ b/lib/Parse/CPAN/Meta/t/17_toolbar.t @@ -55,4 +55,5 @@ yaml_ok( ] } ], 'toolbar.yml', + noyamlperl => 1, ); diff --git a/lib/Parse/CPAN/Meta/t/18_tap.t b/lib/Parse/CPAN/Meta/t/18_tap.t new file mode 100644 index 0000000000..62b84f936e --- /dev/null +++ b/lib/Parse/CPAN/Meta/t/18_tap.t @@ -0,0 +1,90 @@ +#!/usr/bin/perl + +# Testing relating to functionality in the Test Anything Protocol + +BEGIN { + if( $ENV{PERL_CORE} ) { + chdir 't'; + @INC = ('../lib', 'lib'); + } + else { + unshift @INC, 't/lib/'; + } +} + +use strict; +BEGIN { + $| = 1; + $^W = 1; +} + +use File::Spec::Functions ':ALL'; +use Parse::CPAN::Meta::Test; +use Test::More tests(5, 0, 0); +use Parse::CPAN::Meta (); + + + + + +##################################################################### +# TAP Tests + +# Make sure we support x-foo keys +yaml_ok( + "---\nx-foo: 1\n", + [ { 'x-foo' => 1 } ], + 'x-foo key', +); + +# Document ending (hash) +yaml_ok( + "---\n" + . " foo: bar\n" + . "...\n", + [ { foo => "bar" } ], + 'document_end_hash', + noyamlpm => 1, + nosyck => 1, + noyamlperl => 1, +); + +# Document ending (array) +yaml_ok( + "---\n" + . "- foo\n" + . "...\n", + [ [ 'foo' ] ], + 'document_end_array', + noyamlpm => 1, + noyamlperl => 1, +); + +# Multiple documents (simple) +yaml_ok( + "---\n" + . "- foo\n" + . "...\n" + . "---\n" + . "- foo\n" + . "...\n", + [ [ 'foo' ], [ 'foo' ] ], + 'multi_document_simple', + noyamlpm => 1, + noyamlperl => 1, +); + +# Multiple documents (whitespace-separated) +yaml_ok( + "---\n" + . "- foo\n" + . "...\n" + . "\n" + . "---\n" + . "- foo\n" + . "...\n", + [ [ 'foo' ], [ 'foo' ] ], + 'multi_document_space', + noyamlpm => 1, + noyamlperl => 1, +); diff --git a/lib/Parse/CPAN/Meta/t/19_errors.t b/lib/Parse/CPAN/Meta/t/19_errors.t new file mode 100644 index 0000000000..baa06ad5b2 --- /dev/null +++ b/lib/Parse/CPAN/Meta/t/19_errors.t @@ -0,0 +1,43 @@ +#!/usr/bin/perl + +# Testing documents that should fail + +BEGIN { + if( $ENV{PERL_CORE} ) { + chdir 't'; + @INC = ('../lib', 'lib'); + } + else { + unshift @INC, 't/lib/'; + } +} + +use strict; +BEGIN { + $| = 1; + $^W = 1; +} + +use File::Spec::Functions ':ALL'; +use Parse::CPAN::Meta::Test; +use Test::More tests => 1; + + + + + +##################################################################### +# Missing Features + +# We don't support raw nodes +yaml_error( <<'END_YAML', 'does not support a feature' ); +--- +version: !!perl/hash:version + original: v2.0.2 + qv: 1 + version: + - 2 + - 0 + - 2 +END_YAML + diff --git a/lib/Parse/CPAN/Meta/t/21_bom.t b/lib/Parse/CPAN/Meta/t/21_bom.t new file mode 100644 index 0000000000..706cf77c3f --- /dev/null +++ b/lib/Parse/CPAN/Meta/t/21_bom.t @@ -0,0 +1,39 @@ +#!/usr/bin/perl + +BEGIN { + if( $ENV{PERL_CORE} ) { + chdir 't'; + @INC = ('../lib', 'lib'); + } + else { + unshift @INC, 't/lib/'; + } +} + +use strict; +BEGIN { + $| = 1; + $^W = 1; +} + +use File::Spec::Functions ':ALL'; +use Parse::CPAN::Meta::Test; +use Test::More tests(0, 1, 3); + + + + + +##################################################################### +# Testing that Perl::Smith config files work + +my $sample_file = catfile( test_data_directory(), 'utf_16_le_bom.yml' ); +my $sample = load_ok( 'utf_16_le_bom.yml', $sample_file, 3 ); + +# Does the string parse to the structure +my $name = "utf-16"; +my $yaml_copy = $sample; +my $yaml = eval { Parse::CPAN::Meta::Load( $yaml_copy ); }; +is( $yaml_copy, $sample, "$name: Parse::CPAN::Meta::Load does not modify the input string" ); +is( $yaml, undef, "file not parsed" ); +ok( $@ =~ "Stream has a non UTF-8 Unicode Byte Order Mark", "correct error" ); diff --git a/lib/Parse/CPAN/Meta/t/data/Spreadsheet-Read.yml b/lib/Parse/CPAN/Meta/t/data/Spreadsheet-Read.yml new file mode 100644 index 0000000000..f402ab8d68 --- /dev/null +++ b/lib/Parse/CPAN/Meta/t/data/Spreadsheet-Read.yml @@ -0,0 +1,61 @@ +--- #YAML:1.1 +name: Read +version: VERSION +abstract: Meta-Wrapper for reading spreadsheet data +license: perl +author: + - H.Merijn Brand <h.m.brand@xs4all.nl> +generated_by: Author +distribution_type: module +provides: + Spreadsheet::Read: + file: Read.pm + version: VERSION +requires: + perl: 5.006 + Exporter: 0 + Carp: 0 + Data::Dumper: 0 +recommends: + perl: 5.008005 + File::Temp: 0.14 + IO::Scalar: 0 +build_requires: + perl: 5.006 + Test::Harness: 0 + Test::More: 0 +optional_features: +- opt_csv: + description: Provides parsing of CSV streams + requires: + Text::CSV_XS: 0.23 + recommends: + Text::CSV: 1.10 + Text::CSV_PP: 1.10 + Text::CSV_XS: 0.58 +- opt_excel: + description: Provides parsing of Microsoft Excel files + requires: + Spreadsheet::ParseExcel: 0.26 + Spreadsheet::ParseExcel::FmtDefault: 0 + recommends: + Spreadsheet::ParseExcel: 0.42 +- opt_excelx: + description: Provides parsing of Microsoft Excel 2007 files + requires: + Spreadsheet::XLSX: 0.07 +- opt_oo: + description: Provides parsing of OpenOffice spreadsheets + requires: + Spreadsheet::ReadSXC: 0.2 +- opt_tools: + description: Spreadsheet tools + recommends: + Tk: 0 + Tk::NoteBook: 0 + Tk::TableMatrix::Spreadsheet: 0 +resources: + license: http://dev.perl.org/licenses/ +meta-spec: + version: 1.4 + url: http://module-build.sourceforge.net/META-spec-v1.4.html |