MooX-ConfigFromFile-0.007/000755 000765 000024 00000000000 12517450274 015202 5ustar00snostaff000000 000000 MooX-ConfigFromFile-0.007/calc/000755 000765 000024 00000000000 12517450274 016104 5ustar00snostaff000000 000000 MooX-ConfigFromFile-0.007/Changes000644 000765 000024 00000003047 12517430767 016506 0ustar00snostaff000000 000000 Revision history for MooX-ConfigFromFile 0.007 2015-04-27 - separate loading and merging of configfile content - ensure order of multiple loaded config files - add support for merging deep structures in config files - eval all test-libraries to be aware of mistakes 0.006 2015-03-04 - add rough support for multiple prefixes - fix incorrect meta-data and incomplete handling of newer eumm features - improve test coverage - simplify some code to avoid useless conditions - add new tests for MooX::Cmd and MooX::Options integration - introduce import setting for config_identifier (consumed attribute from MooX::File::ConfigDir) - bump copyright year to 2015 0.005 2014-12-01 - Update Makefile.PL for up-to-date resources and requirements spec - consolidate Synopsis in main pod - move from README to README.md - improve author tests before releasing 0.004 2014-10-28 - add ability for options to importer of MooX::ConfigFromFile - add option to have a singleton config (loaded once). - improve documentation - harmonize tests 0.003 2014-08-02 - fix links in documentation to fix RT#97429 (thanks abraxxa for reporting) - switch to ExtUtils::MakeMaker - it better maintained these days 0.002 2013-09-27 - improve documentation - add test to verify we're working on Moose, too - ensure we're only $with->() for classes, not roles - add a Build.PL auto_feature for author test requires 0.001 2013-09-26 - First version, released on an unsuspecting world. MooX-ConfigFromFile-0.007/etc/000755 000765 000024 00000000000 12517450274 015755 5ustar00snostaff000000 000000 MooX-ConfigFromFile-0.007/lib/000755 000765 000024 00000000000 12517450274 015750 5ustar00snostaff000000 000000 MooX-ConfigFromFile-0.007/Makefile.PL000644 000765 000024 00000011657 12517424400 017156 0ustar00snostaff000000 000000 use strict; use warnings; use 5.008001; use ExtUtils::MakeMaker; my %RUN_DEPS = ( "Config::Any" => 0, "File::Find::Rule" => "0.30", "FindBin" => 0, "Moo" => "1.003", "MooX::File::ConfigDir" => "0.002", ); my %CONFIGURE_DEPS = ( 'ExtUtils::MakeMaker' => 0, ); my %BUILD_DEPS = (); my %TEST_DEPS = ( 'Cwd' => 0, 'File::Basename' => 0, 'File::Spec' => 0, 'Hash::Merge' => 0, 'JSON' => 0, 'Test::More' => 0.90, ); WriteMakefile1( MIN_PERL_VERSION => '5.008001', META_ADD => { 'meta-spec' => { version => 2 }, resources => { homepage => 'https://metacpan.org/release/MooX-ConfigFromFile', repository => { url => 'https://github.com:rehsack/MooX-ConfigFromFile.git', web => 'https://github.com/rehsack/MooX-ConfigFromFile', type => 'git', }, bugtracker => { web => 'http://rt.cpan.org/Public/Dist/Display.html?Name=MooX-ConfigFromFile', mailto => 'bug-MooX-ConfigFromFile@rt.cpan.org', }, license => 'http://dev.perl.org/licenses/', }, prereqs => { develop => { requires => { 'Test::CPAN::Changes' => 0, 'Test::CheckManifest' => 0, 'Module::CPANTS::Analyse' => '0.96', 'Test::Kwalitee' => 0, 'Test::Pod' => 0, 'Test::Pod::Coverage' => 0, 'Test::Pod::Spelling::CommonMistakes' => 0, 'Test::Spelling' => 0, }, }, configure => { requires => {%CONFIGURE_DEPS}, }, build => { requires => {%BUILD_DEPS} }, test => { requires => {%TEST_DEPS}, suggests => { 'MooX::Cmd' => '0.012', 'MooX::Options' => '4.001' } }, runtime => { requires => { %RUN_DEPS, perl => '5.8.1', }, suggests => { "Hash::Merge" => 0, } }, }, }, NAME => 'MooX::ConfigFromFile', VERSION_FROM => 'lib/MooX/ConfigFromFile.pm', ABSTRACT_FROM => 'lib/MooX/ConfigFromFile.pm', LICENSE => 'perl', AUTHOR => q{Jens Rehsack }, PREREQ_PM => \%RUN_DEPS, CONFIGURE_REQUIRES => \%CONFIGURE_DEPS, BUILD_REQUIRES => \%BUILD_DEPS, TEST_REQUIRES => \%TEST_DEPS, test => { TESTS => 't/*.t xt/*.t' }, ); sub WriteMakefile1 { # originally written by Alexandr Ciornii, version 0.21. Added by eumm-upgrade. my %params = @_; my $eumm_version = $ExtUtils::MakeMaker::VERSION; $eumm_version = eval $eumm_version; die "EXTRA_META is deprecated" if ( exists( $params{EXTRA_META} ) ); die "License not specified" if ( !exists( $params{LICENSE} ) ); $params{TEST_REQUIRES} and $eumm_version < 6.6303 and $params{BUILD_REQUIRES} = { %{ $params{BUILD_REQUIRES} || {} }, %{ delete $params{TEST_REQUIRES} } }; #EUMM 6.5502 has problems with BUILD_REQUIRES $params{BUILD_REQUIRES} and $eumm_version < 6.5503 and $params{PREREQ_PM} = { %{ $params{PREREQ_PM} || {} }, %{ delete $params{BUILD_REQUIRES} } }; ref $params{AUTHOR} and "ARRAY" eq ref $params{AUTHOR} and $eumm_version < 6.5702 and $params{AUTHOR} = join( ", ", @{ $params{AUTHOR} } ); delete $params{CONFIGURE_REQUIRES} if ( $eumm_version < 6.52 ); delete $params{MIN_PERL_VERSION} if ( $eumm_version < 6.48 ); delete $params{META_MERGE} if ( $eumm_version < 6.46 ); delete $params{META_ADD}{prereqs} if ( $eumm_version < 6.58 ); delete $params{META_ADD}{'meta-spec'} if ( $eumm_version < 6.58 ); delete $params{META_ADD} if ( $eumm_version < 6.46 ); delete $params{LICENSE} if ( $eumm_version < 6.31 ); delete $params{AUTHOR} if ( $] < 5.005 ); delete $params{ABSTRACT_FROM} if ( $] < 5.005 ); delete $params{BINARY_LOCATION} if ( $] < 5.005 ); # more or less taken from Moose' Makefile.PL if ( $params{CONFLICTS} ) { my $ok = CheckConflicts(%params); exit(0) if ( $params{PREREQ_FATAL} and not $ok ); my $cpan_smoker = grep { $_ =~ m/(?:CR_SMOKER|CPAN_REPORTER|AUTOMATED_TESTING)/ } keys %ENV; unless ( $cpan_smoker || $ENV{PERL_MM_USE_DEFAULT} ) { sleep 4 unless ($ok); } delete $params{CONFLICTS}; } WriteMakefile(%params); } MooX-ConfigFromFile-0.007/MANIFEST000644 000765 000024 00000001557 12517450275 016344 0ustar00snostaff000000 000000 calc/etc/large-operands.json calc/etc/operands.json calc/etc/small-operands.json Changes etc/calc-operands.json etc/MooXCmdTest-test-this-hashmerged.json etc/MooXCmdTest-test-this.json etc/MooXCmdTest-test.json etc/MooXCmdTest.json etc/MooXCmdTest.test.this.json etc/MooXCmdTest.tested.json lib/MooX/ConfigFromFile.pm lib/MooX/ConfigFromFile/Role.pm lib/MooX/ConfigFromFile/Role/HashMergeLoaded.pm Makefile.PL MANIFEST MANIFEST.SKIP README.md t/00-load.t t/01-moo.t t/02-moose.t t/lib/MooXCmdTest.pm t/lib/MooXCmdTest/Cmd/Test.pm t/lib/MooXCmdTest/Cmd/Test/Cmd/This.pm t/lib/MooXCmdTest/Cmd/Test/Cmd/This/Cmd/HashMerged.pm t/lib/MooXCmdTest/Cmd/Tested.pm t/testerr.pm t/testlib.pm t/testmxcmd.pm t/testmxopt.pm META.yml Module YAML meta-data (added by MakeMaker) META.json Module JSON meta-data (added by MakeMaker) MooX-ConfigFromFile-0.007/MANIFEST.SKIP000644 000765 000024 00000000506 12475034651 017101 0ustar00snostaff000000 000000 \B\.svn\b \B\.git\b \.gitignore$ \.[Bb][Aa][Kk]$ \.orig$ \.old$ \.tdy$ \.tmp$ \..*swp ^Makefile$ ^Build$ ^Build\.bat$ \.Inline/.* _Inline/.* \.bak$ \.tar$ \.tgz$ \.tar\.gz$ ^mess/ ^tmp/ ^testdata/ ^blib/ ^sandbox/ ^pm_to_blib$ ^cover_db/ ^_build/.* ~$ .*\.planner ^\..* MooX-ConfigFromFile-.* \bxt ^MYMETA\.json$ ^MYMETA\..*$ MooX-ConfigFromFile-0.007/META.json000644 000765 000024 00000004531 12517450274 016626 0ustar00snostaff000000 000000 { "abstract" : "Moo eXtension for initializing objects from config file", "author" : [ "Jens Rehsack " ], "dynamic_config" : 1, "generated_by" : "ExtUtils::MakeMaker version 7.04, CPAN::Meta::Converter version 2.150001", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : "2" }, "name" : "MooX-ConfigFromFile", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : {} }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "develop" : { "requires" : { "Module::CPANTS::Analyse" : "0.96", "Test::CPAN::Changes" : "0", "Test::CheckManifest" : "0", "Test::Kwalitee" : "0", "Test::Pod" : "0", "Test::Pod::Coverage" : "0", "Test::Pod::Spelling::CommonMistakes" : "0", "Test::Spelling" : "0" } }, "runtime" : { "requires" : { "Config::Any" : "0", "File::Find::Rule" : "0.30", "FindBin" : "0", "Moo" : "1.003", "MooX::File::ConfigDir" : "0.002", "perl" : "v5.8.1" }, "suggests" : { "Hash::Merge" : "0" } }, "test" : { "requires" : { "Cwd" : "0", "File::Basename" : "0", "File::Spec" : "0", "Hash::Merge" : "0", "JSON" : "0", "Test::More" : "0.9" }, "suggests" : { "MooX::Cmd" : "0.012", "MooX::Options" : "4.001" } } }, "release_status" : "stable", "resources" : { "bugtracker" : { "mailto" : "bug-MooX-ConfigFromFile@rt.cpan.org", "web" : "http://rt.cpan.org/Public/Dist/Display.html?Name=MooX-ConfigFromFile" }, "homepage" : "https://metacpan.org/release/MooX-ConfigFromFile", "license" : [ "http://dev.perl.org/licenses/" ], "repository" : { "type" : "git", "url" : "https://github.com:rehsack/MooX-ConfigFromFile.git", "web" : "https://github.com/rehsack/MooX-ConfigFromFile" } }, "version" : "0.007" } MooX-ConfigFromFile-0.007/META.yml000644 000765 000024 00000001716 12517450274 016460 0ustar00snostaff000000 000000 --- abstract: 'Moo eXtension for initializing objects from config file' author: - 'Jens Rehsack ' build_requires: Cwd: '0' File::Basename: '0' File::Spec: '0' Hash::Merge: '0' JSON: '0' Test::More: '0.9' configure_requires: ExtUtils::MakeMaker: '0' dynamic_config: 1 generated_by: 'ExtUtils::MakeMaker version 7.04, CPAN::Meta::Converter version 2.150001' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: MooX-ConfigFromFile no_index: directory: - t - inc requires: Config::Any: '0' File::Find::Rule: '0.30' FindBin: '0' Moo: '1.003' MooX::File::ConfigDir: '0.002' perl: v5.8.1 resources: bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=MooX-ConfigFromFile homepage: https://metacpan.org/release/MooX-ConfigFromFile license: http://dev.perl.org/licenses/ repository: https://github.com:rehsack/MooX-ConfigFromFile.git version: '0.007' MooX-ConfigFromFile-0.007/README.md000644 000765 000024 00000003163 12435065614 016463 0ustar00snostaff000000 000000 ## Name MooX::ConfigFromFile - Moo eXtension for initializing objects from config file ## Description This module is intended to easy load initialization values for attributes on object construction from an appropriate config file. The building is done in MooX::ConfigFromFile::Role - using MooX::ConfigFromFile ensures the role is applied. ## Author Jens Rehsack, "" ## BUGS Please report any bugs or feature requests to "bug-moox-configfromfile at rt.cpan.org", or through the web interface at . I will be notified, and then you'll automatically be notified of progress on your bug as I make changes. ## Support You can find documentation for this module with the perldoc command. perldoc MooX::ConfigFromFile You can also look for information at: * RT: CPAN's request tracker (report bugs here) * AnnoCPAN: Annotated CPAN documentation * CPAN Ratings * Search CPAN ## License And Copyright Copyright 2013-2014 Jens Rehsack. This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License. See for more information. MooX-ConfigFromFile-0.007/t/000755 000765 000024 00000000000 12517450274 015445 5ustar00snostaff000000 000000 MooX-ConfigFromFile-0.007/t/00-load.t000644 000765 000024 00000000411 12475064501 016757 0ustar00snostaff000000 000000 #!perl use 5.008001; use strict; use warnings FATAL => 'all'; use Test::More; use Moo; BEGIN { use_ok( 'MooX::ConfigFromFile' ) || print "Bail out!\n"; } diag( "Testing MooX::ConfigFromFile $MooX::ConfigFromFile::VERSION, Perl $], $^X" ); done_testing(); MooX-ConfigFromFile-0.007/t/01-moo.t000644 000765 000024 00000000537 12517411761 016645 0ustar00snostaff000000 000000 #!perl use 5.008001; use strict; use warnings FATAL => 'all'; use Test::More; our $OO = "Moo"; eval "do 't/testerr.pm'"; eval "do 't/testlib.pm'"; eval "use MooX::Cmd 0.012; do 't/testmxcmd.pm'"; eval "{package MooX::ConfigFromFile::Test::Availability::Of::MooX::Options; use Moo; use MooX::Options 4.001; }; do 't/testmxopt.pm'"; done_testing; MooX-ConfigFromFile-0.007/t/02-moose.t000644 000765 000024 00000000752 12517412242 017170 0ustar00snostaff000000 000000 #!perl use 5.008001; use strict; use warnings FATAL => 'all'; use Test::More; BEGIN { eval "use Moose;"; $@ and plan skip_all => "Moose test requires Moose being installed"; } our $OO = "Moose"; $ENV{WHICH_MOODEL} = "Moose"; eval "do 't/testerr.pm'"; eval "do 't/testlib.pm'"; eval "use MooX::Cmd 0.012; do 't/testmxcmd.pm'"; eval "{package MooX::ConfigFromFile::Test::Availability::Of::MooX::Options; use $OO; use MooX::Options 4.001; }; do 't/testmxopt.pm'"; done_testing; MooX-ConfigFromFile-0.007/t/lib/000755 000765 000024 00000000000 12517450274 016213 5ustar00snostaff000000 000000 MooX-ConfigFromFile-0.007/t/testerr.pm000644 000765 000024 00000001151 12475544155 017476 0ustar00snostaff000000 000000 use strict; use warnings FATAL => "all"; require Role::Tiny; eval sprintf( <<'EOCDECL', ($main::OO) x 1 ); { package # Must::Fail; use MooX::ConfigFromFile; sub new { bless {}, shift } } { package # Already::There; use %s; sub _initialize_from_config {} use MooX::ConfigFromFile; } EOCDECL note $main::OO; my $mf = Must::Fail->new; ok( !$mf->can("_initialize_from_config"), "Failed to apply MooX::ConfigFromFile::Role" ); my $ar = Already::There->new; ok( !Role::Tiny::does_role( $ar, "MooX::ConfigFromFile::Role" ), "Skipped applying MooX::ConfigFromFile::Role" ); MooX-ConfigFromFile-0.007/t/testlib.pm000644 000765 000024 00000010224 12517412154 017443 0ustar00snostaff000000 000000 use strict; use warnings FATAL => "all"; use FindBin; eval sprintf( <<'EOCDECL', ($main::OO) x 6 ); { package # Calc::Role::BinaryOperation; use %s::Role; has a => ( is => "ro", required => 1, ); has b => ( is => "ro", required => 1, ); } { package # Calc::add; use %s; use MooX::ConfigFromFile; with "Calc::Role::BinaryOperation"; sub execute { my $self = shift; return $self->a + $self->b; } } { package # Calc::sub; use %s; use MooX::ConfigFromFile config_prefix => "calc-operands"; with "Calc::Role::BinaryOperation"; sub execute { my $self = shift; return $self->a - $self->b; } } { package # Calc::mul; use %s; use MooX::ConfigFromFile config_prefix => "calc-operands", config_singleton => 1; with "Calc::Role::BinaryOperation"; sub execute { my $self = shift; return $self->a * $self->b; } } { package # Calc::div; use %s; use MooX::ConfigFromFile config_singleton => 0; with "Calc::Role::BinaryOperation"; around BUILDARGS => sub { my $next = shift; my $class = shift; my $a = shift; my $b = shift; my $loaded_config = { a => $a, b => $b }; $class->$next( loaded_config => $loaded_config, ); }; sub execute { my $self = shift; return $self->a / $self->b; } } { package # Dumb::Cfg; use %s; use MooX::ConfigFromFile; sub execute { return; } } EOCDECL # This is for warn once note $main::OO; my $adder = Calc::add->new( config_prefix => "calc-operands" ); ok( defined( $adder->a ), "read \"a\" from add config" ); ok( defined( $adder->b ), "read \"b\" from add config" ); cmp_ok( $adder->execute, "==", 5, "read right adder config" ); ok( Moo::Role::does_role( $adder, "MooX::ConfigFromFile::Role" ), "Applying MooX::ConfigFromFile::Role" ); foreach my $copy_attr ( map { "config_$_" } qw(extensions dirs prefix_map_separator prefixes prefix_map files_pattern files) ) { my $subber = Calc::sub->new( $copy_attr => $adder->$copy_attr ); ok( defined( $subber->a ), "read \"a\" from sub config using $copy_attr" ); ok( defined( $subber->b ), "read \"b\" from sub config using $copy_attr" ); cmp_ok( $subber->execute, "==", -1, "read right subber config using $copy_attr" ); } my $secsub = Calc::sub->new( raw_loaded_config => [ { t => { b => 2, a => 4 } } ]); ok( defined( $secsub->a ), "read \"a\" from sub config" ); ok( defined( $secsub->b ), "read \"b\" from sub config" ); cmp_ok( $secsub->execute, "==", 2, "use right secsub config" ); ok( Moo::Role::does_role( $secsub, "MooX::ConfigFromFile::Role" ), "Applying MooX::ConfigFromFile::Role" ); my $mul1 = Calc::mul->new( b => 4 ); ok( defined( $mul1->a ), "read \"a\" from mul1 config" ); ok( defined( $mul1->b ), "read \"b\" from mul1 config" ); cmp_ok( $mul1->execute, "==", 8, "read right mul config" ); my $mul2 = Calc::mul->new( config_prefix => "no-calc-operands" ); ok( defined( $mul2->a ), "copy \"a\" from mul1 config" ); ok( defined( $mul2->b ), "copy \"b\" from mul1 config" ); cmp_ok( $mul2->execute, "==", 6, "right mul2 config duplicated" ); my $mul3 = $mul2->new; cmp_ok( $mul3->execute, "==", 6, "right mul3 config duplicated" ); my $div1 = Calc::div->new( 12, 3 ); ok( defined( $div1->a ), "read \"a\" from div1 config" ); ok( defined( $div1->b ), "read \"b\" from div1 config" ); cmp_ok( $div1->execute, "==", 4, "read right div1 config" ); my $div2 = Calc::div->new( 12, 6 ); ok( defined( $div2->a ), "read \"a\" from div2 config" ); ok( defined( $div2->b ), "read \"b\" from div2 config" ); cmp_ok( $div2->execute, "==", 2, "read right div2 config" ); my $dumb = Dumb::Cfg->new( config_dirs => 1 ); isa_ok( $dumb, "Dumb::Cfg" ); is( $dumb->config_prefix, $FindBin::Script, "fallback config prefix" ); is_deeply( $dumb->config_dirs, [qw(.)], "fallback config dirs" ); is_deeply( $dumb->config_prefixes, [$FindBin::Script], "fallback config prefix" ); MooX-ConfigFromFile-0.007/t/testmxcmd.pm000644 000765 000024 00000003343 12517444031 020010 0ustar00snostaff000000 000000 use MooX::Cmd::Tester; use FindBin qw($Bin); use lib "$Bin/lib"; use MooXCmdTest; my @tests = ( [ [], "MooXCmdTest", "MooXCmdTest", { complicated_setting => { say => "Hello!" } } ], [ [qw(test)], "MooXCmdTest", "MooXCmdTest::Cmd::Test", { unintialized_attribute => sub { time - $_[0] < 1 } } ], [ [qw(tested)], "MooXCmdTest", "MooXCmdTest::Cmd::Tested", { confidential_setting => 42 } ], [ [qw(test this)], "MooXCmdTest", "MooXCmdTest::Cmd::Test::Cmd::This", { dedicated_setting => 4711 } ], [ [qw(test this hashmerged)], "MooXCmdTest", "MooXCmdTest::Cmd::Test::Cmd::This::Cmd::HashMerged", { dedicated_setting => 4711, merged_frame => { kept_value => "sane", "overwritten_value" => "dammed" } } ], ); for (@tests) { SKIP: { my ( $args, $class, $cmd_class, $attrs ) = @{$_}; ref $args or $args = [ split( ' ', $args ) ]; my $rv = test_cmd( $class => $args ); #diag(explain($rv)); my $test_ident = "$class => " . join( " ", "[", @$args, "]" ); ok( $rv->cmd, "got cmd for $test_ident" ) or diag( explain($rv) ); isa_ok( $rv->cmd, $class ) or skip( "Cannot do attribute testing without command", 2 ); isa_ok( $rv->cmd->command_chain_end, $cmd_class ) or skip( "Cannot do attribute testing without specific command", 1 ) if scalar @$args; my $cmd = scalar @$args ? $rv->cmd->command_chain_end : $rv->cmd; foreach my $k ( keys %$attrs ) { my $cmd_attr = $cmd->$k; ref $attrs->{$k} or is( $attrs->{$k}, $cmd_attr, "Attribute $k for $test_ident" ); "CODE" eq ref $attrs->{$k} and ok( $attrs->{$k}->($cmd_attr), "Attribute $k ok for $test_ident" ); ref $attrs->{$k} and "CODE" ne ref $attrs->{$k} and is_deeply( $attrs->{$k}, $cmd_attr, "Attribute $k for $test_ident" ); } } } MooX-ConfigFromFile-0.007/t/testmxopt.pm000644 000765 000024 00000007141 12475570416 020061 0ustar00snostaff000000 000000 use strict; use warnings FATAL => "all"; use FindBin; use Cwd qw'abs_path getcwd'; use File::Spec; eval sprintf( <<'EOCDECL', ($main::OO) x 5 ); { package # oCalc::Role::BinaryOperation; use %s::Role; has a => ( is => "ro", required => 1, ); has b => ( is => "ro", required => 1, ); } { package # oCalc::add; use %s; use MooX::Options with_config_from_file => 1; with "oCalc::Role::BinaryOperation"; sub execute { my $self = shift; return $self->a + $self->b; } } { package # oCalc::sub; use %s; use MooX::Options with_config_from_file => 1; use MooX::ConfigFromFile config_identifier => "calc"; with "oCalc::Role::BinaryOperation"; sub execute { my $self = shift; return $self->a - $self->b; } } { package # oCalc::mul; use %s; use MooX::ConfigFromFile config_singleton => 1; use MooX::Options with_config_from_file => 1; with "oCalc::Role::BinaryOperation"; sub execute { my $self = shift; return $self->a * $self->b; } } { package # oCalc::div; use %s; use MooX::ConfigFromFile config_singleton => 0; use MooX::Options with_config_from_file => 1; with "oCalc::Role::BinaryOperation"; sub execute { my $self = shift; return $self->a / $self->b; } } EOCDECL # This is for warn once note $main::OO; my $cwd = abs_path(getcwd); my @cfg_files = map { ( "--config-files", File::Spec->catfile( $cwd, qw(calc etc), $_ ) ) } qw(operands.json small-operands.json large-operands.json); SCOPE: { local @ARGV = qw(--config-prefix calc-operands); my $adder = oCalc::add->new_with_options; ok( defined( $adder->a ), "read \"a\" from add config" ); ok( defined( $adder->b ), "read \"b\" from add config" ); cmp_ok( $adder->execute, "==", 5, "read right adder config" ); ok( Moo::Role::does_role( $adder, "MooX::ConfigFromFile::Role" ), "Applying MooX::ConfigFromFile::Role to oCalc::add" ); } SCOPE: { local @ARGV = qw(--config-prefix operands); my $subber = oCalc::sub->new_with_options; ok( defined( $subber->a ), "read \"a\" from sub config" ); ok( defined( $subber->b ), "read \"b\" from sub config" ); cmp_ok( $subber->execute, "==", 17, "read right subber config" ); ok( Moo::Role::does_role( $subber, "MooX::ConfigFromFile::Role" ), "Applying MooX::ConfigFromFile::Role to oCalc::sub" ); } SCOPE: { local @ARGV = @cfg_files[ 0 .. 1 ]; my $mul = oCalc::mul->new_with_options; is( $mul->a, 21,, "read \"a\" from mul config" ); is( $mul->b, 4, "read \"b\" from mul config" ); cmp_ok( $mul->execute, "==", 84, "read right mul config" ); } SCOPE: { local @ARGV = @cfg_files[ 2 .. 3 ]; my $mul = oCalc::mul->new_with_options; is( $mul->a, 21,, "keep \"a\" from first mul config" ); is( $mul->b, 4, "keep \"b\" from first mul config" ); cmp_ok( $mul->execute, "==", 84, "read right mul config" ); } SCOPE: { local @ARGV = @cfg_files[ 2 .. 3 ]; my $div = oCalc::div->new_with_options; is( $div->a, 30,, "read \"a\" from small div config" ); is( $div->b, 6, "read \"b\" from small div config" ); cmp_ok( $div->execute, "==", 5, "read right div config" ); } SCOPE: { local @ARGV = @cfg_files[ 4 .. 5 ]; my $div = oCalc::div->new_with_options; is( $div->a, 666,, "read \"a\" from large div config" ); is( $div->b, 222, "read \"b\" from large div config" ); cmp_ok( $div->execute, "==", 3, "read right div config" ); } MooX-ConfigFromFile-0.007/t/lib/MooXCmdTest/000755 000765 000024 00000000000 12517450274 020361 5ustar00snostaff000000 000000 MooX-ConfigFromFile-0.007/t/lib/MooXCmdTest.pm000644 000765 000024 00000000561 12475544155 020726 0ustar00snostaff000000 000000 package MooXCmdTest; use strict; use warnings; BEGIN { my $moodel = $ENV{WHICH_MOODEL} || "Moo"; eval "use $moodel;"; $@ and die $@; $moodel->import; } use MooX::ConfigFromFile config_prefix => "MooXCmdTest"; use MooX::Cmd with_config_from_file => 1; has complicated_setting => ( is => "ro", required => 1 ); sub execute { @_ } 1; MooX-ConfigFromFile-0.007/t/lib/MooXCmdTest/Cmd/000755 000765 000024 00000000000 12517450274 021064 5ustar00snostaff000000 000000 MooX-ConfigFromFile-0.007/t/lib/MooXCmdTest/Cmd/Test/000755 000765 000024 00000000000 12517450274 022003 5ustar00snostaff000000 000000 MooX-ConfigFromFile-0.007/t/lib/MooXCmdTest/Cmd/Test.pm000644 000765 000024 00000000603 12475544155 022345 0ustar00snostaff000000 000000 package MooXCmdTest::Cmd::Test; use strict; use warnings; BEGIN { my $moodel = $ENV{WHICH_MOODEL} || "Moo"; eval "use $moodel;"; $@ and die $@; $moodel->import; } use MooX::Cmd; has unintialized_attribute => ( is => "ro", builder => "_build_unintialized_attribute", lazy => 1 ); sub _build_unintialized_attribute { time } sub execute { @_ } 1; MooX-ConfigFromFile-0.007/t/lib/MooXCmdTest/Cmd/Tested.pm000644 000765 000024 00000001015 12475544155 022654 0ustar00snostaff000000 000000 package MooXCmdTest::Cmd::Tested; use strict; use warnings; BEGIN { my $moodel = $ENV{WHICH_MOODEL} || "Moo"; eval "use $moodel;"; $@ and die $@; $moodel->import; } use MooX::ConfigFromFile config_prefix => "MooXCmdTest", config_prefix_map_separator => "."; use MooX::Cmd with_config_from_file => 1; has confidential_setting => ( is => "ro", builder => "_build_confidential_attribute", lazy => 1, ); sub _build_confidential_attribute { time } sub execute { @_ } 1; MooX-ConfigFromFile-0.007/t/lib/MooXCmdTest/Cmd/Test/Cmd/000755 000765 000024 00000000000 12517450274 022506 5ustar00snostaff000000 000000 MooX-ConfigFromFile-0.007/t/lib/MooXCmdTest/Cmd/Test/Cmd/This/000755 000765 000024 00000000000 12517450274 023415 5ustar00snostaff000000 000000 MooX-ConfigFromFile-0.007/t/lib/MooXCmdTest/Cmd/Test/Cmd/This.pm000644 000765 000024 00000000670 12475544154 023762 0ustar00snostaff000000 000000 package MooXCmdTest::Cmd::Test::Cmd::This; use strict; use warnings; BEGIN { my $moodel = $ENV{WHICH_MOODEL} || "Moo"; eval "use $moodel;"; $@ and die $@; $moodel->import; } use MooX::ConfigFromFile config_prefix => "MooXCmdTest", config_prefix_map_separator => "."; use MooX::Cmd with_config_from_file => 1; has dedicated_setting => ( is => "ro", required => 1 ); sub execute { @_ } 1; MooX-ConfigFromFile-0.007/t/lib/MooXCmdTest/Cmd/Test/Cmd/This/Cmd/000755 000765 000024 00000000000 12517450274 024120 5ustar00snostaff000000 000000 MooX-ConfigFromFile-0.007/t/lib/MooXCmdTest/Cmd/Test/Cmd/This/Cmd/HashMerged.pm000644 000765 000024 00000001030 12517403615 026454 0ustar00snostaff000000 000000 package MooXCmdTest::Cmd::Test::Cmd::This::Cmd::HashMerged; use strict; use warnings; BEGIN { my $moodel = $ENV{WHICH_MOODEL} || "Moo"; eval "use $moodel;"; $@ and die $@; $moodel->import; } use MooX::ConfigFromFile config_prefix => "MooXCmdTest"; use MooX::Cmd with_config_from_file => 1; with "MooX::ConfigFromFile::Role::HashMergeLoaded"; has dedicated_setting => ( is => "ro", required => 1 ); has merged_frame => ( is => "ro", required => 1 ); sub execute { @_ } 1; MooX-ConfigFromFile-0.007/lib/MooX/000755 000765 000024 00000000000 12517450274 016632 5ustar00snostaff000000 000000 MooX-ConfigFromFile-0.007/lib/MooX/ConfigFromFile/000755 000765 000024 00000000000 12517450274 021463 5ustar00snostaff000000 000000 MooX-ConfigFromFile-0.007/lib/MooX/ConfigFromFile.pm000644 000765 000024 00000013073 12517427074 022027 0ustar00snostaff000000 000000 package MooX::ConfigFromFile; use strict; use warnings FATAL => 'all'; our $VERSION = '0.007'; my %loaded_configs; sub import { my ( undef, %import_options ) = @_; my $target = caller; my @target_isa; { no strict 'refs'; @target_isa = @{"${target}::ISA"} }; #don't add this to a role #ISA of a role is always empty ! ## no critic qw/ProhibitStringyEval/ @target_isa or return; my $apply_modifiers = sub { return if $target->can('_initialize_from_config'); my $with = $target->can('with'); $with->('MooX::ConfigFromFile::Role'); }; $apply_modifiers->(); my $around; defined $import_options{config_singleton} and $import_options{config_singleton} and do { $around = $target->can('around'); $around->( _build_loaded_config => sub { my $orig = shift; my $class = shift; defined $loaded_configs{$class} or $loaded_configs{$class} = $class->$orig(@_); return $loaded_configs{$class}; } ); }; my %default_modifiers = ( config_prefix => '_build_config_prefix', config_identifier => '_build_config_identifier', config_prefix_map_separator => '_build_config_prefix_map_separator', config_extensions => '_build_config_extensions', config_dirs => '_build_config_dirs', config_files => '_build_config_files', ); foreach my $opt_key ( keys %default_modifiers ) { exists $import_options{$opt_key} or next; $around or $around = $target->can('around'); $around->( $default_modifiers{$opt_key} => sub { $import_options{$opt_key} } ); } return; } =head1 NAME MooX::ConfigFromFile - Moo eXtension for initializing objects from config file =head1 SYNOPSIS package Role::Action; use Moo::Role; has operator => ( is => "ro" ); package Action; use Moo; use MooX::ConfigFromFile; # imports the MooX::ConfigFromFile::Role with "Role::Action"; sub operate { return say shift->operator; } package OtherAction; use Moo; with "Role::Action", "MooX::ConfigFromFile::Role"; sub operate { return warn shift->operator; } package QuiteOtherOne; use Moo; # consumes the MooX::ConfigFromFile::Role but load config only once use MooX::ConfigFromFile config_singleton => 1; with "Role::Action"; sub _build_config_prefix { "die" } sub operate { return die shift->operator; } package main; my $action = Action->new(); # tries to find a config file in config_dirs and loads it my $other = OtherAction->new( config_prefix => "warn" ); # use another config file my $quite_o = QuiteOtherOne->new(); # quite another way to have an individual config file =head1 DESCRIPTION This module is intended to easy load initialization values for attributes on object construction from an appropriate config file. The building is done in L - using MooX::ConfigFromFile ensures the role is applied. For easier usage, with 0.004, several options can be passed via I resulting in default initializers for appropriate role attributes: =over 4 =item C Default for L. =item C Default for L. =item C Default for L. =item C Default for L. Same warning regarding modifying this attribute applies here: Possible, but use with caution! =item C Default for L. Reasonable when you want exactly one config file in development mode. For production code it is highly recommended to override the builder. =item C Flag adding a wrapper L<< around|Class::Method::Modifiers/around method(s) => sub { ... }; >> the I of L to ensure a config is loaded only once per class. The I restriction results from applicable modifiers per class (and singletons are per class). =item C Default for L. =back =head1 AUTHOR Jens Rehsack, C<< >> =head1 BUGS Please report any bugs or feature requests to C, or through the web interface at L. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes. =head1 SUPPORT You can find documentation for this module with the perldoc command. perldoc MooX::ConfigFromFile You can also look for information at: =over 4 =item * RT: CPAN's request tracker (report bugs here) L =item * AnnoCPAN: Annotated CPAN documentation L =item * CPAN Ratings L =item * Search CPAN L =back =head1 ACKNOWLEDGEMENTS =head1 LICENSE AND COPYRIGHT Copyright 2013-2015 Jens Rehsack. This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License. See L for more information. =cut 1; # End of MooX::ConfigFromFile MooX-ConfigFromFile-0.007/lib/MooX/ConfigFromFile/Role/000755 000765 000024 00000000000 12517450274 022364 5ustar00snostaff000000 000000 MooX-ConfigFromFile-0.007/lib/MooX/ConfigFromFile/Role.pm000644 000765 000024 00000016761 12517430023 022723 0ustar00snostaff000000 000000 package MooX::ConfigFromFile::Role; use strict; use warnings; our $VERSION = '0.007'; use FindBin qw/$Script/; use Config::Any; use File::Find::Rule; use Moo::Role; with "MooX::File::ConfigDir"; around BUILDARGS => sub { my $next = shift; my $class = shift; my $params = $class->$next(@_); $class->_initialize_from_config($params); return $params; }; sub _initialize_from_config { my ( $class, $params ) = @_; defined $params->{loaded_config} or $params->{loaded_config} = $class->_build_loaded_config($params); # This copies stuff from loaded_config into the object's parameters foreach my $cfg_key ( keys %{ $params->{loaded_config} } ) { exists $params->{$cfg_key} and next; $params->{$cfg_key} = $params->{loaded_config}->{$cfg_key}; } return $params; } has 'config_prefix' => ( is => 'lazy' ); sub _build_config_prefix { $Script; } has 'config_prefixes' => ( is => 'lazy' ); sub _build_config_prefixes { my ( $class, $params ) = @_; defined $params->{config_prefix} or $params->{config_prefix} = $class->_build_config_prefix($params); [ $params->{config_prefix} ]; } has 'config_prefix_map_separator' => ( is => 'lazy' ); sub _build_config_prefix_map_separator { "-" } has 'config_prefix_map' => ( is => 'lazy' ); sub _build_config_prefix_map { my ( $class, $params ) = @_; defined $params->{config_prefix_map_separator} or $params->{config_prefix_map_separator} = $class->_build_config_prefix_map_separator($params); defined $params->{config_prefixes} or $params->{config_prefixes} = $class->_build_config_prefixes($params); my ( $sep, $i, @prefix_map ) = ( $params->{config_prefix_map_separator} ); for ( $i = 0; $i < scalar @{ $params->{config_prefixes} }; ++$i ) { push @prefix_map, join( $sep, @{ $params->{config_prefixes} }[ 0 .. $i ] ); } \@prefix_map; } has 'config_extensions' => ( is => 'lazy' ); sub _build_config_extensions { [ Config::Any->extensions() ] } has 'config_files_pattern' => ( is => 'lazy' ); sub _build_config_files_pattern { my ( $class, $params ) = @_; defined $params->{config_prefix_map} or $params->{config_prefix_map} = $class->_build_config_prefix_map($params); defined $params->{config_extensions} or $params->{config_extensions} = $class->_build_config_extensions($params); # my @cfg_pattern = map { $params->{config_prefix} . "." . $_ } @{ $params->{config_extensions} }; my @cfg_pattern = map { my $ext = $_; map { $_ . "." . $ext } @{ $params->{config_prefix_map} } } @{ $params->{config_extensions} }; \@cfg_pattern; } has 'config_files' => ( is => 'lazy' ); sub _build_config_files { my ( $class, $params ) = @_; defined $params->{config_files_pattern} or $params->{config_files_pattern} = $class->_build_config_files_pattern($params); defined $params->{config_dirs} or $params->{config_dirs} = $class->_build_config_dirs($params); ref $params->{config_dirs} eq "ARRAY" or $params->{config_dirs} = ["."]; my @cfg_files = File::Find::Rule->file()->name( @{ $params->{config_files_pattern} } )->maxdepth(1)->in( @{ $params->{config_dirs} } ); return \@cfg_files; } has raw_loaded_config => ( is => 'lazy', clearer => 1 ); sub _build_raw_loaded_config { my ( $class, $params ) = @_; defined $params->{config_files} or $params->{config_files} = $class->_build_config_files($params); return [] if !@{ $params->{config_files} }; [ sort { my @a = %{$a}; my @b = %{$b}; $a[0] cmp $b[0]; } @{ Config::Any->load_files( { files => $params->{config_files}, use_ext => 1 } ) } ]; } has 'loaded_config' => ( is => 'lazy', clearer => 1 ); sub _build_loaded_config { my ( $class, $params ) = @_; defined $params->{raw_loaded_config} or $params->{raw_loaded_config} = $class->_build_raw_loaded_config($params); my $config_merged = {}; for my $c ( map { values %$_ } @{ $params->{raw_loaded_config} } ) { %$config_merged = ( %$config_merged, %$c ); } $config_merged; } =head1 NAME MooX::ConfigFromFile::Role - Moo eXtension for initializing objects from config file =head1 DESCRIPTION This role adds a initializing sub around L and puts all what could read from config files into the hash which will be used to construct the final object. While it does that, it internally calls it's own _build_* methods (I<_build_config_prefix>, I<_build_config_files> and I<_build_loaded_config>) unless the appropriate attributes are already in C<$params>. =head1 ATTRIBUTES This role uses following attributes which might be suitable customized by overloading the appropriate builder or pass defaults in construction arguments. Be sure to read L, especially L to understand how the L are build. When you miss a directory - see L and L. =head2 config_prefix This attribute is a string and defaults to L's C<$Script>. It's interpreted as the basename of the config file name to use. =head2 config_prefixes This attribute is an array of strings and defaults to C<<[ config_prefix ]>>. =head2 config_prefix_map_separator This attribute is a string and contains the character which is used building I from I. =head2 config_prefix_map This attribute is an array of strings containing all config-prefixes joint together C<($0, $0.$1, $0.$1.$2, ...)> using I. =head2 config_files_pattern This attribute contains a cross-product of I and I. Both are concatenated using the shell wildcard '*'. =head2 config_dirs This attribute is consumed from L. It might not be smart to override - but possible. Use with caution. =head2 config_extensions This attribute defaults to list of extensions from L. =head2 config_files This attribute contains the list of existing files in I matching I . I. Search is operated by L. =head2 raw_loaded_config This attribute contains the config as loaded from file system in an array of C<< filename => \%content >>. The result from L is sorted by filename (C<< '-' < '.' >>). =head2 loaded_config This attribute contains the config loaded and transformed while constructing the instance. Construction is done from I, ignoring the filename part. For classes set up using use MooX::ConfigFromFile config_singleton = 1; this attribute is cached from the very first construction and fed by overwritten I. The content of this attribute is passed to lower I. =head1 AUTHOR Jens Rehsack, C<< >> =head1 ACKNOWLEDGEMENTS Toby Inkster suggested to rely on BUILDARGS instead of intercepting object creation with nasty hacks. He also taught me a bit more how Moo(se) works. =head1 LICENSE AND COPYRIGHT Copyright 2013-2015 Jens Rehsack. This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License. See L for more information. =cut 1; MooX-ConfigFromFile-0.007/lib/MooX/ConfigFromFile/Role/HashMergeLoaded.pm000644 000765 000024 00000004554 12517430361 025701 0ustar00snostaff000000 000000 package MooX::ConfigFromFile::Role::HashMergeLoaded; use strict; use warnings; our $VERSION = '0.007'; use Hash::Merge; use Moo::Role; requires "loaded_config"; has "config_merger" => ( is => "lazy" ); sub _build_config_merger { Hash::Merge->new('LEFT_PRECEDENT') } around _build_loaded_config => sub { my ( $next, $class, $params ) = @_; defined $params->{raw_loaded_config} or $params->{raw_loaded_config} = $class->_build_raw_loaded_config($params); defined $params->{config_merger} or $params->{config_merger} = $class->_build_config_merger($params); my $config_merged = {}; for my $c ( map { values %$_ } @{ $params->{raw_loaded_config} } ) { %$config_merged = %{ $params->{config_merger}->merge( $config_merged, $c ) }; } $config_merged; }; 1; =head1 NAME MooX::ConfigFromFile::Role::HashMergeLoaded - allows better merge stragegies for multiple config files =head1 SYNOPSIS package MyApp::Cmd::TPau; use DBI; use Moo; use MooX::Cmd with_configfromfile => 1; with "MooX::ConfigFromFile::Role::HashMergeLoaded"; has csv => (is => "ro", required => 1); sub execute { my $self = shift; DBI->connect("DBI::csv:", undef, undef, $self->csv); } __END__ $ cat etc/myapp.json { "csv": { "f_ext": ".csv/r", "csv_sep_char": ";", "csv_class": "Text::CSV_XS" } } $cat etc/myapp-tpau.json { "csv": { "f_dir": "data/tpau" } } =head1 DESCRIPTION This is an additional role for MooX::ConfigFromFile to allow better merging of deep structures. =head1 ATTRIBUTES =head2 config_merger This attribute contains the instance of the merger used to merge the I into I. =head2 loaded_config This role modifies the builder for I by merging the items from I in order of appearance. It is assumed that more relevant config files are in front and are filled up with defaults in following ones. =head1 AUTHOR Jens Rehsack, C<< >> =head1 ACKNOWLEDGEMENTS =head1 LICENSE AND COPYRIGHT Copyright 2015 Jens Rehsack. This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License. See L for more information. =cut MooX-ConfigFromFile-0.007/etc/calc-operands.json000644 000765 000024 00000000035 12221023560 021343 0ustar00snostaff000000 000000 { "a" : 2, "b" : 3 } MooX-ConfigFromFile-0.007/etc/MooXCmdTest-test-this-hashmerged.json000644 000765 000024 00000000077 12517401415 025042 0ustar00snostaff000000 000000 { "merged_frame": { "overwritten_value": "dammed" } } MooX-ConfigFromFile-0.007/etc/MooXCmdTest-test-this.json000644 000765 000024 00000000203 12517403515 022727 0ustar00snostaff000000 000000 { "dedicated_setting": 4711, "merged_frame": { "kept_value": "sane", "overwritten_value": "insane" } } MooX-ConfigFromFile-0.007/etc/MooXCmdTest-test.json000644 000765 000024 00000000044 12475543102 021765 0ustar00snostaff000000 000000 { "unintialized_attribute": 1 } MooX-ConfigFromFile-0.007/etc/MooXCmdTest.json000644 000765 000024 00000000070 12475540400 021005 0ustar00snostaff000000 000000 { "complicated_setting": { "say": "Hello!" } } MooX-ConfigFromFile-0.007/etc/MooXCmdTest.test.this.json000644 000765 000024 00000000042 12517403542 022732 0ustar00snostaff000000 000000 { "dedicated_setting": 4711 } MooX-ConfigFromFile-0.007/etc/MooXCmdTest.tested.json000644 000765 000024 00000000043 12475543064 022305 0ustar00snostaff000000 000000 { "confidential_setting": 42 } MooX-ConfigFromFile-0.007/calc/etc/000755 000765 000024 00000000000 12517450274 016657 5ustar00snostaff000000 000000 MooX-ConfigFromFile-0.007/calc/etc/large-operands.json000644 000765 000024 00000000041 12475550503 022447 0ustar00snostaff000000 000000 { "a" : 666, "b" : 222 } MooX-ConfigFromFile-0.007/calc/etc/operands.json000644 000765 000024 00000000036 12475551574 021374 0ustar00snostaff000000 000000 { "a" : 21, "b" : 4 } MooX-ConfigFromFile-0.007/calc/etc/small-operands.json000644 000765 000024 00000000036 12475550466 022501 0ustar00snostaff000000 000000 { "a" : 30, "b" : 6 }