Codebase list libconfig-model-itself-perl / 9336691
New upstream version 2.021 gregor herrmann 3 years ago
15 changed file(s) with 244 addition(s) and 94 deletion(s). Raw diff Collapse all Expand all
6868 'Getopt::Long' => '0',
6969 'Module::Build' => '0.34',
7070 'Test::Differences' => '0',
71 'Test::Exception' => '0',
7172 'Test::File::Contents' => '0',
7273 'Test::Memory::Cycle' => '0',
7374 'Test::More' => '0',
0 2.021 2021-01-13
1
2 A new 2.021 release for 2021 :-)
3
4 Bug fix:
5 * fix error message when attaching Config class to unknown Perl class
6 * update rw_config file documentation in model
7 * remove files of deleted application when writing back a model
8
09 2.020 2019-12-29
110
211 Dependencies:
0 # This file was automatically generated by Dist::Zilla::Plugin::Manifest v6.012.
0 # This file was automatically generated by Dist::Zilla::Plugin::Manifest v6.017.
11 Build.PL
22 CONTRIBUTING.md
33 Changes
88 README-build-from-git.md
99 README.md
1010 contrib/bash_completion.cme_meta
11 data/application.d/goner
1112 data/application.d/master
1213 data/models/MasterModel.pl
1314 data/models/MasterModel/CheckListExamples.pl
4142 lib/Config/Model/models/Itself/WarpValue.pod
4243 lib/Config/Model/models/Itself/WarpableCargoElement.pl
4344 lib/Config/Model/models/Itself/WarpableElement.pl
45 t/application.t
4446 t/author-critic.t
4547 t/backend_detect.t
4648 t/cme-meta-edit.t
5254 t/itself_snippet.t
5355 t/list_itself_structure.t
5456 t/load_write_itself.t
57 t/meta-class.t
5558 t/pod.t
5659 t/pod_gen.t
5760 weaver.ini
33 "Dominique Dumont"
44 ],
55 "dynamic_config" : 0,
6 "generated_by" : "Dist::Zilla version 6.012, CPAN::Meta::Converter version 2.150010",
6 "generated_by" : "Dist::Zilla version 6.017, CPAN::Meta::Converter version 2.150010",
77 "license" : [
88 "lgpl_2_1"
99 ],
6666 "File::Copy::Recursive" : "0",
6767 "Getopt::Long" : "0",
6868 "Test::Differences" : "0",
69 "Test::Exception" : "0",
6970 "Test::File::Contents" : "0",
7071 "Test::Memory::Cycle" : "0",
7172 "Test::More" : "0",
8889 "web" : "http://github.com/dod38fr/config-model-itself"
8990 }
9091 },
91 "version" : "2.020",
92 "x_generated_by_perl" : "v5.30.0",
93 "x_serialization_backend" : "Cpanel::JSON::XS version 4.17"
92 "version" : "2.021",
93 "x_generated_by_perl" : "v5.32.0",
94 "x_serialization_backend" : "Cpanel::JSON::XS version 4.25",
95 "x_spdx_expression" : "LGPL-2.1"
9496 }
9597
1010 Getopt::Long: '0'
1111 Module::Build: '0.34'
1212 Test::Differences: '0'
13 Test::Exception: '0'
1314 Test::File::Contents: '0'
1415 Test::Memory::Cycle: '0'
1516 Test::More: '0'
1920 configure_requires:
2021 Module::Build: '0.34'
2122 dynamic_config: 0
22 generated_by: 'Dist::Zilla version 6.012, CPAN::Meta::Converter version 2.150010'
23 generated_by: 'Dist::Zilla version 6.017, CPAN::Meta::Converter version 2.150010'
2324 license: lgpl
2425 meta-spec:
2526 url: http://module-build.sourceforge.net/META-spec-v1.4.html
5556 bugtracker: https://github.com/dod38fr/config-model-itself/issues
5657 homepage: https://github.com/dod38fr/config-model/wiki
5758 repository: git://github.com/dod38fr/config-model-itself.git
58 version: '2.020'
59 x_generated_by_perl: v5.30.0
59 version: '2.021'
60 x_generated_by_perl: v5.32.0
6061 x_serialization_backend: 'YAML::Tiny version 1.73'
62 x_spdx_expression: LGPL-2.1
0 model = MasterModel
1 allow_config_file_override = 1
88 #
99 # ABSTRACT: Work on the configuration model of an application
1010
11 package App::Cme::Command::meta 2.020;
11 package App::Cme::Command::meta 2.021;
1212
1313 use strict ;
1414 use warnings ;
404404
405405 =head1 VERSION
406406
407 version 2.020
407 version 2.021
408408
409409 =head1 SYNOPSIS
410410
66 #
77 # The GNU Lesser General Public License, Version 2.1, February 1999
88 #
9 package Config::Model::Itself::BackendDetector 2.020;
9 package Config::Model::Itself::BackendDetector 2.021;
1010
1111 # since this package is mostly targeted for dev environments
1212 # let the detector detect models under development
101101
102102 =head1 VERSION
103103
104 version 2.020
104 version 2.021
105105
106106 =head1 SYNOPSIS
107107
66 #
77 # The GNU Lesser General Public License, Version 2.1, February 1999
88 #
9 package Config::Model::Itself::TkEditUI 2.020;
9 package Config::Model::Itself::TkEditUI 2.021;
1010
1111 use strict;
1212 use warnings ;
66 #
77 # The GNU Lesser General Public License, Version 2.1, February 1999
88 #
9 package Config::Model::Itself 2.020;
9 package Config::Model::Itself 2.021;
1010
1111 use Mouse ;
1212 use Config::Model 2.134;
194194
195195 my $app_dir = $read_from || $self->model_dir->parent;
196196 my %apps;
197 my %map;
197198 $logger->info("reading app files from ".$app_dir);
198199 foreach my $dir ( $app_dir->children(qr/\.d$/) ) {
199200
218219
219220 my $appli = $file->basename;
220221 $apps{$appli} = $data{model} ;
222 $map{$appli} = $file;
221223
222224 $self->meta_root->load_data(
223225 data => { application => { $appli => \%data } },
225227 ) ;
226228 }
227229 }
230
231 $self->{app_map} = \%map;
228232
229233 return \%apps;
230234 }
472476 my $app_obj = $self->meta_root->fetch_element('application');
473477
474478 foreach my $app_name ( $app_obj->fetch_all_indexes ) {
479 $logger->debug("writing $app_name...");
475480 my $app = $app_obj->fetch_with_id($app_name);
476481 my $cat_dir_name = $app->fetch_element_value( name =>'category' ).'.d';
477482 $app_dir->child($cat_dir_name)->mkpath();
488493 }
489494 $logger->info("writing file ".$app_file);
490495 $app_file->spew(@lines);
491 }
492
496 delete $self->{app_map}{$app_name};
497 }
498
499 # prune removed app files
500 foreach my $old_file ( values %{$self->{app_map}}) {
501 $logger->debug("Removing $old_file.");
502 $old_file->remove;
503 }
493504 }
494505
495506 sub write_all {
528539 my %map_to_write = (%$map,%new_map) ;
529540
530541 foreach my $file (keys %map_to_write) {
531 $logger->info("checking model file $file");
532
533 my @data ;
534 my @notes ;
535 my $file_needs_write = 0;
536
537 # check if any a class of a file was modified
538 foreach my $class_name (@{$map_to_write{$file}}) {
539 $file_needs_write++ if $self->class_needs_write($class_name);
540 $logger->info("file $file class $class_name needs write ",$file_needs_write);
541 }
542
543 next unless $file_needs_write ;
544
545 foreach my $class_name (@{$map_to_write{$file}}) {
542 my ($data,$notes) = $self->check_model_to_write($file, \%map_to_write, \%loaded_classes);
543 next unless @$data ; # don't write empty model
544 write_model_file ($dir->child($file), $self->{header}{$file}, $notes, $data);
545 }
546
547 $self->meta_instance->clear_changes ;
548 }
549
550 sub check_model_to_write {
551 my ($self, $file, $map_to_write, $loaded_classes) = @_;
552 $logger->info("checking model file $file");
553
554 my @data ;
555 my @notes ;
556 my $file_needs_write = 0;
557
558 # check if any a class of a file was modified
559 foreach my $class_name (@{$map_to_write->{$file}}) {
560 $file_needs_write++ if $self->class_needs_write($class_name);
561 $logger->info("file $file class $class_name needs write ",$file_needs_write);
562 }
563
564 if ($file_needs_write) {
565 foreach my $class_name (@{$map_to_write->{$file}}) {
546566 $logger->info("writing class $class_name");
547 my $model
548 = $self-> get_perl_data_model(class_name => $class_name) ;
567 my $model = $self-> get_perl_data_model(class_name => $class_name) ;
549568 push @data, $model if defined $model and keys %$model;
550569
551570 my $node = $self->{meta_root}->grab("class:".$class_name) ;
552571 push @notes, $node->dump_annotations_as_pod ;
553572 # remove class name from above list
554 delete $loaded_classes{$class_name} ;
555 }
556
557 next unless @data ; # don't write empty model
558
559 write_model_file ($dir->child($file), $self->{header}{$file}, \@notes, \@data);
560 }
561
562 $self->meta_instance->clear_changes ;
573 delete $loaded_classes->{$class_name} ;
574 }
575 }
576
577 return (\@data, \@notes);
563578 }
564579
565580 sub write_model_plugin {
610625 } ;
611626 find ($wanted, $plugin_dir ) ;
612627
628 foreach my $load_file (@files) {
629 $self->read_plugin_file($load_file);
630 }
631 }
632
633 sub read_plugin_file {
634 my ($self, $load_file) = @_;
635
636 $logger->info("trying to read plugin $load_file");
613637 my $class_element = $self->meta_root->fetch_element('class') ;
614638
615 foreach my $load_file (@files) {
616 $logger->info("trying to read plugin $load_file");
617
618 $load_file = "./$load_file" if $load_file !~ m!^/! and -e $load_file;
619
620 my $plugin = do $load_file ;
621
622 unless ($plugin) {
623 if ($@) {die "couldn't parse $load_file: $@"; }
624 elsif (not defined $plugin) {die "couldn't do $load_file: $!"}
625 else { die "couldn't run $load_file" ;}
626 }
627
628 # there should be only only class in each plugin file
629 foreach my $model (@$plugin) {
630 my $class_name = delete $model->{name} ;
631 # load with a array ref to avoid warnings about missing order
632 $class_element->fetch_with_id($class_name)->load_data( $model ) ;
633 }
634
635 # load annotations
636 $logger->info("loading annotations from plugin file $load_file");
637 my $fh = IO::File->new($load_file) || die "Can't open $load_file: $!" ;
638 my @lines = $fh->getlines ;
639 $fh->close;
640 $self->meta_root->load_pod_annotation(join('',@lines)) ;
641 }
642 }
643
639 $load_file = "./$load_file" if $load_file !~ m!^/! and -e $load_file;
640
641 my $plugin = do $load_file ;
642
643 unless ($plugin) {
644 if ($@) {die "couldn't parse $load_file: $@"; }
645 elsif (not defined $plugin) {die "couldn't do $load_file: $!"}
646 else { die "couldn't run $load_file" ;}
647 }
648
649 # there should be only only class in each plugin file
650 foreach my $model (@$plugin) {
651 my $class_name = delete $model->{name} ;
652 # load with a array ref to avoid warnings about missing order
653 $class_element->fetch_with_id($class_name)->load_data( $model ) ;
654 }
655
656 # load annotations
657 $logger->info("loading annotations from plugin file $load_file");
658 my $fh = IO::File->new($load_file) || die "Can't open $load_file: $!" ;
659 my @lines = $fh->getlines ;
660 $fh->close;
661 $self->meta_root->load_pod_annotation(join('',@lines)) ;
662 }
644663
645664 #
646665 # New subroutine "write_model_file" extracted - Mon Mar 12 13:38:29 2012.
831850
832851 =head1 VERSION
833852
834 version 2.020
853 version 2.021
835854
836855 =head1 SYNOPSIS
837856
9961015
9971016 =item *
9981017
999 Search CPAN
1000
1001 The default CPAN search engine, useful to view POD in HTML format.
1002
1003 L<http://search.cpan.org/dist/Config-Model-Itself>
1004
1005 =item *
1006
1007 CPAN Ratings
1008
1009 The CPAN Ratings is a website that allows community ratings and reviews of Perl modules.
1010
1011 L<http://cpanratings.perl.org/d/Config-Model-Itself>
1012
1013 =item *
1014
10151018 CPANTS
10161019
10171020 The CPANTS is a website that analyzes the Kwalitee ( code metrics ) of a distribution.
6161 ."This Perl class must inherit L<Config::Model::Node>. Use with care.",
6262 assert => {
6363 "1_load_class" => {
64 code => 'not defined $_ or eval{Mouse::Util::load_class($_)}; not $@;',
64 code => 'return 1 unless defined $_;'
65 .'return Mouse::Util::load_class($_);',
6566 msg => 'Error while loading $_ class ',
6667 },
6768 "2_class_inherit" => {
175176 .'not be applicable depending on your application. It may also be '
176177 .'hardcoded in a custom backend. If not specified, the instance name '
177178 .'is used as base name for your configuration file. The configuration file name'
178 .'can be specified with &index keyword when a backend is associated to a node '
179 .'contained in a hash. See '
180 .'L<backend specifications|http://search.cpan.org/dist/Config-Model/lib/Config/Model/BackendMgr.pm#Backend_specification>.'
179 .'can be specified with &index() or &element function. See '
180 .'L<backend specifications|http://search.cpan.org/dist/Config-Model/lib/Config/Model/BackendMgr.pm#Backend_specification> '
181 .'and L<Config::Model::Role::ComputeFunction>.'
181182 },
182183 ]
183184 ],
2222
2323 =head2 file - target configuration file name
2424
25 specify the configuration file name. This parameter may not be applicable depending on your application. It may also be hardcoded in a custom backend. If not specified, the instance name is used as base name for your configuration file. The configuration file namecan be specified with &index keyword when a backend is associated to a node contained in a hash. See L<backend specifications|http://search.cpan.org/dist/Config-Model/lib/Config/Model/BackendMgr.pm#Backend_specification>. I< Optional. Type uniline. >
25 specify the configuration file name. This parameter may not be applicable depending on your application. It may also be hardcoded in a custom backend. If not specified, the instance name is used as base name for your configuration file. The configuration file namecan be specified with &index() or &element function. See L<backend specifications|http://search.cpan.org/dist/Config-Model/lib/Config/Model/BackendMgr.pm#Backend_specification> and L<Config::Model::Role::ComputeFunction>. I< Optional. Type uniline. >
2626
2727 =head1 SEE ALSO
2828
5050
5151 =head2 file - target configuration file name
5252
53 specify the configuration file name. This parameter may not be applicable depending on your application. It may also be hardcoded in a custom backend. If not specified, the instance name is used as base name for your configuration file. The configuration file namecan be specified with &index keyword when a backend is associated to a node contained in a hash. See L<backend specifications|http://search.cpan.org/dist/Config-Model/lib/Config/Model/BackendMgr.pm#Backend_specification>. I< Optional. Type uniline. >
53 specify the configuration file name. This parameter may not be applicable depending on your application. It may also be hardcoded in a custom backend. If not specified, the instance name is used as base name for your configuration file. The configuration file namecan be specified with &index() or &element function. See L<backend specifications|http://search.cpan.org/dist/Config-Model/lib/Config/Model/BackendMgr.pm#Backend_specification> and L<Config::Model::Role::ComputeFunction>. I< Optional. Type uniline. >
5454
5555 =head2 function
5656
0 # -*- cperl -*-
1
2 use ExtUtils::testlib;
3 use Test::More ;
4 use Config::Model 2.138;
5 use Config::Model::Tester::Setup qw/init_test setup_test_dir/;
6 use Path::Tiny;
7
8 use Config::Model::Itself ;
9 use File::Copy::Recursive qw(fcopy rcopy dircopy);
10 use Test::Memory::Cycle;
11
12 use 5.10.1;
13 use warnings;
14 use strict;
15
16 my ($meta_model, $trace) = init_test();
17
18 # do search for the models created in this test
19 use lib "wr_root/itself/lib";
20
21 my $wr_test = setup_test_dir ;
22 my $wr_lib = $wr_test->child("lib");
23 my $wr_model1 = $wr_lib->child("wr_model1");
24
25 $wr_model1->mkpath;
26
27 # copy test model
28 dircopy('data',$wr_model1->stringify) || die "cannot copy model data:$!" ;
29
30 my $model = Config::Model->new(
31 model_dir => $wr_model1->child("models")->relative($wr_lib)->stringify
32 ) ;
33 ok(1,"loaded Master model") ;
34
35 # ok now we can load test model in Itself
36
37 my $meta_inst = $meta_model -> instance (
38 root_class_name => 'Itself::Model',
39 instance_name => 'itself_instance',
40 root_dir => $wr_model1->stringify,
41 );
42 ok($meta_inst,"Read Itself::Model and created instance") ;
43
44 my $meta_root = $meta_inst -> config_root ;
45
46 my $rw_obj = Config::Model::Itself -> new(
47 model_object => $meta_root,
48 cm_lib_dir => $wr_model1->stringify,
49 ) ;
50
51 ok($rw_obj,"Created model reader/writer");
52
53 $rw_obj->read_all(
54 root_model => 'MasterModel',
55 legacy => 'ignore',
56 ) ;
57
58 ok(1,"Read all models in data dir") ;
59
60 is_deeply(
61 [ $meta_root->grab('application')->fetch_all_indexes ],
62 [ qw/goner master/],
63 "check that 2 application files were read"
64 );
65
66 # remove dummy application
67 $meta_root->load("application:.rm(goner)");
68
69 is_deeply(
70 [ $meta_root->grab('application')->fetch_all_indexes ],
71 [ qw/master/],
72 "check that 1 application is left"
73 );
74
75 $rw_obj -> write_all();
76 ok(1,"Wrote back model") ;
77
78 ok(
79 ! $wr_model1->child('application.d/goner')->exists,
80 "check that goner application file was removed"
81 );
82
83 note("testing memory cycles. Please wait...");
84 memory_cycle_ok($meta_model, "Check memory cycle");
85
86 done_testing;
0
1 use ExtUtils::testlib;
2 use Test::More ;
3 use Config::Model 2.138;
4 use Config::Model::Tester::Setup qw/init_test setup_test_dir/;
5
6 use Config::Model::Itself ;
7 use Test::Memory::Cycle;
8 use Test::Exception;
9
10 use warnings;
11 use strict;
12
13 my ($meta_model, $trace) = init_test();
14
15 my $wr_root = setup_test_dir;
16
17 my $meta_inst = $meta_model-> instance (
18 root_class_name => 'Itself::Model',
19 instance_name => 'itself_instance',
20 root_dir => "data",
21 );
22 ok($meta_inst,"Read Itself::Model and created instance") ;
23
24 my $meta_root = $meta_inst -> config_root ;
25
26 $meta_root->load('class:Test');
27 ok(1,"Created dummy Test class");
28
29 throws_ok {
30 $meta_root->load('class:Test class="Foo::Bar"');
31 }
32 qr!Can't locate Foo/Bar.pm in \@INC!,
33 "test explicit error message when attaching Config class to unknown Perl class";
34 print "normal error:\n", $@, "\n" if $trace;
35
36 note("testing memory cycles. Please wait...");
37 memory_cycle_ok($meta_model, "Check memory cycle");
38
39 done_testing;