From: Brian Cassidy Date: Tue, 13 Nov 2007 15:21:57 +0000 (+0000) Subject: refactor _load(). fix an issue with use_ext => 0. use_ext now on by default. throw... X-Git-Tag: v0.09_01~5 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=p5sagit%2FConfig-Any.git;a=commitdiff_plain;h=a918b0b8b7952db918dfabb8dc72bf34832d43d0;hp=7c2181827882c125de98ccbe16402f5b277a3f44 refactor _load(). fix an issue with use_ext => 0. use_ext now on by default. throw errors when use_ext => 1. allow multi-stream configs. pod updates --- diff --git a/Changes b/Changes index ce9363b..1b5e0e9 100644 --- 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 diff --git a/lib/Config/Any.pm b/lib/Config/Any.pm index 07f7a9c..708936a 100644 --- a/lib/Config/Any.pm +++ b/lib/Config/Any.pm @@ -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( ) diff --git a/lib/Config/Any/General.pm b/lib/Config/Any/General.pm index 0b39af2..bae5fff 100644 --- a/lib/Config/Any/General.pm +++ b/lib/Config/Any/General.pm @@ -70,23 +70,15 @@ sub _test_perl { =head1 AUTHOR -=over 4 - -=item * Brian Cassidy Ebricas@cpan.orgE - -=back +Brian Cassidy Ebricas@cpan.orgE =head1 CONTRIBUTORS -=over 4 - -=item * Joel Bernstein C<< >> - -=back +Joel Bernstein C<< >> =head1 COPYRIGHT AND LICENSE -Copyright 2006 by Brian Cassidy +Copyright 2007 by Brian Cassidy Portions Copyright 2006 Portugal Telecom diff --git a/lib/Config/Any/INI.pm b/lib/Config/Any/INI.pm index ea2abce..1d0575e 100644 --- a/lib/Config/Any/INI.pm +++ b/lib/Config/Any/INI.pm @@ -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 Ebricas@cpan.orgE +Brian Cassidy Ebricas@cpan.orgE -=item * Joel Bernstein Erataxis@cpan.orgE - -=back +Joel Bernstein Erataxis@cpan.orgE =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. diff --git a/lib/Config/Any/JSON.pm b/lib/Config/Any/JSON.pm index 5e4edf3..18b201f 100644 --- a/lib/Config/Any/JSON.pm +++ b/lib/Config/Any/JSON.pm @@ -59,15 +59,11 @@ sub load { =head1 AUTHOR -=over 4 - -=item * Brian Cassidy Ebricas@cpan.orgE - -=back +Brian Cassidy Ebricas@cpan.orgE =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/lib/Config/Any/Perl.pm b/lib/Config/Any/Perl.pm index 5d8e0a5..ed3752b 100644 --- a/lib/Config/Any/Perl.pm +++ b/lib/Config/Any/Perl.pm @@ -56,15 +56,11 @@ sub load { =head1 AUTHOR -=over 4 - -=item * Brian Cassidy Ebricas@cpan.orgE - -=back +Brian Cassidy Ebricas@cpan.orgE =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/lib/Config/Any/XML.pm b/lib/Config/Any/XML.pm index a5fc881..9c49443 100644 --- a/lib/Config/Any/XML.pm +++ b/lib/Config/Any/XML.pm @@ -73,19 +73,15 @@ sub _coerce { $out; } -=head1 AUTHOR +=head1 AUTHORS -=over 4 - -=item * Brian Cassidy Ebricas@cpan.orgE +Brian Cassidy Ebricas@cpan.orgE -=item * Joel Bernstein Erataxis@cpan.orgE - -=back +Joel Bernstein Erataxis@cpan.orgE =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/lib/Config/Any/YAML.pm b/lib/Config/Any/YAML.pm index 46e4d1e..594fecb 100644 --- a/lib/Config/Any/YAML.pm +++ b/lib/Config/Any/YAML.pm @@ -56,15 +56,11 @@ sub load { =head1 AUTHOR -=over 4 - -=item * Brian Cassidy Ebricas@cpan.orgE - -=back +Brian Cassidy Ebricas@cpan.orgE =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 index 0000000..b8b9d7e --- /dev/null +++ b/t/62-multi.t @@ -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 index 0000000..c6c23ca --- /dev/null +++ b/t/multi/conf.yml @@ -0,0 +1,11 @@ +--- +name: TestApp +Model: + Model::Baz: + qux: xyzzy +--- +name2: TestApp2 +Model2: + Model::Baz2: + qux2: xyzzy2 +