refactor _load(). fix an issue with use_ext => 0. use_ext now on by default. throw...
Brian Cassidy [Tue, 13 Nov 2007 15:21:57 +0000 (15:21 +0000)]
Changes
lib/Config/Any.pm
lib/Config/Any/General.pm
lib/Config/Any/INI.pm
lib/Config/Any/JSON.pm
lib/Config/Any/Perl.pm
lib/Config/Any/XML.pm
lib/Config/Any/YAML.pm
t/62-multi.t [new file with mode: 0644]
t/multi/conf.yml [new file with mode: 0644]

diff --git a/Changes b/Changes
index ce9363b..1b5e0e9 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,34 +1,38 @@
 Revision history for Config-Any
 
-0.09 Thu Nov 08 2007
-    code and pod cleanups
+0.09_01 Tue Nov 13 2007
+    - code and pod cleanups
+    - use_ext is now on by default
+    - when use_ext is on, if a parser throws an error, we throw an error
+    - fix case where use_ext is defined and false, but was behaving like
+      use_ext => 1
+    - allow loaders to return multiple documents as an array.
 
 0.08 Thu Aug 23 2007
-    pass config options to each parser
-    fix for loading the same perl config twice (RT #28812)
+    - pass config options to each parser
+    - fix for loading the same perl config twice (RT #28812)
 
 0.07 Mon Feb 26 2007
-    promote 0.06_01 to non-dev.
+    - promote 0.06_01 to non-dev.
 
 0.06_01 Sun Feb 25 19:23:00 2007
-    fixed bug [rt.cpan.org #25143] make tests fails
-        - t/61_features.t had 1 more test added than was set to skip if the INI parser
-          was not installed. Fixed by s/9/10/ on the skip() line.
+    - fixed bug [rt.cpan.org #25143] make tests fails
+      + t/61_features.t had 1 more test added than was set to skip if the INI
+        parser was not installed. Fixed by s/9/10/ on the skip() line.
 
 0.06 Thu Feb 22 21:05:00 2007
-    removed reference to Test::Exception, bumped version number
+    - removed reference to Test::Exception, bumped version number
 
 0.05  Wed Feb 21 22:00:00 2007
-    added support for:
-        - 'force_plugins => [ qw(Config::Any::Foo Config::Any::Blah) ]' parameter
-         to load_(files|stems)
-        - $Config::Any::INI::MAP_SECTION_SPACE_TO_NESTED_KEY - boolean, defaulting
-          to on, controlling whether to map spaces in INI section headings 
-          to nested hashrefs 
-        both as requested by Evan Kaufman      
+    - added support for (requested by Evan Kaufman):
+      + 'force_plugins => [ qw(Config::Any::Foo Config::Any::Blah) ]' parameter
+           to load_(files|stems)
+      + $Config::Any::INI::MAP_SECTION_SPACE_TO_NESTED_KEY - boolean, defaulting
+        to on, controlling whether to map spaces in INI section headings 
+        to nested hashrefs
 
 0.04  Mon Aug  7 15:15:15 2006
-    Initial CPAN-worthy release with proper test suite
+    - Initial CPAN-worthy release with proper test suite
 
 0.01 - 0.03 dev releases
 
index 07f7a9c..708936a 100644 (file)
@@ -6,7 +6,7 @@ use warnings;
 use Carp;
 use Module::Pluggable::Object ();
 
-our $VERSION = '0.09';
+our $VERSION = '0.09_01';
 
 =head1 NAME
 
@@ -129,64 +129,70 @@ sub load_stems {
     return $class->_load( $args );
 }
 
-# this is where we do the real work
-# it's a private class-method because users should use the interface described
-# in the POD.
 sub _load {
     my ( $class, $args ) = @_;
-    my ( $files_ref, $filter_cb, $use_ext, $force_plugins_ref )
-        = @{ $args }{ qw(files filter use_ext force_plugins) };
-    croak "_load requires a arrayref of file paths" unless defined $files_ref;
-
-    my %files         = map { $_ => 1 } @$files_ref;
-    my %force_plugins = map { $_ => 1 } @$force_plugins_ref;
-    my $enforcing = keys %force_plugins ? 1 : 0;
-
-    my $final_configs     = [];
-    my $originally_loaded = {};
-
-    # perform a separate file loop for each loader
-    for my $loader ( $class->plugins ) {
-        next if $enforcing && not defined $force_plugins{ $loader };
-        last unless keys %files;
-        my %ext = map { $_ => 1 } $loader->extensions;
-
-        my ( $loader_class ) = $loader =~ /::([^:]+)$/;
-        my $driver_args = $args->{ driver_args }{ $loader_class } || {};
-
-    FILE:
-        for my $filename ( keys %files ) {
-            next unless -f $filename;
-
-       # use file extension to decide whether this loader should try this file
-       # use_ext => 1 hits this block
-            if ( defined $use_ext && !$enforcing ) {
-                my $matched_ext = 0;
-            EXT:
-                for my $e ( keys %ext ) {
-                    next EXT unless $filename =~ m{ \. $e \z }xms;
-                    next FILE unless exists $ext{ $e };
-                    $matched_ext = 1;
-                }
-
-                next FILE unless $matched_ext;
-            }
+    croak "_load requires a arrayref of file paths" unless $args->{ files };
+
+    if( !defined $args->{ use_ext } ) {
+        warn "use_ext argument was not explicitly set, as of 0.09, this is true by default";
+        $args->{ use_ext } = 1;
+    }
+
+    # figure out what plugins we're using
+    my $force   = defined $args->{ force_plugins };
+    my @plugins = $force ? @{ $args->{ force_plugins } } : $class->plugins;
+
+    # map extensions if we have to
+    my( %extension_lut, $extension_re );
+    my $use_ext_lut = !$force && $args->{ use_ext };
+    if( $use_ext_lut ) {
+        for my $plugin ( @plugins ) {
+            $extension_lut{ $_ } = $plugin for $plugin->extensions;
+        }
+
+        $extension_re = join( '|', keys %extension_lut );
+    }
 
-            my $config;
-            eval { $config = $loader->load( $filename, $driver_args ); };
+    # map args to plugins
+    my $base_class = __PACKAGE__;
+    my %loader_args;
+    for my $plugin ( @plugins ) {
+        $plugin =~ m{^$base_class\::(.+)};
+        $loader_args{ $plugin } = $args->{ driver_args }->{ $1 } || {};
+    }
+
+    my @results;
+
+    for my $filename ( @{ $args->{ files } } ) {
+        # don't even bother if it's not there
+        next unless -f $filename;
+
+        my @try_plugins = @plugins;
 
-            next if $@;         # if it croaked or warned, we can't use it
-            next if !$config;
-            delete $files{ $filename };
+        if( $use_ext_lut ) {
+            $filename =~ m{\.($extension_re)\z};
+            next unless $1;
+            @try_plugins = $extension_lut{ $1 };
+        }
+
+        for my $loader ( @try_plugins ) {
+            my @configs = eval { $loader->load( $filename, $loader_args{ $loader } ); };
 
-            # post-process config with a filter callback, if we got one
-            $filter_cb->( $config ) if defined $filter_cb;
+            # fatal error if we used extension matching
+            croak "Error parsing file: $filename" if $@ and $use_ext_lut;
+            next if $@ or !@configs;
+
+            # post-process config with a filter callback
+            if ( $args->{ filter } ) {
+                $args->{ filter }->( $_ ) for @configs;
+            }
 
-            push @$final_configs, { $filename => $config };
+            push @results, { $filename => @configs == 1 ? $configs[ 0 ] : \@configs };
+            last;
         }
     }
 
-    return $final_configs;
+    return \@results;
 }
 
 =head2 finder( )
index 0b39af2..bae5fff 100644 (file)
@@ -70,23 +70,15 @@ sub _test_perl {
 
 =head1 AUTHOR
 
-=over 4 
-
-=item * Brian Cassidy E<lt>bricas@cpan.orgE<gt>
-
-=back
+Brian Cassidy E<lt>bricas@cpan.orgE<gt>
 
 =head1 CONTRIBUTORS
 
-=over 4
-
-=item * Joel Bernstein C<< <rataxis@cpan.org> >>
-
-=back
+Joel Bernstein C<< <rataxis@cpan.org> >>
 
 =head1 COPYRIGHT AND LICENSE
 
-Copyright 2006 by Brian Cassidy
+Copyright 2007 by Brian Cassidy
 
 Portions Copyright 2006 Portugal Telecom
 
index ea2abce..1d0575e 100644 (file)
@@ -84,19 +84,15 @@ Set it to 0 to preserve literal spaces in section headings:
 
 =back
 
-=head1 AUTHOR
+=head1 AUTHORS
 
-=over 4 
-
-=item * Brian Cassidy E<lt>bricas@cpan.orgE<gt>
+Brian Cassidy E<lt>bricas@cpan.orgE<gt>
 
-=item * Joel Bernstein E<lt>rataxis@cpan.orgE<gt>
-
-=back
+Joel Bernstein E<lt>rataxis@cpan.orgE<gt>
 
 =head1 COPYRIGHT AND LICENSE
 
-Copyright 2006 by Brian Cassidy, portions copyright 2006, 2007 by Joel Bernstein
+Copyright 2007 by Brian Cassidy, portions copyright 2006, 2007 by Joel Bernstein
 
 This library is free software; you can redistribute it and/or modify
 it under the same terms as Perl itself. 
index 5e4edf3..18b201f 100644 (file)
@@ -59,15 +59,11 @@ sub load {
 
 =head1 AUTHOR
 
-=over 4 
-
-=item * Brian Cassidy E<lt>bricas@cpan.orgE<gt>
-
-=back
+Brian Cassidy E<lt>bricas@cpan.orgE<gt>
 
 =head1 COPYRIGHT AND LICENSE
 
-Copyright 2006 by Brian Cassidy
+Copyright 2007 by Brian Cassidy
 
 This library is free software; you can redistribute it and/or modify
 it under the same terms as Perl itself. 
index 5d8e0a5..ed3752b 100644 (file)
@@ -56,15 +56,11 @@ sub load {
 
 =head1 AUTHOR
 
-=over 4 
-
-=item * Brian Cassidy E<lt>bricas@cpan.orgE<gt>
-
-=back
+Brian Cassidy E<lt>bricas@cpan.orgE<gt>
 
 =head1 COPYRIGHT AND LICENSE
 
-Copyright 2006 by Brian Cassidy
+Copyright 2007 by Brian Cassidy
 
 This library is free software; you can redistribute it and/or modify
 it under the same terms as Perl itself. 
index a5fc881..9c49443 100644 (file)
@@ -73,19 +73,15 @@ sub _coerce {
     $out;
 }
 
-=head1 AUTHOR
+=head1 AUTHORS
 
-=over 4 
-
-=item * Brian Cassidy E<lt>bricas@cpan.orgE<gt>
+Brian Cassidy E<lt>bricas@cpan.orgE<gt>
 
-=item * Joel Bernstein E<lt>rataxis@cpan.orgE<gt>
-
-=back
+Joel Bernstein E<lt>rataxis@cpan.orgE<gt>
 
 =head1 COPYRIGHT AND LICENSE
 
-Copyright 2006 by Brian Cassidy
+Copyright 2007 by Brian Cassidy
 
 This library is free software; you can redistribute it and/or modify
 it under the same terms as Perl itself. 
index 46e4d1e..594fecb 100644 (file)
@@ -56,15 +56,11 @@ sub load {
 
 =head1 AUTHOR
 
-=over 4 
-
-=item * Brian Cassidy E<lt>bricas@cpan.orgE<gt>
-
-=back
+Brian Cassidy E<lt>bricas@cpan.orgE<gt>
 
 =head1 COPYRIGHT AND LICENSE
 
-Copyright 2006 by Brian Cassidy
+Copyright 2007 by Brian Cassidy
 
 This library is free software; you can redistribute it and/or modify
 it under the same terms as Perl itself. 
diff --git a/t/62-multi.t b/t/62-multi.t
new file mode 100644 (file)
index 0000000..b8b9d7e
--- /dev/null
@@ -0,0 +1,28 @@
+use Test::More tests => 3;
+
+use strict;
+use warnings;
+
+use Config::Any;
+use Config::Any::YAML;
+
+my $file   = 't/multi/conf.yml';
+my @expect = (
+    {   name  => 'TestApp',
+        Model => { 'Model::Baz' => { qux => 'xyzzy' } }
+    },
+    {   name2  => 'TestApp2',
+        Model2 => { 'Model::Baz2' => { qux2 => 'xyzzy2' } }
+    },
+);
+
+my @results = eval { Config::Any::YAML->load( $file ); };
+
+SKIP: {
+    skip "Can't load YAML files", 3 if $@;
+    is( @results, 2, '2 documents' );
+    is_deeply( \@results, \@expect, 'structures ok' );
+
+    my $return = Config::Any->load_files( { use_ext => 1, files => [ $file ] } );
+    is_deeply( $return, [ { $file => \@expect } ], 'config-any structures ok' );
+}
diff --git a/t/multi/conf.yml b/t/multi/conf.yml
new file mode 100644 (file)
index 0000000..c6c23ca
--- /dev/null
@@ -0,0 +1,11 @@
+---
+name: TestApp
+Model:
+    Model::Baz:
+        qux: xyzzy
+---
+name2: TestApp2
+Model2:
+    Model::Baz2:
+        qux2: xyzzy2
+