[libconfig-model-perl] 01/01: New upstream version 2.095
dod at debian.org
dod at debian.org
Mon Dec 12 12:53:32 UTC 2016
This is an automated email from the git hooks/post-receive script.
dod pushed a commit to annotated tag upstream/2.095
in repository libconfig-model-perl.
commit db7a25a3252eb67226f2e0ff7323b738bf5cf1f3
Author: Dominique Dumont <dod at debian.org>
Date: Tue Dec 6 19:00:57 2016 +0100
New upstream version 2.095
---
Build.PL | 5 +-
Changes | 16 +
MANIFEST | 4 +
META.json | 13 +-
META.yml | 9 +-
README.md | 6 +
lib/Config/Model.pm | 6 +-
lib/Config/Model/Annotation.pm | 16 +-
lib/Config/Model/AnyId.pm | 18 +-
lib/Config/Model/AnyThing.pm | 457 +------------------
lib/Config/Model/Backend/Any.pm | 4 +-
lib/Config/Model/Backend/Fstab.pm | 4 +-
lib/Config/Model/Backend/IniFile.pm | 4 +-
lib/Config/Model/Backend/Json.pm | 4 +-
lib/Config/Model/Backend/PlainFile.pm | 4 +-
lib/Config/Model/Backend/ShellVar.pm | 4 +-
lib/Config/Model/Backend/Yaml.pm | 4 +-
lib/Config/Model/BackendMgr.pm | 22 +-
lib/Config/Model/CheckList.pm | 8 +-
lib/Config/Model/Cookbook/CreateModelFromDoc.pod | 2 +-
lib/Config/Model/Describe.pm | 4 +-
lib/Config/Model/DumpAsData.pm | 4 +-
lib/Config/Model/Dumper.pm | 4 +-
lib/Config/Model/Exception.pm | 46 +-
lib/Config/Model/FuseUI.pm | 4 +-
lib/Config/Model/HashId.pm | 45 +-
lib/Config/Model/IdElementReference.pm | 6 +-
lib/Config/Model/Instance.pm | 11 +-
lib/Config/Model/Iterator.pm | 4 +-
lib/Config/Model/ListId.pm | 6 +-
lib/Config/Model/Lister.pm | 4 +-
lib/Config/Model/Loader.pm | 86 +++-
lib/Config/Model/Manual/ModelCreationAdvanced.pod | 2 +-
.../Model/Manual/ModelCreationIntroduction.pod | 2 +-
lib/Config/Model/Node.pm | 26 +-
lib/Config/Model/ObjTreeScanner.pm | 4 +-
lib/Config/Model/Report.pm | 8 +-
lib/Config/Model/{AnyThing.pm => Role/Grab.pm} | 507 ++-------------------
lib/Config/Model/Role/HelpAsText.pm | 97 ++++
lib/Config/Model/Role/NodeLoader.pm | 4 +-
lib/Config/Model/Role/WarpMaster.pm | 4 +-
lib/Config/Model/SearchElement.pm | 4 +-
lib/Config/Model/SimpleUI.pm | 14 +-
lib/Config/Model/TermUI.pm | 4 +-
lib/Config/Model/TreeSearcher.pm | 6 +-
lib/Config/Model/Utils/GenClassPod.pm | 4 +-
lib/Config/Model/Value.pm | 6 +-
lib/Config/Model/Value/LayeredInclude.pm | 4 +-
lib/Config/Model/ValueComputer.pm | 8 +-
lib/Config/Model/WarpedNode.pm | 12 +-
lib/Config/Model/Warper.pm | 10 +-
t/annotation.t | 26 +-
t/backend_mgr.t | 106 +++--
t/dump_load_model.pm | 7 +
t/hash_id_of_values.t | 10 +
t/load.t | 9 +
.../multi-ini-examples/max-overflow/etc/bar.conf | 1 +
t/model_tests.d/multi-ini-test-conf.pl | 71 +++
58 files changed, 642 insertions(+), 1148 deletions(-)
diff --git a/Build.PL b/Build.PL
index afc6bc2..6e95fbe 100644
--- a/Build.PL
+++ b/Build.PL
@@ -69,6 +69,7 @@ my $build = $class->new(
'build_requires' => {
'Config::Model::Tester' => '2.053',
'Module::Build' => '0.34',
+ 'Path::Tiny' => '0.070',
'Test::Differences' => '0',
'Test::Exception' => '0',
'Test::File::Contents' => '0',
@@ -110,8 +111,10 @@ my $build = $class->new(
'MouseX::StrictConstructor' => '0',
'POSIX' => '0',
'Parse::RecDescent' => 'v1.90.0',
- 'Path::Tiny' => '0',
+ 'Path::Tiny' => '0.070',
'Pod::POM' => '0',
+ 'Pod::Simple' => '3.23',
+ 'Pod::Text' => '0',
'Scalar::Util' => '0',
'Storable' => '0',
'Text::Diff' => '0',
diff --git a/Changes b/Changes
index 16ecf0a..a43c95c 100644
--- a/Changes
+++ b/Changes
@@ -1,3 +1,19 @@
+2.095 2016-12-06
+
+ New feature usable by cme:
+ * loader: add .insort() command for hash element
+ * Hash element: add insort method
+
+ Term UI improvement
+ * better format the output of 'desc' command (transform
+ pod doc to text). This requires Pod::Text and
+ Pod::Simple 3.23
+
+ Bug fix:
+ * track and save annotation changes (gh #12)
+ * Node: propagate check override in init() (which fixes
+ loading of a systemd config that contains an error)
+
2.094 2016-11-09
Fix compatibility with older Term::ReadLine::Gnu:
diff --git a/MANIFEST b/MANIFEST
index 29518f4..54dac94 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -44,6 +44,8 @@ lib/Config/Model/Manual/ModelCreationIntroduction.pod
lib/Config/Model/Node.pm
lib/Config/Model/ObjTreeScanner.pm
lib/Config/Model/Report.pm
+lib/Config/Model/Role/Grab.pm
+lib/Config/Model/Role/HelpAsText.pm
lib/Config/Model/Role/NodeLoader.pm
lib/Config/Model/Role/WarpMaster.pm
lib/Config/Model/SearchElement.pm
@@ -122,6 +124,8 @@ t/model_tests.d/fstab-test-conf.pl
t/model_tests.d/layer-examples/mini/etc/foo-config.pl
t/model_tests.d/layer-examples/mini/home/joe/foo/config.pl
t/model_tests.d/layer-test-conf.pl
+t/model_tests.d/multi-ini-examples/max-overflow/etc/bar.conf
+t/model_tests.d/multi-ini-test-conf.pl
t/model_tests.d/multistrap-examples/arm/home/foo/my_arm.conf
t/model_tests.d/multistrap-examples/arm/usr/share/multistrap/crosschroot.conf
t/model_tests.d/multistrap-examples/from_scratch/usr/share/multistrap/crosschroot.conf
diff --git a/META.json b/META.json
index 1e308ff..00009de 100644
--- a/META.json
+++ b/META.json
@@ -4,13 +4,13 @@
"Dominique Dumont"
],
"dynamic_config" : 0,
- "generated_by" : "Dist::Zilla version 6.008, CPAN::Meta::Converter version 2.150010",
+ "generated_by" : "Dist::Zilla version 6.008, CPAN::Meta::Converter version 2.150005",
"license" : [
"lgpl_2_1"
],
"meta-spec" : {
"url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",
- "version" : 2
+ "version" : "2"
},
"name" : "Config-Model",
"prereqs" : {
@@ -56,8 +56,10 @@
"MouseX::StrictConstructor" : "0",
"POSIX" : "0",
"Parse::RecDescent" : "v1.90.0",
- "Path::Tiny" : "0",
+ "Path::Tiny" : "0.070",
"Pod::POM" : "0",
+ "Pod::Simple" : "3.23",
+ "Pod::Text" : "0",
"Scalar::Util" : "0",
"Storable" : "0",
"Text::Diff" : "0",
@@ -69,6 +71,7 @@
"test" : {
"requires" : {
"Config::Model::Tester" : "2.053",
+ "Path::Tiny" : "0.070",
"Test::Differences" : "0",
"Test::Exception" : "0",
"Test::File::Contents" : "0",
@@ -91,7 +94,7 @@
"web" : "http://github.com/dod38fr/config-model"
}
},
- "version" : "2.094",
- "x_serialization_backend" : "Cpanel::JSON::XS version 3.022"
+ "version" : "2.095",
+ "x_serialization_backend" : "JSON::XS version 3.03"
}
diff --git a/META.yml b/META.yml
index b785367..ddae9fc 100644
--- a/META.yml
+++ b/META.yml
@@ -5,6 +5,7 @@ author:
build_requires:
Config::Model::Tester: '2.053'
Module::Build: '0.34'
+ Path::Tiny: '0.070'
Test::Differences: '0'
Test::Exception: '0'
Test::File::Contents: '0'
@@ -15,7 +16,7 @@ build_requires:
configure_requires:
Module::Build: '0.34'
dynamic_config: 0
-generated_by: 'Dist::Zilla version 6.008, CPAN::Meta::Converter version 2.150010'
+generated_by: 'Dist::Zilla version 6.008, CPAN::Meta::Converter version 2.150005'
license: lgpl
meta-spec:
url: http://module-build.sourceforge.net/META-spec-v1.4.html
@@ -50,8 +51,10 @@ requires:
MouseX::StrictConstructor: '0'
POSIX: '0'
Parse::RecDescent: v1.90.0
- Path::Tiny: '0'
+ Path::Tiny: '0.070'
Pod::POM: '0'
+ Pod::Simple: '3.23'
+ Pod::Text: '0'
Scalar::Util: '0'
Storable: '0'
Text::Diff: '0'
@@ -62,5 +65,5 @@ resources:
bugtracker: https://github.com/dod38fr/config-model/issues
homepage: https://github.com/dod38fr/config-model/wiki
repository: git://github.com/dod38fr/config-model.git
-version: '2.094'
+version: '2.095'
x_serialization_backend: 'YAML::Tiny version 1.69'
diff --git a/README.md b/README.md
index 2f81091..9163497 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,9 @@
+# Config-Model
+
+Configuration schema on steroids.
+
+[](https://travis-ci.org/dod38fr/config-model)
+
# What is Config-Model project
[Config::Model](https://metacpan.org/pod/Config::Model) is:
diff --git a/lib/Config/Model.pm b/lib/Config/Model.pm
index dd68c32..2fb9f36 100644
--- a/lib/Config/Model.pm
+++ b/lib/Config/Model.pm
@@ -8,7 +8,7 @@
# The GNU Lesser General Public License, Version 2.1, February 1999
#
package Config::Model;
-$Config::Model::VERSION = '2.094';
+$Config::Model::VERSION = '2.095';
use strict ;
use warnings;
use 5.10.1;
@@ -1678,7 +1678,7 @@ Config::Model - Create tools to validate, migrate and edit configuration files
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
@@ -2730,7 +2730,7 @@ CPANTS
The CPANTS is a website that analyzes the Kwalitee ( code metrics ) of a distribution.
-L<http://cpants.perl.org/dist/overview/Config-Model>
+L<http://cpants.cpanauthors.org/dist/Config-Model>
=item *
diff --git a/lib/Config/Model/Annotation.pm b/lib/Config/Model/Annotation.pm
index 96430c8..47d3f0b 100644
--- a/lib/Config/Model/Annotation.pm
+++ b/lib/Config/Model/Annotation.pm
@@ -8,7 +8,7 @@
# The GNU Lesser General Public License, Version 2.1, February 1999
#
package Config::Model::Annotation;
-$Config::Model::Annotation::VERSION = '2.094';
+$Config::Model::Annotation::VERSION = '2.095';
use Mouse;
use English;
@@ -164,7 +164,7 @@ Config::Model::Annotation - Read and write configuration annotations
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
@@ -224,8 +224,12 @@ version 2.094
=head1 DESCRIPTION
This module provides an object that read and write annotations (a bit
-like comments) to and from a configuration tree and save them in a file (not
-configuration file)
+like comments) to and from a configuration tree and save them in a
+file (not configuration file). This module can be used to save
+annotation for configuration files that do not support comments.
+
+THis module should not be used for configuration files that support
+comments.
Depending on the effective id of the process, the annotation is
saved in:
@@ -257,6 +261,10 @@ Save annotations in a file (See L<DESCRIPTION>)
Loads annotations from a file (See L<DESCRIPTION>)
+=head1 CAVEATS
+
+This module is currently not used.
+
=head1 AUTHOR
Dominique Dumont, (ddumont at cpan dot org)
diff --git a/lib/Config/Model/AnyId.pm b/lib/Config/Model/AnyId.pm
index a6e880f..b74845f 100644
--- a/lib/Config/Model/AnyId.pm
+++ b/lib/Config/Model/AnyId.pm
@@ -8,7 +8,7 @@
# The GNU Lesser General Public License, Version 2.1, February 1999
#
package Config::Model::AnyId;
-$Config::Model::AnyId::VERSION = '2.094';
+$Config::Model::AnyId::VERSION = '2.095';
use 5.010;
use Mouse;
@@ -24,6 +24,11 @@ use Scalar::Util qw/weaken/;
extends qw/Config::Model::AnyThing/;
+use Mouse::Util::TypeConstraints;
+
+subtype 'KeyArray' => as 'ArrayRef' ;
+coerce 'KeyArray' => from 'Str' => via { [$_] } ;
+
my $logger = get_logger("Tree::Element::Id");
my $deep_check_logger = get_logger('DeepCheck');
my $fix_logger = get_logger("Anything::Fix");
@@ -103,7 +108,12 @@ my @common_hash_params = qw/default_with_init/;
has \@common_hash_params => ( is => 'ro', isa => 'Maybe[HashRef]' );
my @common_list_params = qw/allow_keys default_keys auto_create_keys/;
-has \@common_list_params => ( is => 'ro', isa => 'Maybe[ArrayRef]' );
+has \@common_list_params => (
+ is => 'ro',
+ isa => 'KeyArray',
+ coerce => 1,
+ default => sub { []; }
+);
my @common_str_params = qw/allow_keys_from allow_keys_matching follow_keys_from
migrate_keys_from migrate_values_from
@@ -1001,7 +1011,7 @@ Config::Model::AnyId - Base class for hash or list element
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
@@ -1163,7 +1173,7 @@ be used with string index type)
When set, the default parameter (or set of parameters) are used as
default keys hashes and created automatically when the C<keys> or C<exists>
-functions are used on an I<empty> hash..
+functions are used on an I<empty> hash.
You can use C<< default_keys => 'foo' >>,
or C<< default_keys => ['foo', 'bar'] >>.
diff --git a/lib/Config/Model/AnyThing.pm b/lib/Config/Model/AnyThing.pm
index 1678eb5..e43cbaa 100644
--- a/lib/Config/Model/AnyThing.pm
+++ b/lib/Config/Model/AnyThing.pm
@@ -8,7 +8,7 @@
# The GNU Lesser General Public License, Version 2.1, February 1999
#
package Config::Model::AnyThing;
-$Config::Model::AnyThing::VERSION = '2.094';
+$Config::Model::AnyThing::VERSION = '2.095';
use Mouse;
# FIXME: must cleanup warp mechanism to implement this
@@ -195,18 +195,22 @@ sub xpath {
sub annotation {
my $self = shift;
- $self->{annotation} = join( "\n", grep ( defined $_, @_ ) )
- if @_
- and not $self->instance->preset
- and not $self->instance->layered;
+ my $old_note = $self->{annotation} || '';
+ if (@_ and not $self->instance->preset and not $self->instance->layered) {
+ my $new = $self->{annotation} = join( "\n", grep ( defined $_, @_ ) );
+ $self->notify_change(note => 'updated annotation') unless $new eq $old_note;
+ }
+
return $self->{annotation} || '';
}
sub clear_annotation {
my $self = shift;
+ $self->notify_change(note => 'deleted annotation') if $self->{annotation};
$self->{annotation} = '';
}
+# may be used (but not yet) to load annotation from perl data file
sub load_pod_annotation {
my $self = shift;
my $pod = shift;
@@ -230,339 +234,6 @@ sub load_pod_annotation {
}
}
-## Navigation
-
-# accept commands like
-# item:b -> go down a node, create a new node if necessary
-# - climbs up
-# ! climbs up to the top
-
-# Now return an object and not a value !
-
-sub grab {
- my $self = shift;
- my ( $steps, $mode, $autoadd, $type, $grab_non_available, $check ) =
- ( undef, 'strict', 1, undef, 0, 'yes' );
-
- my %args = @_ > 1 ? @_ : ( steps => $_[0] );
-
- $steps = delete $args{steps} // delete $args{step};
- $mode = delete $args{mode} if defined $args{mode};
- $autoadd = delete $args{autoadd} if defined $args{autoadd};
- $grab_non_available = delete $args{grab_non_available}
- if defined $args{grab_non_available};
- $type = delete $args{type}; # node, leaf or undef
- $check = $self->_check_check( delete $args{check} );
-
- if ( defined $args{strict} ) {
- carp "grab: deprecated parameter 'strict'. Use mode";
- $mode = delete $args{strict} ? 'strict' : 'adaptative';
- }
-
- Config::Model::Exception::User->throw(
- object => $self,
- message => "grab: unexpected parameter: " . join( ' ', keys %args ) ) if %args;
-
- Config::Model::Exception::Internal->throw(
- error => "grab: steps parameter must be a string " . "or an array ref" )
- unless ref $steps eq 'ARRAY' || not ref $steps;
-
- # accept commands, grep remove empty items left by spurious spaces
- my $huge_string = ref $steps ? join( ' ', @$steps ) : $steps;
- my @command = (
- $huge_string =~ m/
- ( # begin of *one* command
- (?: # group parts of a command (e.g ...:... )
- [^\s"]+ # match anything but a space and a quote
- (?: # begin quoted group
- " # begin of a string
- (?: # begin group
- \\" # match an escaped quote
- | # or
- [^"] # anything but a quote
- )* # lots of time
- " # end of the string
- ) # end of quoted group
- ? # match if I got more than one group
- )+ # can have several parts in one command
- ) # end of *one* command
- /gx
- );
-
- my @saved = @command;
-
- $logger->debug(
- "grab: executing '",
- join( "' '", @command ),
- "' on object '",
- $self->name, "'"
- );
-
- my @found = ($self);
-
-COMMAND:
- while (@command) {
- last if $mode eq 'step_by_step' and @saved > @command;
-
- my $cmd = shift @command;
-
- my $obj = $found[-1];
- $logger->debug( "grab: executing cmd '$cmd' on object '", $obj->name, "($obj)'" );
-
- if ( $cmd eq '!' ) {
- push @found, $obj->grab_root();
- next;
- }
-
- if ( $cmd =~ /^!([\w:]*)/ ) {
- my $ancestor = $obj->grab_ancestor($1);
- if ( defined $ancestor ) {
- push @found, $ancestor;
- next;
- }
- else {
- Config::Model::Exception::AncestorClass->throw(
- object => $obj,
- info => "grab called from '"
- . $self->name
- . "' with steps '@saved' looking for class $1"
- ) if $mode eq 'strict';
- return;
- }
- }
-
- if ( $cmd =~ /^\?(\w[\w-]*)/ ) {
- push @found, $obj->grab_ancestor_with_element_named($1);
- $cmd =~ s/^\?//; #remove the go up part
- unshift @command, $cmd;
- next;
- }
-
- if ( $cmd eq '-' ) {
- if ( defined $obj->parent ) {
- push @found, $obj->parent;
- next;
- }
- else {
- $logger->debug( "grab: ", $obj->name, " has no parent" );
- return $mode eq 'adaptative' ? $obj : undef;
- }
- }
-
- unless ( $obj->isa('Config::Model::Node')
- or $obj->isa('Config::Model::WarpedNode') ) {
- Config::Model::Exception::Model->throw(
- object => $obj,
- message => "Cannot apply command '$cmd' on leaf item"
- . " (full command is '@saved')"
- );
- }
-
- my ( $name, $action, $arg ) =
- ( $cmd =~ /(\w[\-\w]*)(?:(:)((?:"[^\"]*")|(?:[\w:\/\.\-\+]+)))?/ );
-
- if ( defined $arg and $arg =~ /^"/ and $arg =~ /"$/ ) {
- $arg =~ s/^"//; # remove leading quote
- $arg =~ s/"$//; # remove trailing quote
- }
-
- {
- no warnings "uninitialized";
- $logger->debug("grab: cmd '$cmd' -> name '$name', action '$action', arg '$arg'");
- }
-
- unless ( $obj->has_element($name) ) {
- if ( $mode eq 'step_by_step' ) {
- return wantarray ? ( undef, @command ) : undef;
- }
- elsif ( $mode eq 'loose' ) {
- return;
- }
- elsif ( $mode eq 'adaptative' ) {
- last;
- }
- else {
- Config::Model::Exception::UnknownElement->throw(
- object => $obj,
- element => $name,
- function => 'grab',
- info => "grab called from '" . $self->name . "' with steps '@saved'"
- );
- }
- }
-
- unless (
- $grab_non_available
- or $obj->is_element_available(
- name => $name,
- )
- ) {
- if ( $mode eq 'step_by_step' ) {
- return wantarray ? ( undef, @command ) : undef;
- }
- elsif ( $mode eq 'loose' ) {
- return;
- }
- elsif ( $mode eq 'adaptative' ) {
- last;
- }
- else {
- Config::Model::Exception::UnavailableElement->throw(
- object => $obj,
- element => $name,
- function => 'grab',
- info => "grab called from '" . $self->name . "' with steps '@saved'"
- );
- }
- }
-
- my $next_obj = $obj->fetch_element(
- name => $name,
- check => $check,
- accept_hidden => $grab_non_available
- );
-
- # create list or hash element only if autoadd is true
- if ( defined $action
- and $autoadd == 0
- and not $next_obj->exists($arg) ) {
- return if $mode eq 'loose';
- Config::Model::Exception::UnknownId->throw(
- object => $obj->fetch_element($name),
- element => $name,
- id => $arg,
- function => 'grab'
- ) unless $mode eq 'adaptative';
- last;
- }
-
- if ( defined $action and not $next_obj->isa('Config::Model::AnyId') ) {
- return if $mode eq 'loose';
- Config::Model::Exception::Model->throw(
- object => $obj,
- message => "Cannot apply command '$cmd' on non hash or non list item"
- . " (full command is '@saved'). item is '"
- . $next_obj->name . "'"
- );
- last;
- }
-
- # action can only be :
- $next_obj = $next_obj->fetch_with_id(index => $arg, check => $check) if defined $action;
-
- push @found, $next_obj;
- }
-
- # check element type
- if ( defined $type ) {
- my @allowed = ref $type ? @$type : ($type);
- while ( @found and not grep {$found[-1]->get_type eq $_} @allowed ) {
- Config::Model::Exception::WrongType->throw(
- object => $found[-1],
- function => 'grab',
- got_type => $found[-1]->get_type,
- expected_type => $type,
- info => "requested with steps '$steps'"
- ) if $mode ne 'adaptative';
- pop @found;
- }
- }
-
- my $return = $found[-1];
- $logger->debug( "grab: returning object '", $return->name, "($return)'" );
- return wantarray ? ( $return, @command ) : $return;
-}
-
-sub grab_value {
- my $self = shift;
- my %args = scalar @_ == 1 ? ( steps => $_[0] ) : @_;
-
- my $obj = $self->grab(%args);
-
- # Pb: may return a node. add another option to grab ??
- # to get undef value when needed?
-
- return if ( $args{mode} and $args{mode} eq 'loose' and not defined $obj );
-
- Config::Model::Exception::User->throw(
- object => $self,
- message => "grab_value: cannot get value of non-leaf or check_list "
- . "item with '"
- . join( "' '", @_ )
- . "'. item is $obj"
- )
- unless ref $obj
- and ( $obj->isa("Config::Model::Value")
- or $obj->isa("Config::Model::CheckList") );
-
- my $value = $obj->fetch;
- if ( $logger->is_debug ) {
- my $str = defined $value ? $value : '<undef>';
- $logger->debug( "grab_value: returning value $str of object '", $obj->name );
- }
- return $value;
-}
-
-sub grab_annotation {
- my $self = shift;
- my @args = scalar @_ == 1 ? ( steps => $_[0] ) : @_;
-
- my $obj = $self->grab(@args);
-
- return $obj->annotation;
-}
-
-sub grab_root {
- my $self = shift;
- return defined $self->parent
- ? $self->parent->grab_root
- : $self;
-}
-
-sub grab_ancestor {
- my $self = shift;
- my $class = shift || die "grab_ancestor: missing ancestor class";
-
- return $self if $self->get_type eq 'node' and $self->config_class_name eq $class;
-
- return $self->{parent}->grab_ancestor($class) if defined $self->{parent};
- return;
-}
-
-#internal. Used by grab with '?xxx' steps
-sub grab_ancestor_with_element_named {
- my ( $self, $search, $type ) = @_;
-
- my $obj = $self;
-
- while (1) {
- $logger->debug(
- "grab_ancestor_with_element_named: executing cmd '?$search' on object " . $obj->name );
-
- my $obj_element_name = $obj->element_name;
-
- if ( $obj->isa('Config::Model::Node')
- and $obj->has_element( name => $search, type => $type ) ) {
-
- # object contains the search element, we need to grab the
- # searched object (i.e. the '?foo' part is done
- return $obj;
- }
- elsif ( defined $obj->parent ) {
-
- # going up
- $obj = $obj->parent;
- }
- else {
- # there's no more up to go to...
- Config::Model::Exception::Model->throw(
- object => $self,
- error => "Error: cannot grab '?$search'" . "from " . $self->name
- );
- }
- }
-}
-
# fallback method for object that don't implement has_data
sub has_data {
my $self= shift;
@@ -655,7 +326,7 @@ Config::Model::AnyThing - Base class for configuration tree item
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
@@ -696,12 +367,12 @@ Returns the root node of the configuration tree.
=head2 location()
Returns the node location in the configuration tree. This location
-conforms with the syntax defined by L</grab()> method.
+conforms with the syntax defined by L<grab|Config::Model::Role::Grab/grab> method.
=head2 location_short()
Returns the node location in the configuration tree. This location truncates long
-indexes to be readable. It cannot be used by L</grab()> method.
+indexes to be readable. It cannot be used by L<grab|Config::Model::Role::Grab/grab> method.
=head2 composite_name
@@ -758,110 +429,6 @@ Clear the annotation of an element
=head1 Information management
-=head2 grab(...)
-
-Grab an object from the configuration tree.
-
-Parameters are:
-
-=over
-
-=item C<steps> (or C<step>)
-
-A string indicating the steps to follow in the tree to find the
-required item. (mandatory)
-
-=item C<mode>
-
-When set to C<strict>, C<grab> throws an exception if no object is found
-using the passed string. When set to C<adaptative>, the object found last is
-returned. For instance, for the steps C<good_step wrong_step>, only
-the object held by C<good_step> is returned. When set to C<loose>, grab
-returns undef in case of problem. (default is C<strict>)
-
-=item C<type>
-
-Either C<node>, C<leaf>, C<hash> or C<list> or an array ref containing these
-values. Returns only an object of
-requested type. Depending on C<strict> value, C<grab> either
-throws an exception or returns the last object found with the requested type.
-(optional, default to C<undef>, which means any type of object)
-
-Examples:
-
- $root->grep(steps => 'foo:2 bar', type => 'leaf')
- $root->grep(steps => 'foo:2 bar', type => ['leaf','check_list'])
-
-=item C<autoadd>
-
-When set to 1, C<hash> or C<list> configuration element are created
-when requested by the passed steps. (default is 1).
-
-=item grab_non_available
-
-When set to 1, grab returns an object even if this one is not
-available. I.e. even if this element was warped out. (default is 0).
-
-=back
-
-The C<steps> parameters is made of the following items separated by
-spaces:
-
-=over 8
-
-=item -
-
-Go up one node
-
-=item !
-
-Go to the root node.
-
-=item !Foo
-
-Go up the configuration tree until the C<Foo> configuration class is found. Raise an exception if
-no C<Foo> class is found when root node is reached.
-
-=item xxx
-
-Go down using C<xxx> element.
-
-=item xxx:yy
-
-Go down using C<xxx> element and id C<yy> (valid for hash or list elements)
-
-=item ?xxx
-
-Go up the tree until a node containing element C<xxx> is found. Then go down
-the tree like item C<xxx>.
-
-If C<?xxx:yy>, go up the tree the same way. But no check is done to
-see if id C<yy> actually exists or not. Only the element C<xxx> is
-considered when going up the tree.
-
-=back
-
-=head2 grab_value(...)
-
-Like L</grab(...)>, but returns the value of a leaf or check_list object, not
-just the leaf object.
-
-C<grab_value> raises an exception if following the steps ends on anything but a
-leaf or a check_list.
-
-=head2 grab_annotation(...)
-
-Like L</grab(...)>, but returns the annotation of an object.
-
-=head2 grab_root()
-
-Returns the root of the configuration tree.
-
-=head2 grab_ancestor( Foo )
-
-Go up the configuration tree until the C<Foo> configuration class is found. Returns
-the found node or undef.
-
=head2 notify_change(...)
Notify the instance of semantic changes. Parameters are:
diff --git a/lib/Config/Model/Backend/Any.pm b/lib/Config/Model/Backend/Any.pm
index c43f5dd..eea9fc1 100644
--- a/lib/Config/Model/Backend/Any.pm
+++ b/lib/Config/Model/Backend/Any.pm
@@ -8,7 +8,7 @@
# The GNU Lesser General Public License, Version 2.1, February 1999
#
package Config::Model::Backend::Any;
-$Config::Model::Backend::Any::VERSION = '2.094';
+$Config::Model::Backend::Any::VERSION = '2.095';
use Carp;
use strict;
use warnings;
@@ -185,7 +185,7 @@ Config::Model::Backend::Any - Virtual class for other backends
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
diff --git a/lib/Config/Model/Backend/Fstab.pm b/lib/Config/Model/Backend/Fstab.pm
index 9ceb2ec..494dd6e 100644
--- a/lib/Config/Model/Backend/Fstab.pm
+++ b/lib/Config/Model/Backend/Fstab.pm
@@ -8,7 +8,7 @@
# The GNU Lesser General Public License, Version 2.1, February 1999
#
package Config::Model::Backend::Fstab;
-$Config::Model::Backend::Fstab::VERSION = '2.094';
+$Config::Model::Backend::Fstab::VERSION = '2.095';
use Mouse;
use Carp;
use Log::Log4perl qw(get_logger :levels);
@@ -164,7 +164,7 @@ Config::Model::Backend::Fstab - Read and write config from fstab file
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
diff --git a/lib/Config/Model/Backend/IniFile.pm b/lib/Config/Model/Backend/IniFile.pm
index 431caa0..cb6b2f7 100644
--- a/lib/Config/Model/Backend/IniFile.pm
+++ b/lib/Config/Model/Backend/IniFile.pm
@@ -8,7 +8,7 @@
# The GNU Lesser General Public License, Version 2.1, February 1999
#
package Config::Model::Backend::IniFile;
-$Config::Model::Backend::IniFile::VERSION = '2.094';
+$Config::Model::Backend::IniFile::VERSION = '2.095';
use Carp;
use Mouse;
use 5.10.0;
@@ -408,7 +408,7 @@ Config::Model::Backend::IniFile - Read and write config as a INI file
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
diff --git a/lib/Config/Model/Backend/Json.pm b/lib/Config/Model/Backend/Json.pm
index 535e285..cd8b421 100644
--- a/lib/Config/Model/Backend/Json.pm
+++ b/lib/Config/Model/Backend/Json.pm
@@ -8,7 +8,7 @@
# The GNU Lesser General Public License, Version 2.1, February 1999
#
package Config::Model::Backend::Json;
-$Config::Model::Backend::Json::VERSION = '2.094';
+$Config::Model::Backend::Json::VERSION = '2.095';
use Carp;
use strict;
use warnings;
@@ -93,7 +93,7 @@ Config::Model::Backend::Json - Read and write config as a JSON data structure
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
diff --git a/lib/Config/Model/Backend/PlainFile.pm b/lib/Config/Model/Backend/PlainFile.pm
index cc674ed..a6bb690 100644
--- a/lib/Config/Model/Backend/PlainFile.pm
+++ b/lib/Config/Model/Backend/PlainFile.pm
@@ -8,7 +8,7 @@
# The GNU Lesser General Public License, Version 2.1, February 1999
#
package Config::Model::Backend::PlainFile;
-$Config::Model::Backend::PlainFile::VERSION = '2.094';
+$Config::Model::Backend::PlainFile::VERSION = '2.095';
use Carp;
use Mouse;
use Config::Model::Exception;
@@ -189,7 +189,7 @@ Config::Model::Backend::PlainFile - Read and write config as plain file
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
diff --git a/lib/Config/Model/Backend/ShellVar.pm b/lib/Config/Model/Backend/ShellVar.pm
index 47a1f75..5c74379 100644
--- a/lib/Config/Model/Backend/ShellVar.pm
+++ b/lib/Config/Model/Backend/ShellVar.pm
@@ -8,7 +8,7 @@
# The GNU Lesser General Public License, Version 2.1, February 1999
#
package Config::Model::Backend::ShellVar;
-$Config::Model::Backend::ShellVar::VERSION = '2.094';
+$Config::Model::Backend::ShellVar::VERSION = '2.095';
use Carp;
use Mouse;
use Config::Model::Exception;
@@ -114,7 +114,7 @@ Config::Model::Backend::ShellVar - Read and write config as a C<SHELLVAR> data s
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
diff --git a/lib/Config/Model/Backend/Yaml.pm b/lib/Config/Model/Backend/Yaml.pm
index d719922..a71f20e 100644
--- a/lib/Config/Model/Backend/Yaml.pm
+++ b/lib/Config/Model/Backend/Yaml.pm
@@ -9,7 +9,7 @@
#
package Config::Model::Backend::Yaml;
-$Config::Model::Backend::Yaml::VERSION = '2.094';
+$Config::Model::Backend::Yaml::VERSION = '2.095';
use Carp;
use strict;
use warnings;
@@ -110,7 +110,7 @@ Config::Model::Backend::Yaml - Read and write config as a YAML data structure
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
diff --git a/lib/Config/Model/BackendMgr.pm b/lib/Config/Model/BackendMgr.pm
index fdb53cb..8a71490 100644
--- a/lib/Config/Model/BackendMgr.pm
+++ b/lib/Config/Model/BackendMgr.pm
@@ -8,7 +8,7 @@
# The GNU Lesser General Public License, Version 2.1, February 1999
#
package Config::Model::BackendMgr;
-$Config::Model::BackendMgr::VERSION = '2.094';
+$Config::Model::BackendMgr::VERSION = '2.095';
use Mouse;
use Carp;
@@ -813,7 +813,7 @@ Config::Model::BackendMgr - Load configuration node on demand
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
@@ -951,6 +951,24 @@ directory can be hardcoded in the custom class. C<config_dir> beginning
with 'C<~>' is munged so C<~> is replaced by C<< File::HomeDir->my_data >>.
See L<File::HomeDir> for details.
+=item file
+
+Specify configuration file name (without the path). This parameter is
+optional as the file name can be hardcoded in the custom class.
+
+The configuration file name can be specified with C<&index> keyword
+when a backend is associated to a node contained in a hash. For instance,
+with C<file> set to C<index.conf>:
+
+ service # hash element
+ foo # hash index
+ nodeA # values of nodeA are stored in foo.conf
+ bar # hash index
+ nodeB # values of nodeB are stored in bar.conf
+
+Alternatively, C<file> can be set to C<->, in which case, the
+configuration is read from STDIN.
+
=item os_config_dir
Specify alternate location of a configuration directory depending on the OS
diff --git a/lib/Config/Model/CheckList.pm b/lib/Config/Model/CheckList.pm
index d3cf4e9..26548c7 100644
--- a/lib/Config/Model/CheckList.pm
+++ b/lib/Config/Model/CheckList.pm
@@ -8,7 +8,7 @@
# The GNU Lesser General Public License, Version 2.1, February 1999
#
package Config::Model::CheckList;
-$Config::Model::CheckList::VERSION = '2.094';
+$Config::Model::CheckList::VERSION = '2.095';
use Mouse;
use 5.010;
@@ -23,6 +23,8 @@ use Storable qw/dclone/;
extends qw/Config::Model::AnyThing/;
with "Config::Model::Role::WarpMaster";
+with "Config::Model::Role::Grab";
+with "Config::Model::Role::HelpAsText";
my $logger = get_logger("Tree::Element::CheckList");
@@ -744,7 +746,7 @@ Config::Model::CheckList - Handle check list element
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
@@ -931,7 +933,7 @@ checklist are available.
This other hash or other checklist is indicated by the C<refer_to> or
C<computed_refer_to> parameter. C<refer_to> uses the syntax of the
-C<steps> parameter of L<grab(...)|Config::AnyThing/"grab(...)">
+C<steps> parameter of L<grab(...)|Config::Role::Grab/grab">
See L<refer_to parameter|Config::Model::IdElementReference/"refer_to parameter">.
diff --git a/lib/Config/Model/Cookbook/CreateModelFromDoc.pod b/lib/Config/Model/Cookbook/CreateModelFromDoc.pod
index bdcc24f..1b861db 100644
--- a/lib/Config/Model/Cookbook/CreateModelFromDoc.pod
+++ b/lib/Config/Model/Cookbook/CreateModelFromDoc.pod
@@ -13,7 +13,7 @@ Config::Model::Cookbook::CreateModelFromDoc - Create a configuration model from
=head1 VERSION
-version 2.094
+version 2.095
=head1 Introduction
diff --git a/lib/Config/Model/Describe.pm b/lib/Config/Model/Describe.pm
index a916744..acd84da 100644
--- a/lib/Config/Model/Describe.pm
+++ b/lib/Config/Model/Describe.pm
@@ -9,7 +9,7 @@
#
package Config::Model::Describe;
-$Config::Model::Describe::VERSION = '2.094';
+$Config::Model::Describe::VERSION = '2.095';
use Carp;
use strict;
use warnings;
@@ -182,7 +182,7 @@ Config::Model::Describe - Provide a description of a node element
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
diff --git a/lib/Config/Model/DumpAsData.pm b/lib/Config/Model/DumpAsData.pm
index 00c716f..0b500c3 100644
--- a/lib/Config/Model/DumpAsData.pm
+++ b/lib/Config/Model/DumpAsData.pm
@@ -8,7 +8,7 @@
# The GNU Lesser General Public License, Version 2.1, February 1999
#
package Config::Model::DumpAsData;
-$Config::Model::DumpAsData::VERSION = '2.094';
+$Config::Model::DumpAsData::VERSION = '2.095';
use Carp;
use strict;
use warnings;
@@ -252,7 +252,7 @@ Config::Model::DumpAsData - Dump configuration content as a perl data structure
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
diff --git a/lib/Config/Model/Dumper.pm b/lib/Config/Model/Dumper.pm
index 6800ea0..fed73df 100644
--- a/lib/Config/Model/Dumper.pm
+++ b/lib/Config/Model/Dumper.pm
@@ -8,7 +8,7 @@
# The GNU Lesser General Public License, Version 2.1, February 1999
#
package Config::Model::Dumper;
-$Config::Model::Dumper::VERSION = '2.094';
+$Config::Model::Dumper::VERSION = '2.095';
use Carp;
use strict;
use warnings;
@@ -259,7 +259,7 @@ Config::Model::Dumper - Serialize data of config tree
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
diff --git a/lib/Config/Model/Exception.pm b/lib/Config/Model/Exception.pm
index 99f3144..1500d92 100644
--- a/lib/Config/Model/Exception.pm
+++ b/lib/Config/Model/Exception.pm
@@ -8,7 +8,7 @@
# The GNU Lesser General Public License, Version 2.1, February 1999
#
package Config::Model::Exception;
-$Config::Model::Exception::VERSION = '2.094';
+$Config::Model::Exception::VERSION = '2.095';
use warnings;
use strict;
use Data::Dumper;
@@ -93,19 +93,19 @@ sub full_message {
}
package Config::Model::Exception::Any;
-$Config::Model::Exception::Any::VERSION = '2.094';
+$Config::Model::Exception::Any::VERSION = '2.095';
use Mouse;
extends 'Config::Model::Exception';
package Config::Model::Exception::ModelDeclaration;
-$Config::Model::Exception::ModelDeclaration::VERSION = '2.094';
+$Config::Model::Exception::ModelDeclaration::VERSION = '2.095';
use Mouse;
extends 'Config::Model::Exception::Fatal';
sub _desc {'configuration model declaration error' }
package Config::Model::Exception::User ;
-$Config::Model::Exception::User::VERSION = '2.094';
+$Config::Model::Exception::User::VERSION = '2.095';
use Mouse;
extends 'Config::Model::Exception::Any';
sub _desc {'user error' }
@@ -113,7 +113,7 @@ sub _desc {'user error' }
## old classes below
package Config::Model::Exception::Syntax;
-$Config::Model::Exception::Syntax::VERSION = '2.094';
+$Config::Model::Exception::Syntax::VERSION = '2.095';
use Mouse;
extends 'Config::Model::Exception::Any';
@@ -134,7 +134,7 @@ sub full_message {
}
package Config::Model::Exception::LoadData;
-$Config::Model::Exception::LoadData::VERSION = '2.094';
+$Config::Model::Exception::LoadData::VERSION = '2.095';
use Mouse;
extends 'Config::Model::Exception::User';
@@ -158,7 +158,7 @@ sub full_message {
}
package Config::Model::Exception::Model;
-$Config::Model::Exception::Model::VERSION = '2.094';
+$Config::Model::Exception::Model::VERSION = '2.095';
use Mouse;
extends 'Config::Model::Exception::Fatal';
@@ -191,7 +191,7 @@ sub full_message {
}
package Config::Model::Exception::Load;
-$Config::Model::Exception::Load::VERSION = '2.094';
+$Config::Model::Exception::Load::VERSION = '2.095';
use Mouse;
extends 'Config::Model::Exception::User';
@@ -220,7 +220,7 @@ sub full_message {
}
package Config::Model::Exception::UnavailableElement;
-$Config::Model::Exception::UnavailableElement::VERSION = '2.094';
+$Config::Model::Exception::UnavailableElement::VERSION = '2.095';
use Mouse;
extends 'Config::Model::Exception::User';
@@ -251,7 +251,7 @@ sub full_message {
}
package Config::Model::Exception::AncestorClass;
-$Config::Model::Exception::AncestorClass::VERSION = '2.094';
+$Config::Model::Exception::AncestorClass::VERSION = '2.095';
use Mouse;
extends 'Config::Model::Exception::User';
@@ -259,7 +259,7 @@ sub _desc { 'unknown ancestor class'}
package Config::Model::Exception::ObsoleteElement;
-$Config::Model::Exception::ObsoleteElement::VERSION = '2.094';
+$Config::Model::Exception::ObsoleteElement::VERSION = '2.095';
use Mouse;
extends 'Config::Model::Exception::User';
@@ -275,7 +275,7 @@ sub full_message {
my $msg = $self->description;
my $location = $obj->name;
- my $help = $obj->get_help($element) || '';
+ my $help = $obj->get_help_as_text($element) || '';
$msg .= " '$element' in node '$location'.\n";
$msg .= "\t$help\n";
@@ -284,7 +284,7 @@ sub full_message {
}
package Config::Model::Exception::UnknownElement;
-$Config::Model::Exception::UnknownElement::VERSION = '2.094';
+$Config::Model::Exception::UnknownElement::VERSION = '2.095';
use Carp;
use Mouse;
@@ -359,14 +359,14 @@ sub full_message {
}
package Config::Model::Exception::WarpError;
-$Config::Model::Exception::WarpError::VERSION = '2.094';
+$Config::Model::Exception::WarpError::VERSION = '2.095';
use Mouse;
extends 'Config::Model::Exception::User';
sub _desc { 'warp error'}
package Config::Model::Exception::Fatal;
-$Config::Model::Exception::Fatal::VERSION = '2.094';
+$Config::Model::Exception::Fatal::VERSION = '2.095';
use Mouse;
extends 'Config::Model::Exception::Any';
@@ -374,7 +374,7 @@ sub _desc { 'fatal error' }
package Config::Model::Exception::UnknownId;
-$Config::Model::Exception::UnknownId::VERSION = '2.094';
+$Config::Model::Exception::UnknownId::VERSION = '2.095';
use Mouse;
extends 'Config::Model::Exception::User';
@@ -408,7 +408,7 @@ sub full_message {
}
package Config::Model::Exception::WrongValue;
-$Config::Model::Exception::WrongValue::VERSION = '2.094';
+$Config::Model::Exception::WrongValue::VERSION = '2.095';
use Mouse;
extends 'Config::Model::Exception::User';
@@ -416,7 +416,7 @@ sub _desc { 'wrong value'};
package Config::Model::Exception::WrongType;
-$Config::Model::Exception::WrongType::VERSION = '2.094';
+$Config::Model::Exception::WrongType::VERSION = '2.095';
use Mouse;
extends 'Config::Model::Exception::User';
@@ -447,14 +447,14 @@ sub full_message {
}
package Config::Model::Exception::ConfigFile;
-$Config::Model::Exception::ConfigFile::VERSION = '2.094';
+$Config::Model::Exception::ConfigFile::VERSION = '2.095';
use Mouse;
extends 'Config::Model::Exception::User';
sub _desc { 'error in configuration file' }
package Config::Model::Exception::ConfigFile::Missing;
-$Config::Model::Exception::ConfigFile::Missing::VERSION = '2.094';
+$Config::Model::Exception::ConfigFile::Missing::VERSION = '2.095';
use Mouse;
extends 'Config::Model::Exception::ConfigFile';
@@ -471,14 +471,14 @@ sub full_message {
}
package Config::Model::Exception::Formula;
-$Config::Model::Exception::Formula::VERSION = '2.094';
+$Config::Model::Exception::Formula::VERSION = '2.095';
use Mouse;
extends 'Config::Model::Exception::Model';
sub _desc { 'error in computation formula of the configuration model'}
package Config::Model::Exception::Internal;
-$Config::Model::Exception::Internal::VERSION = '2.094';
+$Config::Model::Exception::Internal::VERSION = '2.095';
use Mouse;
extends 'Config::Model::Exception::Fatal';
@@ -500,7 +500,7 @@ Config::Model::Exception - Exception mechanism for configuration model
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
diff --git a/lib/Config/Model/FuseUI.pm b/lib/Config/Model/FuseUI.pm
index f8420f0..338fcd7 100644
--- a/lib/Config/Model/FuseUI.pm
+++ b/lib/Config/Model/FuseUI.pm
@@ -8,7 +8,7 @@
# The GNU Lesser General Public License, Version 2.1, February 1999
#
package Config::Model::FuseUI;
-$Config::Model::FuseUI::VERSION = '2.094';
+$Config::Model::FuseUI::VERSION = '2.095';
# there's no Singleton with Mouse
use Mouse;
@@ -327,7 +327,7 @@ Config::Model::FuseUI - Fuse virtual file interface for Config::Model
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
diff --git a/lib/Config/Model/HashId.pm b/lib/Config/Model/HashId.pm
index 4070011..2ad94f2 100644
--- a/lib/Config/Model/HashId.pm
+++ b/lib/Config/Model/HashId.pm
@@ -8,18 +8,26 @@
# The GNU Lesser General Public License, Version 2.1, February 1999
#
package Config::Model::HashId;
-$Config::Model::HashId::VERSION = '2.094';
+$Config::Model::HashId::VERSION = '2.095';
use Mouse;
+use 5.10.1;
use Config::Model::Exception;
use Carp;
+use Mouse::Util::TypeConstraints;
+
+subtype 'HaskKeyArray' => as 'ArrayRef' ;
+coerce 'HaskKeyArray' => from 'Str' => via { [$_] } ;
+
use Log::Log4perl qw(get_logger :levels);
my $logger = get_logger("Tree::Element::Id::Hash");
extends qw/Config::Model::AnyId/;
+with "Config::Model::Role::Grab";
+
has data => ( is => 'rw', isa => 'HashRef', default => sub { {}; } );
has list => (
is => 'rw',
@@ -31,8 +39,12 @@ has list => (
}
);
-has [qw/default_keys auto_create_keys/] =>
- ( is => 'rw', isa => 'ArrayRef', default => sub { []; } );
+has [qw/default_keys auto_create_keys/] => (
+ is => 'rw',
+ isa => 'HaskKeyArray',
+ coerce => 1,
+ default => sub { []; }
+);
has [qw/morph ordered/] => ( is => 'ro', isa => 'Bool' );
sub BUILD {
@@ -217,6 +229,21 @@ sub sort {
}
}
+sub insort {
+ my ($self, $id) = @_;
+
+ if ($self->ordered) {
+ my $elt = $self->fetch_with_id($id);
+ $self->_sort;
+ return $elt;
+ }
+ else {
+ Config::Model::Exception::User->throw(
+ object => $self,
+ message => "cannot call insort on non ordered hash"
+ );
+ }
+}
# hash only method
sub firstkey {
@@ -511,7 +538,7 @@ Config::Model::HashId - Handle hash element for configuration model
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
@@ -548,6 +575,16 @@ Returns the number of elements of the hash.
Sort an ordered hash. Throws an error if called on a non ordered hash.
+=head2 insort
+
+Parameters: key
+
+Create a new element in the ordered hash while keeping alphabetical order of the keys
+
+Returns the newly created element.
+
+Throws an error if called on a non ordered hash.
+
=head2 firstkey
Returns the first key of the hash. Behaves like C<each> core perl
diff --git a/lib/Config/Model/IdElementReference.pm b/lib/Config/Model/IdElementReference.pm
index 122db56..fe30c32 100644
--- a/lib/Config/Model/IdElementReference.pm
+++ b/lib/Config/Model/IdElementReference.pm
@@ -8,7 +8,7 @@
# The GNU Lesser General Public License, Version 2.1, February 1999
#
package Config::Model::IdElementReference;
-$Config::Model::IdElementReference::VERSION = '2.094';
+$Config::Model::IdElementReference::VERSION = '2.095';
use Mouse;
use Carp;
@@ -190,7 +190,7 @@ Config::Model::IdElementReference - Refer to id element(s) and extract keys
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
@@ -317,7 +317,7 @@ Construction is handled by the calling object (L<Config::Model::Node>).
C<refer_to> is used to specify a hash element that is used as a
reference. C<refer_to> points to an array or hash element in the
configuration tree using the path syntax (See
-L<Config::Model::Node/grab> for details).
+L<Config::Model::Role::Grab/grab> for details).
=item computed_refer_to
diff --git a/lib/Config/Model/Instance.pm b/lib/Config/Model/Instance.pm
index b6b24a3..8561de7 100644
--- a/lib/Config/Model/Instance.pm
+++ b/lib/Config/Model/Instance.pm
@@ -8,7 +8,7 @@
# The GNU Lesser General Public License, Version 2.1, February 1999
#
package Config::Model::Instance;
-$Config::Model::Instance::VERSION = '2.094';
+$Config::Model::Instance::VERSION = '2.095';
#use Scalar::Util qw(weaken) ;
use strict;
@@ -22,7 +22,6 @@ use Text::Diff;
use File::Path;
use Log::Log4perl qw(get_logger :levels);
-use Config::Model::Annotation;
use Config::Model::Exception;
use Config::Model::Node;
use Config::Model::Loader;
@@ -554,7 +553,7 @@ Config::Model::Instance - Instance of configuration tree
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
@@ -726,6 +725,12 @@ In scalar context, returns a big string. Useful to print.
Print all changes on STDOUT and return the list of changes.
+=head2 clear_changes
+
+Clear list of changes. Note that changes pending in the configuration
+tree is not affected. This clears only the list shown to user. Use
+only for tests.
+
=head2 has_warning
Returns the number of warning found in the elements of this configuration instance.
diff --git a/lib/Config/Model/Iterator.pm b/lib/Config/Model/Iterator.pm
index 7d2bfb0..fff9411 100644
--- a/lib/Config/Model/Iterator.pm
+++ b/lib/Config/Model/Iterator.pm
@@ -8,7 +8,7 @@
# The GNU Lesser General Public License, Version 2.1, February 1999
#
package Config::Model::Iterator;
-$Config::Model::Iterator::VERSION = '2.094';
+$Config::Model::Iterator::VERSION = '2.095';
use Carp;
use strict;
use warnings;
@@ -281,7 +281,7 @@ Config::Model::Iterator - Iterates forward or backward a configuration tree
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
diff --git a/lib/Config/Model/ListId.pm b/lib/Config/Model/ListId.pm
index 6f2665b..98acce9 100644
--- a/lib/Config/Model/ListId.pm
+++ b/lib/Config/Model/ListId.pm
@@ -8,7 +8,7 @@
# The GNU Lesser General Public License, Version 2.1, February 1999
#
package Config::Model::ListId;
-$Config::Model::ListId::VERSION = '2.094';
+$Config::Model::ListId::VERSION = '2.095';
use 5.10.1;
use Mouse;
@@ -18,6 +18,8 @@ use Log::Log4perl qw(get_logger :levels);
use Carp;
extends qw/Config::Model::AnyId/;
+with "Config::Model::Role::Grab";
+
my $logger = get_logger("Tree::Element::Id::List");
has data => (
@@ -502,7 +504,7 @@ Config::Model::ListId - Handle list element for configuration model
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
diff --git a/lib/Config/Model/Lister.pm b/lib/Config/Model/Lister.pm
index 33abe41..7aaf7fd 100644
--- a/lib/Config/Model/Lister.pm
+++ b/lib/Config/Model/Lister.pm
@@ -8,7 +8,7 @@
# The GNU Lesser General Public License, Version 2.1, February 1999
#
package Config::Model::Lister;
-$Config::Model::Lister::VERSION = '2.094';
+$Config::Model::Lister::VERSION = '2.095';
use strict;
use warnings;
use Exporter;
@@ -85,7 +85,7 @@ Config::Model::Lister - List available models and applications
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
diff --git a/lib/Config/Model/Loader.pm b/lib/Config/Model/Loader.pm
index 06d7a6c..7e7b425 100644
--- a/lib/Config/Model/Loader.pm
+++ b/lib/Config/Model/Loader.pm
@@ -8,7 +8,7 @@
# The GNU Lesser General Public License, Version 2.1, February 1999
#
package Config::Model::Loader;
-$Config::Model::Loader::VERSION = '2.094';
+$Config::Model::Loader::VERSION = '2.095';
use Carp;
use strict;
use warnings;
@@ -409,22 +409,28 @@ sub _load_check_list {
# function_args are the arguments passed to the load command
my %dispatch_action = (
list_leaf => {
- ':.sort' => sub { $_[1]->sort; },
- ':.push' => sub { $_[1]->push( @_[ 4 .. $#_ ] ); },
- ':.unshift' => sub { $_[1]->unshift( @_[ 4 .. $#_ ] ); },
- ':.insert_at' => sub { $_[1]->insert_at( @_[ 4 .. $#_ ] ); },
- ':.insort' => sub { $_[1]->insort( @_[ 4 .. $#_ ] ); },
+ ':.sort' => sub { $_[1]->sort; return 'ok';},
+ ':.push' => sub { $_[1]->push( @_[ 5 .. $#_ ] ); return 'ok'; },
+ ':.unshift' => sub { $_[1]->unshift( @_[ 5 .. $#_ ] ); return 'ok'; },
+ ':.insert_at' => sub { $_[1]->insert_at( @_[ 5 .. $#_ ] ); return 'ok'; },
+ ':.insort' => sub { $_[1]->insort( @_[ 5 .. $#_ ] ); return 'ok'; },
':.insert_before' => \&_insert_before,
},
'list_*' => {
- ':.copy' => sub { $_[1]->copy( $_[4], $_[5] ); },
- ':.clear' => sub { $_[1]->clear;},
+ ':.copy' => sub { $_[1]->copy( $_[5], $_[6] ); return 'ok'; },
+ ':.clear' => sub { $_[1]->clear; return 'ok'; },
+ },
+ hash_leaf => {
+ ':.insort' => sub { $_[1]->insort($_[5])->store($_[6]); return 'ok'; },
+ },
+ hash_node => => {
+ ':.insort' => \&_insort_hash_of_node,
},
'hash_*' => {
- ':.sort' => sub { $_[1]->sort; },
- ':@' => sub { $_[1]->sort; },
- ':.copy' => sub { $_[1]->copy( $_[4], $_[5] ); },
- ':.clear' => sub { $_[1]->clear;},
+ ':.sort' => sub { $_[1]->sort; return 'ok'; },
+ ':@' => sub { $_[1]->sort; return 'ok'; },
+ ':.copy' => sub { $_[1]->copy( $_[5], $_[6] ); return 'ok'; },
+ ':.clear' => sub { $_[1]->clear; return 'ok';},
},
leaf => {
':-=' => \&_remove_by_value,
@@ -434,7 +440,8 @@ my %dispatch_action = (
fallback => {
':-' => \&_remove_by_id,
'~' => \&_remove_by_id,
- } );
+ }
+);
my @equiv = qw/:@ :.sort :< :.push :> :.unshift/;
while (@equiv) {
@@ -443,20 +450,21 @@ while (@equiv) {
}
sub _insert_before {
- my ( $self, $element, $check, $inst, $before_str, @values ) = @_;
+ my ( $self, $element, $check, $inst, $cmdref, $before_str, @values ) = @_;
my $before = $before_str =~ m!^/! ? eval "qr$before_str" : $before_str;
$element->insert_before( $before, @values );
+ return 'ok';
}
sub _remove_by_id {
- my ( $self, $element, $check, $inst, $id ) = @_;
- $logger->debug("_remove_by_id: removing id $id");
+ my ( $self, $element, $check, $inst, $cmdref, $id ) = @_;
+ $logger->debug("_remove_by_id: removing id '$id'");
$element->remove($id);
return 'ok';
}
sub _remove_by_value {
- my ( $self, $element, $check, $inst, $rm_val ) = @_;
+ my ( $self, $element, $check, $inst, $cmdref, $rm_val ) = @_;
$logger->debug("_remove_by_value value $rm_val");
foreach my $idx ( $element->fetch_all_indexes ) {
@@ -468,7 +476,7 @@ sub _remove_by_value {
}
sub _remove_matched_value {
- my ( $self, $element, $check, $inst, $rm_val ) = @_;
+ my ( $self, $element, $check, $inst, $cmdref, $rm_val ) = @_;
$logger->debug("_remove_matched_value $rm_val");
@@ -483,7 +491,7 @@ sub _remove_matched_value {
}
sub _substitute_value {
- my ( $self, $element, $check, $inst, $s_val ) = @_;
+ my ( $self, $element, $check, $inst, $cmdref, $s_val ) = @_;
$logger->debug("_substitute_value $s_val");
@@ -495,6 +503,13 @@ sub _substitute_value {
return 'ok';
}
+sub _insort_hash_of_node {
+ my ( $self, $element, $check, $inst, $cmdref, $id ) = @_;
+ my $node = $element->insort($_[5]);
+ $logger->debug("_insort_hash_of_node: calling _load on node id $id");
+ return $self->_load( $node, $check, $cmdref );
+}
+
sub _load_list {
my ( $self, $node, $check, $inst, $cmdref ) = @_;
my ( $element_name, $action, $f_arg, $id, $subaction, $value, $note ) = @$inst;
@@ -544,8 +559,7 @@ sub _load_list {
|| $dispatch_action{$cargo_type}{$action}
|| $dispatch_action{'fallback'}{$action};
if ($dispatch) {
- $dispatch->( $self, $element, $check, $inst, @f_args );
- return 'ok';
+ return $dispatch->( $self, $element, $check, $inst, $cmdref, @f_args );
}
}
@@ -660,11 +674,18 @@ sub _load_hash {
|| $dispatch_action{'fallback'}{$action};
if ($dispatch) {
# todo missing arguments
- $dispatch->( $self, $element, $check, $inst, @f_args );
- return 'ok';
+ return $dispatch->( $self, $element, $check, $inst, $cmdref, @f_args );
}
}
+ if (not defined $id) {
+ Config::Model::Exception::Load->throw(
+ object => $element,
+ command => join( '', @$inst ),
+ error => qq!Unexpected hash instruction: '$action' or missing id!
+ );
+ }
+
my $obj = $element->fetch_with_id( index => $id, check => $check );
$self->_load_note( $obj, $note, $inst, $cmdref );
@@ -805,7 +826,7 @@ Config::Model::Loader - Load serialized data into config tree
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
@@ -1034,6 +1055,23 @@ Insert C<zz> value on C<xxx> list before B<value> matching C<yy>.
Insert C<zz> value on C<xxx> list so that existing alphanumeric order is preserved.
+=item xxx:.insort(zz)
+
+For hash element containing nodes: creates a new hash element with
+C<zz> key on C<xxx> hash so that existing alphanumeric order of keys
+is preserved. Note that all keys are sorted once this instruction is
+called. Following instructions are applied on the created
+element. I.e. putting key order aside, C<xxx:.insort(zz)> has the
+same effect as C<xxx:zz> instruction.
+
+=item xxx:.insort(zz,vv)
+
+For hash element containing leaves: creates a new hash element with
+C<zz> key and assing value C<vv> so that existing alphanumeric order of keys
+is preserved. Note that all keys are sorted once this instruction is
+called. Putting key order aside, C<xxx:.insort(zz,vv)> has the
+same effect as C<xxx:zz=vv> instruction.
+
=item xxx:=z1,z2,z3
Set list element C<xxx> to list C<z1,z2,z3>. Use C<,,> for undef
diff --git a/lib/Config/Model/Manual/ModelCreationAdvanced.pod b/lib/Config/Model/Manual/ModelCreationAdvanced.pod
index 833f2fa..4babc1c 100644
--- a/lib/Config/Model/Manual/ModelCreationAdvanced.pod
+++ b/lib/Config/Model/Manual/ModelCreationAdvanced.pod
@@ -13,7 +13,7 @@ Config::Model::Manual::ModelCreationAdvanced - Creating a model with advanced fe
=head1 VERSION
-version 2.094
+version 2.095
=head1 Introduction
diff --git a/lib/Config/Model/Manual/ModelCreationIntroduction.pod b/lib/Config/Model/Manual/ModelCreationIntroduction.pod
index 7f92d7d..62303a8 100644
--- a/lib/Config/Model/Manual/ModelCreationIntroduction.pod
+++ b/lib/Config/Model/Manual/ModelCreationIntroduction.pod
@@ -13,7 +13,7 @@ Config::Model::Manual::ModelCreationIntroduction - Introduction to model creatio
=head1 VERSION
-version 2.094
+version 2.095
=head1 Introduction
diff --git a/lib/Config/Model/Node.pm b/lib/Config/Model/Node.pm
index 239b139..c899167 100644
--- a/lib/Config/Model/Node.pm
+++ b/lib/Config/Model/Node.pm
@@ -8,7 +8,7 @@
# The GNU Lesser General Public License, Version 2.1, February 1999
#
package Config::Model::Node;
-$Config::Model::Node::VERSION = '2.094';
+$Config::Model::Node::VERSION = '2.095';
use Mouse;
with "Config::Model::Role::NodeLoader";
@@ -29,6 +29,9 @@ use List::MoreUtils qw(insert_after_string);
extends qw/Config::Model::AnyThing/;
+with "Config::Model::Role::Grab";
+with "Config::Model::Role::HelpAsText";
+
use vars qw(@status @level %default_property);
*status = *Config::Model::status;
@@ -312,6 +315,7 @@ sub check_properties {
sub init {
my $self = shift;
+ my %args = @_;
return if $self->{initialized};
$self->{initialized} = 1; # avoid recursions
@@ -332,7 +336,7 @@ sub init {
);
if ( defined $model->{read_config} ) {
- $self->read_config_data( check => $self->check );
+ $self->read_config_data( check => $args{check} // $self->check );
}
# use read_config data if write_config is missing
@@ -650,7 +654,7 @@ sub fetch_element {
my $check = $self->_check_check( $args{check} );
my $accept_hidden = $args{accept_hidden} || 0;
- $self->init();
+ $self->init(check => $check);
my $model = $self->{model};
@@ -1080,6 +1084,8 @@ sub copy_from {
$self->load( step => $dump, check => $check );
}
+# TODO: need Pod::Text attribute -> move that to a role ?
+# to translate Pod description to plain text when help is displayed
sub get_help {
my $self = shift;
@@ -1203,7 +1209,7 @@ Config::Model::Node - Class for configuration tree node
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
@@ -1751,17 +1757,17 @@ Returns 1 if the element is known in the model.
Returns 1 if the element is defined.
-=head2 grab(...)
+=head2 grab
-See L<Config::Model::AnyThing/"grab(...)">.
+See L<Config::Model::Role::Grab/grab">.
-=head2 grab_value(...)
+=head2 grab_value
-See L<Config::Model::AnyThing/"grab_value(...)">.
+See L<Config::Model::Role::Grab/grab_value">.
-=head2 grab_root()
+=head2 grab_root
-See L<Config::Model::AnyThing/"grab_root()">.
+See L<Config::Model::Role::Grab/"grab_root">.
=head2 get( path => ..., mode => ... , check => ... , get_obj => 1|0, autoadd => 1|0)
diff --git a/lib/Config/Model/ObjTreeScanner.pm b/lib/Config/Model/ObjTreeScanner.pm
index 6594da7..7f85e32 100644
--- a/lib/Config/Model/ObjTreeScanner.pm
+++ b/lib/Config/Model/ObjTreeScanner.pm
@@ -8,7 +8,7 @@
# The GNU Lesser General Public License, Version 2.1, February 1999
#
package Config::Model::ObjTreeScanner;
-$Config::Model::ObjTreeScanner::VERSION = '2.094';
+$Config::Model::ObjTreeScanner::VERSION = '2.095';
use strict;
use Config::Model::Exception;
use Scalar::Util qw/blessed/;
@@ -285,7 +285,7 @@ Config::Model::ObjTreeScanner - Scan config tree and perform call-backs for each
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
diff --git a/lib/Config/Model/Report.pm b/lib/Config/Model/Report.pm
index d39b33f..d4d7a7e 100644
--- a/lib/Config/Model/Report.pm
+++ b/lib/Config/Model/Report.pm
@@ -8,7 +8,7 @@
# The GNU Lesser General Public License, Version 2.1, February 1999
#
package Config::Model::Report;
-$Config::Model::Report::VERSION = '2.094';
+$Config::Model::Report::VERSION = '2.095';
use Carp;
use strict;
use warnings;
@@ -44,11 +44,11 @@ sub report {
if ( defined $value ) {
my $name = defined $index ? " $element:$index" : $element;
push @$data_r, $obj->location . " $name = $value";
- my $desc = $obj->get_help($element);
+ my $desc = $obj->get_help_as_text($element);
if ( defined $desc and $desc ) {
push @$data_r, wrap( "\t", "\t\t", "DESCRIPTION: $desc" );
}
- my $effect = $value_obj->get_help($value);
+ my $effect = $value_obj->get_help_as_text($value);
if ( defined $effect and $effect ) {
push @$data_r, wrap( "\t", "\t\t", "SELECTED: $effect" );
}
@@ -90,7 +90,7 @@ Config::Model::Report - Reports data from config tree
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
diff --git a/lib/Config/Model/AnyThing.pm b/lib/Config/Model/Role/Grab.pm
similarity index 53%
copy from lib/Config/Model/AnyThing.pm
copy to lib/Config/Model/Role/Grab.pm
index 1678eb5..3ab81cb 100644
--- a/lib/Config/Model/AnyThing.pm
+++ b/lib/Config/Model/Role/Grab.pm
@@ -7,228 +7,19 @@
#
# The GNU Lesser General Public License, Version 2.1, February 1999
#
-package Config::Model::AnyThing;
-$Config::Model::AnyThing::VERSION = '2.094';
-use Mouse;
+package Config::Model::Role::Grab;
+$Config::Model::Role::Grab::VERSION = '2.095';
+# ABSTRACT: Role to grab data from elsewhere in the tree
-# FIXME: must cleanup warp mechanism to implement this
-# use MouseX::StrictConstructor;
-
-use Pod::POM;
+use Mouse::Role;
+use strict;
+use warnings;
use Carp;
-use Log::Log4perl qw(get_logger :levels);
-use 5.10.1;
-
-my $logger = get_logger("Anything");
-my $change_logger = get_logger("ChangeTracker");
-
-has element_name => ( is => 'ro', isa => 'Str' );
-has parent => ( is => 'ro', isa => 'Config::Model::Node', weak_ref => 1 );
-
-has instance => (
- is => 'ro',
- isa => 'Config::Model::Instance',
- weak_ref => 1,
- handles => [qw/show_message/]
-);
-
-# needs_check defaults to 1 to trap undef mandatory values
-has needs_check => ( is => 'rw', isa => 'Bool', default => 1 );
-
-# index_value can be written to when move method is called. But let's
-# not advertise this feature.
-has index_value => (
- is => 'rw',
- isa => 'Str',
- trigger => sub { my $self = shift; $self->{location} = $self->_location; },
-);
-
-has container => ( is => 'ro', isa => 'Ref', required => 1, weak_ref => 1 );
-
-has container_type => ( is => 'ro', isa => 'Str', builder => '_container_type', lazy => 1 );
-
-sub _container_type {
- my $self = shift;
- my $p = $self->parent;
- return defined $p
- ? $p->element_type( $self->element_name )
- : 'node'; # root node
-
-}
-
-has root => (
- is => 'ro',
- isa => 'Config::Model::Node',
- weak_ref => 1,
- builder => '_root',
- lazy => 1
-);
-
-sub _root {
- my $self = shift;
-
- return $self->parent || $self;
-}
-
-has location => ( is => 'ro', isa => 'Str', builder => '_location', lazy => 1 );
-has location_short => ( is => 'ro', isa => 'Str', builder => '_location_short', lazy => 1 );
-
-has backend_support_annotation => (
- is => 'ro',
- isa => 'Bool',
- builder => '_backend_support_annotation',
- lazy => 1
-);
-
-sub _backend_support_annotation {
- my $self = shift;
- # this method is overridden in Config::Model::Node
- return $self->parent->backend_support_annotation;
-};
-
-sub notify_change {
- my $self = shift;
- my %args = @_;
-
- return if $self->instance->initial_load and not $args{really};
-
- $change_logger->debug( "called for ", $self->name, " from ", join( ' ', caller ),
- " with ", join( ' ', %args ) )
- if $change_logger->is_debug;
-
- # needs_save may be overridden by caller
- $args{needs_save} //= 1;
- $args{path} //= $self->location;
- $args{name} //= $self->element_name if $self->element_name;
- $args{index} //= $self->index_value if $self->index_value;
-
- # better use %args instead of @_ to forward arguments. %args eliminates duplicated keys
- $self->container->notify_change(%args);
-}
-
-sub _location {
- my $self = shift;
-
- my $str = '';
- $str .= $self->parent->location if defined $self->parent;
-
- $str .= ' ' if $str;
-
- $str .= $self->composite_name;
-
- return $str;
-}
-
-sub _location_short {
- my $self = shift;
-
- my $str = '';
- $str .= $self->parent->location_short if defined $self->parent;
-
- $str .= ' ' if $str;
-
- $str .= $self->composite_name_short;
-
- return $str;
-}
-
-#has composite_name => (is => 'ro', isa => 'Str' , builder => '_composite_name', lazy => 1);
-
-sub composite_name {
- my $self = shift;
- my $element = $self->element_name;
- $element = '' unless defined $element;
-
- my $idx = $self->index_value;
- return $element unless defined $idx;
- $idx = '"' . $idx . '"' if $idx =~ /\W/;
-
- return "$element:$idx";
-}
-
-sub composite_name_short {
- my $self = shift;
-
- my $element = $self->element_name;
- $element = '' unless defined $element;
-
-
- my $idx = $self->shorten_idx($self->index_value);
- return $element unless length $idx;
- $idx = '"' . $idx . '"' if $idx =~ /\W/;
- return "$element:$idx";
-}
-
-sub shorten_idx {
- my $self = shift;
- my $long_index = shift ;
-
- my @idx = split /\n/, $long_index // '' ;
- my $idx = shift @idx;
- $idx .= '[...]' if @idx;
-
- return $idx // ''; # may be undef on freebsd with perl 5.10.1 ...
-}
-
-
-## Fixme: not yet tested
-sub xpath {
- my $self = shift;
-
- $logger->debug("xpath called on $self");
-
- my $element = $self->element_name;
- $element = '' unless defined $element;
-
- my $idx = $self->index_value;
-
- my $str = '';
- $str .= $self->cim_parent->parent->xpath
- if $self->can('cim_parent')
- and defined $self->cim_parent;
-
- $str .= '/' . $element . ( defined $idx ? "[\@id=$idx]" : '' ) if $element;
-
- return $str;
-}
-
-sub annotation {
- my $self = shift;
- $self->{annotation} = join( "\n", grep ( defined $_, @_ ) )
- if @_
- and not $self->instance->preset
- and not $self->instance->layered;
- return $self->{annotation} || '';
-}
-
-sub clear_annotation {
- my $self = shift;
- $self->{annotation} = '';
-}
+use Mouse::Util;
+use Log::Log4perl qw(get_logger :levels);
-sub load_pod_annotation {
- my $self = shift;
- my $pod = shift;
-
- my $parser = Pod::POM->new();
- my $pom = $parser->parse_text($pod)
- || croak $parser->error();
- my $sections = $pom->head1();
-
- foreach my $s (@$sections) {
- next unless $s->title eq 'Annotations';
-
- foreach my $item ( $s->over->[0]->item ) {
- my $path = $item->title . ''; # force string representation. Not understood why...
- $path =~ s/^[\s\*]+//;
- my $note = $item->text . '';
- $note =~ s/\s+$//;
- $logger->debug("load_pod_annotation: '$path' -> '$note'");
- $self->grab( steps => $path )->annotation($note);
- }
- }
-}
+my $logger = get_logger("Grab");
## Navigation
@@ -563,86 +354,6 @@ sub grab_ancestor_with_element_named {
}
}
-# fallback method for object that don't implement has_data
-sub has_data {
- my $self= shift;
- $logger->debug("called fall-back has_data for element", $self->name) if $logger->is_debug;
- return 1;
-}
-
-sub model_searcher {
- my $self = shift;
- my %args = @_;
-
- my $model = $self->instance->config_model;
- return Config::Model::SearchElement->new( model => $model, node => $self, %args );
-}
-
-sub searcher {
- carp "Config::Model::AnyThing searcher is deprecated";
- goto &model_searcher;
-}
-
-sub dump_as_data {
- my $self = shift;
- my $dumper = Config::Model::DumpAsData->new;
- $dumper->dump_as_data( node => $self, @_ );
-}
-
-# hum, check if the check information is valid
-sub _check_check {
- my $self = shift;
- my $p = shift;
-
- return 'yes' if not defined $p or $p eq '1' or $p eq 'yes';
- return 'no' if $p eq '0' or $p eq 'no';
- return $p if $p eq 'skip';
-
- croak "Internal error: Unvalid check value: $p";
-}
-
-sub has_fixes {
- my $self = shift;
- $logger->debug( "dummy has_fixes called on " . $self->name );
- return 0;
-}
-
-sub has_warning {
- my $self = shift;
- $logger->debug( "dummy has_warning called on " . $self->name );
- return 0;
-}
-
-sub warp_error {
- my $self = shift;
- return '' unless defined $self->{warper};
- return $self->{warper}->warp_error;
-}
-
-# used by Value and AnyId
-sub set_convert {
- my ( $self, $arg_ref ) = @_;
-
- my $convert = delete $arg_ref->{convert};
-
- # convert_sub keeps a subroutine reference
- $self->{convert_sub} =
- $convert eq 'uc' ? sub { uc(shift) }
- : $convert eq 'lc' ? sub { lc(shift) }
- : undef;
-
- Config::Model::Exception::Model->throw(
- object => $self,
- error => "Unexpected convert value: $convert, " . "expected lc or uc"
- ) unless defined $self->{convert_sub};
-}
-
-__PACKAGE__->meta->make_immutable;
-
-1;
-
-# ABSTRACT: Base class for configuration tree item
-
__END__
=pod
@@ -651,114 +362,25 @@ __END__
=head1 NAME
-Config::Model::AnyThing - Base class for configuration tree item
+Config::Model::Role::Grab - Role to grab data from elsewhere in the tree
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
- # internal class
+ $self->load_node( config_class_name => "...", %other_args);
=head1 DESCRIPTION
-This class must be inherited by all nodes or leaves of the
-configuration tree.
-
-AnyThing provides some methods and no constructor.
-
-=head1 Introspection methods
-
-=head2 element_name()
-
-Returns the element name that contain this object.
-
-=head2 index_value()
-
-For object stored in an array or hash element, returns the index (or key)
-containing this object.
-
-=head2 parent()
-
-Returns the node containing this object. May return undef if C<parent()>
-is called on the root of the tree.
-
-=head2 container_type()
-
-Returns the type (e.g. C<list> or C<hash> or C<leaf> or C<node> or
-C<warped_node>) of the element containing this object.
-
-=head2 root()
-
-Returns the root node of the configuration tree.
-
-=head2 location()
-
-Returns the node location in the configuration tree. This location
-conforms with the syntax defined by L</grab()> method.
-
-=head2 location_short()
-
-Returns the node location in the configuration tree. This location truncates long
-indexes to be readable. It cannot be used by L</grab()> method.
-
-=head2 composite_name
-
-Return the element name with its index (if any). I.e. returns C<foo:bar> or
-C<foo>.
-
-=head2 composite_name_short
-
-Return the element name with its index (if any). Too long indexes are
-truncated to be readable.
-
-=head1 Annotation
-
-Annotation is a way to store miscellaneous information associated to
-each node. (Yeah... comments). Reading and writing annotation makes
-sense only if they can be read from and written to the configuration
-file, hence the need for the following method:
-
-=head2 backend_support_annotation
+Role used to let a tree item (i.e. node, hash, list or leaf) to grab
+another item or value from the configuration tree using a path (a bit
+like an xpath path with a different syntax).
-Returns 1 if at least one of the backends attached to a parent node
-support to read and write annotations (aka comments) in the
-configuration file.
+=head1 METHODS
-=head2 support_annotation
-
-Returns 1 if at least one of the backends support to read and write annotations
-(aka comments) in the configuration file.
-
-=head2 annotation( [ note1, [ note2 , ... ] ] )
-
-Without argument, return a string containing the object's annotation (or
-an empty string).
-
-With several arguments, join the arguments with "\n", store the annotations
-and return the resulting string.
-
-=head2 load_pod_annotation ( pod_string )
-
-Load annotations in configuration tree from a pod document. The pod must
-be in the form:
-
- =over
-
- =item path
-
- Annotation text
-
- =back
-
-=head2 clear_annotation
-
-Clear the annotation of an element
-
-=head1 Information management
-
-=head2 grab(...)
+=head2 grab
Grab an object from the configuration tree.
@@ -841,104 +463,33 @@ considered when going up the tree.
=back
-=head2 grab_value(...)
+=head2 grab_value
-Like L</grab(...)>, but returns the value of a leaf or check_list object, not
+Like L</grab>, but returns the value of a leaf or check_list object, not
just the leaf object.
C<grab_value> raises an exception if following the steps ends on anything but a
leaf or a check_list.
-=head2 grab_annotation(...)
+=head2 grab_annotation
-Like L</grab(...)>, but returns the annotation of an object.
+Like L</grab>, but returns the annotation of an object.
-=head2 grab_root()
+=head2 grab_root
Returns the root of the configuration tree.
-=head2 grab_ancestor( Foo )
-
-Go up the configuration tree until the C<Foo> configuration class is found. Returns
-the found node or undef.
-
-=head2 notify_change(...)
-
-Notify the instance of semantic changes. Parameters are:
-
-=over 8
-
-=item old
-
-old value. (optional)
-
-=item new
-
-new value (optional)
-
-=item path
-
-Location of the changed parameter starting from root node. Default to C<$self->location>.
-
-=item name
+=head2 grab_ancestor
-element name. Default to C<$self->element_name>
-
-=item index
-
-If the changed parameter is part of a hash or an array, C<index>
-contains the key or the index to get the changed parameter.
-
-=item note
-
-information about the change. Mandatory of neither old or new value are defined.
-
-=item really
-
-When set to 1, force recording of change even if in initial load phase.
-
-=item needs_save
-
-internal parameter.
-
-=back
-
-=head2 show_message( string )
-
-Forwarded to L<Config::Model::Instance/"show_message( string )">.
-
-=head2 model_searcher ()
-
-Returns an object dedicated to search an element in the configuration
-model (respecting privilege level).
-
-This method returns a L<Config::Model::SearchElement> object. See
-L<Config::Model::Searcher> for details on how to handle a search.
-
-=head2 dump_as_data ( )
-
-Dumps the configuration data of the node and its siblings into a perl
-data structure.
-
-Returns a hash ref containing the data. See
-L<Config::Model::DumpAsData> for details.
-
-=head2 warp_error
-
-Returns a string describing any issue with L<Config::Model::Warper> object.
-Returns '' if invoked on a tree object without warp specification.
-
-=head1 AUTHOR
+Parameter: a configuration class name
-Dominique Dumont, (ddumont at cpan dot org)
+Go up the configuration tree until a node using the configuration
+class is found. Returns the found node or undef.
-=head1 SEE ALSO
+Example:
-L<Config::Model>,
-L<Config::Model::Instance>,
-L<Config::Model::Node>,
-L<Config::Model::Loader>,
-L<Config::Model::Dumper>
+ # returns a Config::Model::Node object for a Systemd::Service config class
+ $self->grab('Systemd::Service');
=head1 AUTHOR
diff --git a/lib/Config/Model/Role/HelpAsText.pm b/lib/Config/Model/Role/HelpAsText.pm
new file mode 100644
index 0000000..706b8b6
--- /dev/null
+++ b/lib/Config/Model/Role/HelpAsText.pm
@@ -0,0 +1,97 @@
+#
+# This file is part of Config-Model
+#
+# This software is Copyright (c) 2005-2016 by Dominique Dumont.
+#
+# This is free software, licensed under:
+#
+# The GNU Lesser General Public License, Version 2.1, February 1999
+#
+package Config::Model::Role::HelpAsText;
+$Config::Model::Role::HelpAsText::VERSION = '2.095';
+# ABSTRACT: Transalet element help from pod to text
+
+use Mouse::Role;
+use strict;
+use warnings;
+use Pod::Text;
+use Pod::Simple 3.23;
+use 5.10.1;
+
+requires('get_help');
+
+sub get_help_as_text {
+ my $self = shift;
+
+ my $pod = $self->get_help(@_) ;
+ return undef unless defined $pod;
+
+ my $parser = Pod::Text->new(
+ indent => 0,
+ nourls => 1,
+ );
+
+ # require Pod::Simple 3.23
+ $parser->parse_characters('utf8');
+
+ my $output = '';
+ $parser->output_string(\$output);
+
+ $parser->parse_string_document("=pod\n\n" . $pod);
+ $output =~ s/[\n\s]+$//;
+
+ return $output;
+}
+
+1;
+
+__END__
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Config::Model::Role::HelpAsText - Transalet element help from pod to text
+
+=head1 VERSION
+
+version 2.095
+
+=head1 SYNOPSIS
+
+ $self->get_help_as_text( ... );
+
+=head1 DESCRIPTION
+
+Role used to translate Config::Model help text or description from pod
+to text. The provided method should be used when the help text should
+be displayed on STDOUT.
+
+This functionality is provided as a role because the interface to
+L<Pod::Text> is not so easy.
+
+=head1 METHODS
+
+=head2 get_help_as_text
+
+Calls C<get_help> and tranlate the output to text.
+
+=head2 SEE ALSO
+
+L<Pod::Text>, L<Pod::Simple>
+
+=head1 AUTHOR
+
+Dominique Dumont
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is Copyright (c) 2005-2016 by Dominique Dumont.
+
+This is free software, licensed under:
+
+ The GNU Lesser General Public License, Version 2.1, February 1999
+
+=cut
diff --git a/lib/Config/Model/Role/NodeLoader.pm b/lib/Config/Model/Role/NodeLoader.pm
index 8a5395e..1947592 100644
--- a/lib/Config/Model/Role/NodeLoader.pm
+++ b/lib/Config/Model/Role/NodeLoader.pm
@@ -8,7 +8,7 @@
# The GNU Lesser General Public License, Version 2.1, February 1999
#
package Config::Model::Role::NodeLoader;
-$Config::Model::Role::NodeLoader::VERSION = '2.094';
+$Config::Model::Role::NodeLoader::VERSION = '2.095';
# ABSTRACT: Load Node element in configuration tree
use Mouse::Role;
@@ -44,7 +44,7 @@ Config::Model::Role::NodeLoader - Load Node element in configuration tree
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
diff --git a/lib/Config/Model/Role/WarpMaster.pm b/lib/Config/Model/Role/WarpMaster.pm
index e501dc7..8a99d37 100644
--- a/lib/Config/Model/Role/WarpMaster.pm
+++ b/lib/Config/Model/Role/WarpMaster.pm
@@ -8,7 +8,7 @@
# The GNU Lesser General Public License, Version 2.1, February 1999
#
package Config::Model::Role::WarpMaster;
-$Config::Model::Role::WarpMaster::VERSION = '2.094';
+$Config::Model::Role::WarpMaster::VERSION = '2.095';
# ABSTRACT: register and trigger a warped element
use Mouse::Role;
@@ -106,7 +106,7 @@ Config::Model::Role::WarpMaster - register and trigger a warped element
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
diff --git a/lib/Config/Model/SearchElement.pm b/lib/Config/Model/SearchElement.pm
index a601043..146acee 100644
--- a/lib/Config/Model/SearchElement.pm
+++ b/lib/Config/Model/SearchElement.pm
@@ -8,7 +8,7 @@
# The GNU Lesser General Public License, Version 2.1, February 1999
#
package Config::Model::SearchElement;
-$Config::Model::SearchElement::VERSION = '2.094';
+$Config::Model::SearchElement::VERSION = '2.095';
use Log::Log4perl qw(get_logger :levels);
use Carp;
use strict;
@@ -333,7 +333,7 @@ Config::Model::SearchElement - Search an element in a configuration model
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
diff --git a/lib/Config/Model/SimpleUI.pm b/lib/Config/Model/SimpleUI.pm
index 465c1c9..d397181 100644
--- a/lib/Config/Model/SimpleUI.pm
+++ b/lib/Config/Model/SimpleUI.pm
@@ -8,7 +8,7 @@
# The GNU Lesser General Public License, Version 2.1, February 1999
#
package Config::Model::SimpleUI;
-$Config::Model::SimpleUI::VERSION = '2.094';
+$Config::Model::SimpleUI::VERSION = '2.095';
use Carp;
use 5.010;
use strict;
@@ -52,10 +52,14 @@ my $desc_sub = sub {
if (@_) {
my $item;
while ( $item = shift ) {
- if ( $obj->isa('Config::Model::Node') ) {
+ if ( $obj->get_type() eq 'node' ) {
my $type = $obj->element_type($item);
my $elt = $obj->fetch_element($item);
- $res .= "element $item (type $type): " . $obj->get_help($item) . "\n";
+ my $help = $obj->get_help_as_text($item);
+ $res .= "element $item (type $type)";
+ $res .= ": " if $help;
+ $res .= "\n" if $help =~ /\n/ or length($help) > 40 ;
+ $res .= $help . "\n" if $help;
if ( $type eq 'leaf' and $elt->value_type eq 'enum' ) {
$res .= " possible values: " . join( ', ', $elt->get_choice ) . "\n";
}
@@ -63,7 +67,7 @@ my $desc_sub = sub {
}
}
else {
- $res = $obj->get_help();
+ $res = $obj->get_help_as_text();
}
return $res;
};
@@ -330,7 +334,7 @@ Config::Model::SimpleUI - Simple interface for Config::Model
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
diff --git a/lib/Config/Model/TermUI.pm b/lib/Config/Model/TermUI.pm
index a9bcf50..4a47e11 100644
--- a/lib/Config/Model/TermUI.pm
+++ b/lib/Config/Model/TermUI.pm
@@ -8,7 +8,7 @@
# The GNU Lesser General Public License, Version 2.1, February 1999
#
package Config::Model::TermUI;
-$Config::Model::TermUI::VERSION = '2.094';
+$Config::Model::TermUI::VERSION = '2.095';
use Carp;
use utf8; # so literals and identifiers can be in UTF-8
use v5.12; # or later to get "unicode_strings" feature
@@ -228,7 +228,7 @@ Config::Model::TermUI - Interactive command line interface for cme
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
diff --git a/lib/Config/Model/TreeSearcher.pm b/lib/Config/Model/TreeSearcher.pm
index 5ac6629..8bdc931 100644
--- a/lib/Config/Model/TreeSearcher.pm
+++ b/lib/Config/Model/TreeSearcher.pm
@@ -8,7 +8,7 @@
# The GNU Lesser General Public License, Version 2.1, February 1999
#
package Config::Model::TreeSearcher;
-$Config::Model::TreeSearcher::VERSION = '2.094';
+$Config::Model::TreeSearcher::VERSION = '2.095';
use Mouse;
use Mouse::Util::TypeConstraints;
@@ -147,7 +147,7 @@ Config::Model::TreeSearcher - Search tree for match in value, description...
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
@@ -225,7 +225,7 @@ Search in all the items above
Search the keyword or pattern in the tree. The search is done in a case
insensitive manner. Returns a list of path pointing
-to the matching tree element. See L<Config::Model::AnyThing/grab(...)> for details
+to the matching tree element. See L<Config::Model::Role::Grab/grab> for details
on the path syntax.
=head1 BUGS
diff --git a/lib/Config/Model/Utils/GenClassPod.pm b/lib/Config/Model/Utils/GenClassPod.pm
index 81e98d5..3301b98 100644
--- a/lib/Config/Model/Utils/GenClassPod.pm
+++ b/lib/Config/Model/Utils/GenClassPod.pm
@@ -8,7 +8,7 @@
# The GNU Lesser General Public License, Version 2.1, February 1999
#
package Config::Model::Utils::GenClassPod;
-$Config::Model::Utils::GenClassPod::VERSION = '2.094';
+$Config::Model::Utils::GenClassPod::VERSION = '2.095';
# ABSTRACT: generate pod documentation from configuration models
use strict;
@@ -55,7 +55,7 @@ Config::Model::Utils::GenClassPod - generate pod documentation from configuratio
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
diff --git a/lib/Config/Model/Value.pm b/lib/Config/Model/Value.pm
index b2991bf..734590f 100644
--- a/lib/Config/Model/Value.pm
+++ b/lib/Config/Model/Value.pm
@@ -8,7 +8,7 @@
# The GNU Lesser General Public License, Version 2.1, February 1999
#
package Config::Model::Value;
-$Config::Model::Value::VERSION = '2.094';
+$Config::Model::Value::VERSION = '2.095';
use 5.10.1;
use Mouse;
@@ -32,6 +32,8 @@ use List::MoreUtils qw(any) ;
extends qw/Config::Model::AnyThing/;
with "Config::Model::Role::WarpMaster";
+with "Config::Model::Role::Grab";
+with "Config::Model::Role::HelpAsText";
my $logger = get_logger("Tree::Element::Value");
my $change_logger = get_logger("Anything::Change");
@@ -1805,7 +1807,7 @@ Config::Model::Value - Strongly typed configuration value
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
diff --git a/lib/Config/Model/Value/LayeredInclude.pm b/lib/Config/Model/Value/LayeredInclude.pm
index 24411a2..8552b09 100644
--- a/lib/Config/Model/Value/LayeredInclude.pm
+++ b/lib/Config/Model/Value/LayeredInclude.pm
@@ -8,7 +8,7 @@
# The GNU Lesser General Public License, Version 2.1, February 1999
#
package Config::Model::Value::LayeredInclude;
-$Config::Model::Value::LayeredInclude::VERSION = '2.094';
+$Config::Model::Value::LayeredInclude::VERSION = '2.095';
use 5.010;
use strict;
use warnings;
@@ -108,7 +108,7 @@ Config::Model::Value::LayeredInclude - Include a sub layer configuration
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
diff --git a/lib/Config/Model/ValueComputer.pm b/lib/Config/Model/ValueComputer.pm
index 82c90ce..6b0dd96 100644
--- a/lib/Config/Model/ValueComputer.pm
+++ b/lib/Config/Model/ValueComputer.pm
@@ -8,7 +8,7 @@
# The GNU Lesser General Public License, Version 2.1, February 1999
#
package Config::Model::ValueComputer;
-$Config::Model::ValueComputer::VERSION = '2.094';
+$Config::Model::ValueComputer::VERSION = '2.095';
use Mouse;
use MouseX::StrictConstructor;
@@ -581,7 +581,7 @@ Config::Model::ValueComputer - Provides configuration value computation
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
@@ -643,7 +643,7 @@ A string formula that use variables and replace function.
A set of variable and their relative location in the tree (using the
notation explained in
-L<grab() method|Config::Model::AnyThing/"grab(...)">
+L<grab() method|Config::Model::Role::Grab/grab">
=item *
@@ -658,7 +658,7 @@ An optional parameter to force a Perl eval of a string.
B<Note>: A variable must point to a valid location in the configuration
tree. Even when C<&index()> or C<$replace{}> is used. After substitution
of these functions, the string is used as a path (See
-L<grab()|Config::Model::AnyThing/"grab(...)">) starting from the
+L<grab()|Config::Model::Role::Grab/grab">) starting from the
computed value. Hence the path must begin with C<!> to go back to root
node, or C<-> to go up a level.
diff --git a/lib/Config/Model/WarpedNode.pm b/lib/Config/Model/WarpedNode.pm
index cbfe274..c83fbf4 100644
--- a/lib/Config/Model/WarpedNode.pm
+++ b/lib/Config/Model/WarpedNode.pm
@@ -8,9 +8,8 @@
# The GNU Lesser General Public License, Version 2.1, February 1999
#
package Config::Model::WarpedNode;
-$Config::Model::WarpedNode::VERSION = '2.094';
+$Config::Model::WarpedNode::VERSION = '2.095';
use Mouse;
-with "Config::Model::Role::NodeLoader";
use Carp qw(cluck croak);
@@ -23,6 +22,9 @@ use Scalar::Util qw/weaken/;
extends qw/Config::Model::AnyThing/;
+with "Config::Model::Role::NodeLoader";
+with "Config::Model::Role::Grab";
+
my $logger = get_logger("Tree::Node::Warped");
# don't authorize to warp 'morph' parameter as it may lead to
@@ -80,7 +82,7 @@ foreach my $method (
qw/fetch_element config_class_name copy_from get_element_name
has_element is_element_available element_type load
fetch_element_value get_type get_cargo_type dump_tree
- describe get_help children get set accept_regexp/
+ describe get_help get_help_as_text children get set accept_regexp/
) {
# to register new methods in package
no strict "refs";
@@ -311,7 +313,7 @@ Config::Model::WarpedNode - Node that change config class properties
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
@@ -405,7 +407,7 @@ Always set to C<warped_node>.
=item follow
-L<Grab string|Config::Model::AnyThing/"grab(...)"> leading to the
+L<Grab string|Config::Model::Role::Grab/grab"> leading to the
C<Config::Model::Value> warp master.
See L<Config::Model::Warper/"Warp follow argument"> for details.
diff --git a/lib/Config/Model/Warper.pm b/lib/Config/Model/Warper.pm
index c5cb31b..ab68c90 100644
--- a/lib/Config/Model/Warper.pm
+++ b/lib/Config/Model/Warper.pm
@@ -8,7 +8,7 @@
# The GNU Lesser General Public License, Version 2.1, February 1999
#
package Config::Model::Warper;
-$Config::Model::Warper::VERSION = '2.094';
+$Config::Model::Warper::VERSION = '2.095';
use Mouse;
use Log::Log4perl qw(get_logger :levels);
@@ -620,7 +620,7 @@ Config::Model::Warper - Warp tree properties
=head1 VERSION
-version 2.094
+version 2.095
=head1 SYNOPSIS
@@ -654,13 +654,13 @@ and C<rules>:
=head2 Warp follow argument
-L<Grab string|Config::Model::AnyThing/"grab(...)"> leading to the
+L<Grab string|Config::Model::Role::Grab/grab> leading to the
C<Config::Model::Value> or L<Config::Model::CheckList> warp master. E.g.:
follow => '! tree_macro'
In case of several warp master, C<follow> is set to an array ref
-of several L<grab string|Config::Model::AnyThing/"grab(...)">:
+of several L<grab string|Config::Model::Role::Grab/grab>:
follow => [ '! macro1', '- macro2' ]
@@ -822,7 +822,7 @@ warp master is an enumerated type)
When a warped object is created, the constructor registers to the
warp masters. The warp master are found by using the special string
passed to the C<follow> parameter. As explained in
-L<grab method|Config::Model::AnyThing/"grab(...)">,
+L<grab method|Config::Model::Role::Grab/grab>,
the string provides the location of the warp master in the
configuration tree using a symbolic form.
diff --git a/t/annotation.t b/t/annotation.t
index b708005..9b3c61b 100644
--- a/t/annotation.t
+++ b/t/annotation.t
@@ -1,12 +1,13 @@
# -*- cperl -*-
use ExtUtils::testlib;
-use Test::More tests => 19;
+use Test::More ;
use Test::Memory::Cycle;
use Config::Model;
use Config::Model::Annotation;
use File::Path;
use Data::Dumper;
+use 5.10.0;
use warnings;
no warnings qw(once);
@@ -52,9 +53,14 @@ my $step =
. '! hash_a:X2=x hash_a:Y2=xy hash_a:toto#"index comment"
hash_b:X3=xy my_check_list=X2,X3';
ok( $root->load( step => $step ), "set up data in tree with '$step'" );
-
-my @annotate = map { [ $_ => "$_ annotation" ] }
- ( 'std_id', 'std_id:bc X', 'my_check_list', 'olist:0', 'olist:2' );
+$inst->clear_changes;
+
+my @annotate = map
+ { [ $_ => "$_ annotation" ] }
+ (
+ 'std_id', 'std_id', # test that 2 saves of same value is tracked once
+ 'std_id:bc X', 'my_check_list', 'olist:0', 'olist:2'
+ );
my %expect = ( 'hash_a:toto' => "index comment", 'olist:1' => 'olist1_comment' );
foreach (@annotate) {
@@ -64,10 +70,18 @@ foreach (@annotate) {
ok( 1, "set annotation of $l" );
}
+say "pending changes:\n".$inst->list_changes if $trace;
+is( $inst->needs_save, 5, "verify instance needs_save status after storing only annotations" );
+$inst->clear_changes;
+
is( $root->grab("std_id:ab X")->annotation('to delete'), 'to delete', "test clear annotation" );
is( $root->grab("std_id:ab X")->clear_annotation, '', "test clear annotation" );
+say "pending changes:\n".$inst->list_changes if $trace;
+is( $inst->needs_save, 2, "verify instance needs_save status after store/delete annotations" );
+$inst->clear_changes;
+
my $annotate_saver = Config::Model::Annotation->new(
config_class_name => 'Master',
instance => $inst,
@@ -132,4 +146,6 @@ my $h3_ref = $saver2->get_annotation_hash();
print Dumper ($h3_ref) if $trace;
is_deeply( $h3_ref, \%expect3, "check loaded annotation data with non-empty tree" );
-memory_cycle_ok($model);
+memory_cycle_ok($model, "memory cycles");
+
+done_testing;
diff --git a/t/backend_mgr.t b/t/backend_mgr.t
index 52f9aa0..fc4200f 100644
--- a/t/backend_mgr.t
+++ b/t/backend_mgr.t
@@ -4,15 +4,14 @@ use ExtUtils::testlib;
use Test::More;
use Test::Memory::Cycle;
use Config::Model;
-use File::Path;
-use File::Copy;
+use Path::Tiny 0.070;
use Test::Warn;
use Test::Exception;
use Test::File::Contents;
use warnings;
no warnings qw(once);
-
+use 5.10.1;
use strict;
use vars qw/$model/;
@@ -40,15 +39,15 @@ else {
ok( 1, "compiled" );
# pseudo root for config files
-my $wr_root = 'wr_root';
-my $root1 = "$wr_root/test1/";
-my $root2 = "$wr_root/test2/";
-my $root3 = "$wr_root/test3/";
+my $wr_root = path('wr_root');
+my $root1 = $wr_root->child('test1');
+my $root2 = $wr_root->child('test2');
+my $root3 = $wr_root->child('test3');
my $conf_dir = '/etc/test/';
# cleanup before tests
-rmtree($wr_root);
+$wr_root->remove_tree;
# model declaration
$model->create_config_class(
@@ -57,7 +56,10 @@ $model->create_config_class(
[qw/X Y Z/] => {
type => 'leaf',
value_type => 'enum',
- choice => [qw/Av Bv Cv/] } ] );
+ choice => [qw/Av Bv Cv/]
+ }
+ ]
+);
$model->create_config_class(
name => 'Level1',
@@ -86,7 +88,9 @@ $model->create_config_class(
bar => {
type => 'node',
config_class_name => 'Level2',
- } ] );
+ }
+ ]
+);
$model->create_config_class(
name => 'SameReadWriteSpec',
@@ -106,7 +110,10 @@ $model->create_config_class(
bar => {
type => 'node',
config_class_name => 'Level2',
- } ] );
+ },
+ int_with_max => {qw/type leaf value_type integer max 10/},
+ ]
+);
$model->create_config_class(
name => 'Master',
@@ -144,7 +151,8 @@ $model->create_config_class(
type => 'node',
config_class_name => 'SameReadWriteSpec',
},
- ] );
+ ]
+);
$model->create_config_class(
name => 'FromScratch',
@@ -158,7 +166,8 @@ $model->create_config_class(
element => [
aa => { type => 'leaf', value_type => 'string' },
- ] );
+ ]
+);
$model->create_config_class(
name => 'CdsWithFile',
@@ -172,7 +181,8 @@ $model->create_config_class(
element => [
aa => { type => 'leaf', value_type => 'string' },
- ] );
+ ]
+);
$model->create_config_class(
name => 'CdsWithNoFile',
@@ -181,7 +191,8 @@ $model->create_config_class(
element => [
aa => { type => 'leaf', value_type => 'string' },
- ] );
+ ]
+);
$model->create_config_class(
name => 'SimpleRW',
@@ -196,7 +207,8 @@ $model->create_config_class(
element => [
aa => { type => 'leaf', value_type => 'string' },
- ] );
+ ]
+);
#global variable to snoop on read config action
my %result;
@@ -264,7 +276,7 @@ package main;
my $i_fail = $model->instance(
instance_name => 'failed_inst',
root_class_name => 'Master',
- root_dir => $root1,
+ root_dir => $root1->stringify,
backend => 'perl_file',
);
throws_ok {
@@ -278,7 +290,7 @@ is( $result{master_read}, undef, "Master read conf dir" );
my $i_zero = $model->instance(
instance_name => 'zero_inst',
root_class_name => 'Master',
- root_dir => $root1,
+ root_dir => $root1->stringify,
);
ok( $i_zero, "Created instance (from scratch)" );
@@ -320,15 +332,15 @@ $i_zero->write_back( backend => 'all', force => 1 );
# check written files
foreach my $suffix (qw/cds ini/) {
map {
- my $f = "$root1$conf_dir/$_.$suffix";
- ok( -e $f, "check written file $f" );
+ my $f = $root1->child("$conf_dir/$_.$suffix");
+ ok( $f->is_file, "check written file $f" );
} ( 'zero_inst', 'zero_inst/level1', 'zero_inst/samerw' );
}
foreach my $suffix (qw/pl/) {
map {
- my $f = "$root1$conf_dir/$_.$suffix";
- ok( -e "$f", "check written file $f" );
+ my $f = $root1->child("$conf_dir/$_.$suffix");
+ ok( $f->is_file, "check written file $f" );
} ( 'zero_inst', 'zero_inst/level1' );
}
@@ -342,12 +354,15 @@ $i_zero->write_back( backend => 'all', config_dir => $override, force => 1 );
# check written files
foreach my $suffix (qw/cds ini/) {
- map { ok( -e "$root1$override$_.$suffix", "check written file $root1$override$_.$suffix" ); }
- ( 'zero_inst', 'zero_inst/level1', 'zero_inst/samerw' );
+ map {
+ ok( $root1->child("$override$_.$suffix")->is_file,
+ "check written file ".$root1->child("$override$_.$suffix") );
+ } ( 'zero_inst', 'zero_inst/level1', 'zero_inst/samerw' );
}
foreach my $suffix (qw/pl/) {
- map { ok( -e "$root1$override$_.$suffix", "check written file $root1$override$_.$suffix" ); }
- ( 'zero_inst', 'zero_inst/level1' );
+ map { ok( $root1->child("$override$_.$suffix")->is_file,
+ "check written file ".$root1->child("$override$_.$suffix") );
+ } ( 'zero_inst', 'zero_inst/level1' );
}
is( $result{wr_stuff}, $override, 'check custom overridden write dir' );
@@ -368,24 +383,22 @@ my %cds = (
"$inst2/level1" => 'bar X=Av Y=Bv - '
);
-my $dir2 = "$root2/etc/test/";
-mkpath( $dir2 . $inst2, 0, 0755 ) || die "Can't mkpath $dir2.$inst2:$!";
+my $dir2 = $root2->child("etc/test/");
+$dir2->child($inst2)->mkpath();
# write input config files
foreach my $f ( keys %cds ) {
- my $fout = "$dir2/$f.cds";
+ my $fout = $dir2->child($f.'.cds');
next if -r $fout;
- open( FOUT, ">$fout" ) or die "can't open $fout:$!";
- print FOUT $cds{$f};
- close FOUT;
+ $fout->spew($cds{$f});
}
# create another instance
my $test2_inst = $model->instance(
root_class_name => 'Master',
instance_name => $inst2,
- root_dir => $root2,
+ root_dir => $root2->stringify,
);
ok( $test2_inst, "created second instance" );
@@ -412,13 +425,6 @@ samerw
';
is( $dump2, $expect2, "$inst2: check dump" );
-# test loading with ini files
-map {
- my $o = $_;
- s!$root1/zero!ini!;
- copy( $o, "$root2/$_" ) or die "can't copy $o $_:$!"
-} glob("$root1/*.ini");
-
# create another instance to load ini files
my $ini_inst = $model->instance(
root_class_name => 'Master',
@@ -440,15 +446,6 @@ $dump = $ini_inst->config_root->dump_tree;
is( $dump, $expect_custom, "ini_test: check dump" );
-unlink( glob("$root2/*.ini") );
-
-# test loading with pl files
-map {
- my $o = $_;
- s!$root1/zero!pl!;
- copy( $o, "$root2/$_" ) or die "can't copy $o $_:$!"
-} glob("$root1/*.pl");
-
# create another instance to load pl files
my $pl_inst = $model->instance(
root_class_name => 'Master',
@@ -464,7 +461,7 @@ is( $dump, $expect_custom, "pl_test: check dump" );
my $scratch_i = $model->instance(
root_class_name => 'FromScratch',
instance_name => 'scratch_inst',
- root_dir => $root3,
+ root_dir => $root3->stringify,
);
ok( $scratch_i, "Created instance from scratch to load cds files" );
@@ -478,7 +475,7 @@ ok( -e "$root3/$conf_dir/scratch_inst.cds", "wrote cds config file" );
my $cdswf = $model->instance(
root_class_name => 'CdsWithFile',
instance_name => 'cds_with_file_inst',
- root_dir => $root3,
+ root_dir => $root3->stringify,
);
ok( $cdswf, "Created instance to load custom cds file" );
@@ -489,14 +486,13 @@ is( $cdswf->config_root->dump_tree, $expect, "check dump" );
$cdswf->write_back;
-my $toto_conf = "$root3/$conf_dir/toto.conf";
-copy( "$root3/$conf_dir/scratch_inst.cds", $toto_conf )
+my $toto_conf = $root3->child("$conf_dir/scratch_inst.cds")->copy( $root3->child("$conf_dir/toto.conf"))
or die "can't copy scratch_inst.cds to toto.conf:$!";
my $ctoto = $model->instance(
root_class_name => 'SimpleRW',
instance_name => 'custom_toto',
- root_dir => $root3,
+ root_dir => $root3->stringify,
);
ok( $ctoto, "Created instance to load custom custom toto file" );
@@ -520,7 +516,7 @@ my $scratch_conf = 'etc/test/scratch_inst.cds';
my $cdswnf = $model->instance(
root_class_name => 'CdsWithNoFile',
instance_name => 'cds_with_no_file_inst',
- root_dir => $root3,
+ root_dir => $root3->stringify,
config_file => $scratch_conf,
);
ok( $cdswnf, "Created instance to load overridden cds config file" );
diff --git a/t/dump_load_model.pm b/t/dump_load_model.pm
index 0b26d99..a872d41 100644
--- a/t/dump_load_model.pm
+++ b/t/dump_load_model.pm
@@ -127,6 +127,13 @@
cargo_type => 'leaf',
cargo_args => { value_type => 'string' },
},
+ ordered_hash_of_node => {
+ type => 'hash',
+ index_type => 'string',
+ ordered => 1,
+ cargo_type => 'node',
+ config_class_name => 'SubSlave2',
+ },
olist => {
type => 'list',
cargo_type => 'node',
diff --git a/t/hash_id_of_values.t b/t/hash_id_of_values.t
index 6d692c0..ebc5dd8 100644
--- a/t/hash_id_of_values.t
+++ b/t/hash_id_of_values.t
@@ -368,8 +368,18 @@ $oh->move_after( 'd', 'e' );
eq_or_diff( [ $oh->fetch_all_indexes ],
[qw/a z x e d/], "check index order of ordered_hash after move_after(d e)" );
+$oh->sort;
+eq_or_diff( [ $oh->fetch_all_indexes ],
+ [qw/a d e x z/], "check index order of ordered_hash after sort" );
+
+$oh->insort('v')->store('v val');
+eq_or_diff( [ $oh->fetch_all_indexes ],
+ [qw/a d e v x z/], "check index order of ordered_hash after insort" );
+is($oh->fetch_with_id('v')->fetch,'v val',"check value entered with insort");
+
$inst->clear_changes;
$oh->clear;
+
is( $inst->needs_save, 1, "verify instance needs_save status after clear" );
eq_or_diff([$inst->list_changes],['ordered_hash: cleared all entries'],"check change message after clear");
eq_or_diff( [ $oh->fetch_all_indexes ], [], "check index order of ordered_hash after clear" );
diff --git a/t/load.t b/t/load.t
index 5877070..ad1ae3f 100644
--- a/t/load.t
+++ b/t/load.t
@@ -400,6 +400,15 @@ eq_or_diff( [$oh->fetch_all_indexes()],[qw/b a/], "check unsorted keys") ;
$root->load('ordered_hash:.sort') ;
eq_or_diff( [$oh->fetch_all_indexes()],[qw/a b/], "check sorted keys") ;
+# test insort on ordered hash
+$root->load('ordered_hash:.insort(d,"dv")') ;
+eq_or_diff( [$oh->fetch_all_indexes()],[qw/a b d/], "check sorted keys after insort") ;
+
+# test insort on ordered hash of node
+my $ohon = $root->fetch_element('ordered_hash_of_node');
+$root->load('ordered_hash_of_node:g aa2="g aa2 val" - ordered_hash_of_node:.insort(d) aa2="d aa2 val"');
+eq_or_diff( [$ohon->fetch_all_indexes()],[qw/d g/], "check sorted keys") ;
+
# test combination of annotation plus load and some utf8
$step = 'std_id#std_id_note ! std_id:ab#std_id_ab_note X=Bv X#X_note
- std_id:bc X=Av X#X2_note '
diff --git a/t/model_tests.d/multi-ini-examples/max-overflow/etc/bar.conf b/t/model_tests.d/multi-ini-examples/max-overflow/etc/bar.conf
new file mode 100644
index 0000000..d6cf8ff
--- /dev/null
+++ b/t/model_tests.d/multi-ini-examples/max-overflow/etc/bar.conf
@@ -0,0 +1 @@
+int_with_max=100
\ No newline at end of file
diff --git a/t/model_tests.d/multi-ini-test-conf.pl b/t/model_tests.d/multi-ini-test-conf.pl
new file mode 100644
index 0000000..5da431b
--- /dev/null
+++ b/t/model_tests.d/multi-ini-test-conf.pl
@@ -0,0 +1,71 @@
+#
+# This file is part of Config-Model
+#
+# This software is Copyright (c) 2005-2016 by Dominique Dumont.
+#
+# This is free software, licensed under:
+#
+# The GNU Lesser General Public License, Version 2.1, February 1999
+#
+
+# test inifile backend with multiple ini files
+
+# specify the name of the class to test
+$model_to_test = "MultiMiniIni";
+
+# create minimal model to test ini file backend.
+
+# this class is used by MultiMiniIni class below
+$model->create_config_class(
+ name => 'MultiIniTest::Class',
+ element => [
+ int_with_max => {qw/type leaf value_type integer max 10/},
+ ],
+ read_config => [{
+ backend => 'IniFile',
+ config_dir => '/etc/',
+ file => '&index.conf',
+ auto_create => 1,
+ }],
+);
+
+$model->create_config_class(
+ name => 'MultiMiniIni',
+ element => [
+ service => {
+ type => 'hash',
+ index_type => 'string',
+ # require to trigger load of bar.conf
+ default_keys => 'bar',
+ cargo => {
+ type => 'node',
+ config_class_name => 'MultiIniTest::Class'
+ }
+ },
+ ],
+ read_config => [{
+ backend => 'Yaml',
+ config_dir => '/etc/',
+ file => 'service.yml',
+ auto_create => 1,
+ }],
+);
+
+
+# the test suite
+ at tests = (
+ {
+ name => 'max-overflow',
+ # work only with Config::Model > 2.094 because of an obscure
+ # initialisation bug occuring while loading a bad value in
+ # a sub-node (thanks systemd)
+ load => 'service:bar int_with_max=9',
+ file_check_sub => sub {
+ my $list_ref = shift ;
+ # file added because of default bar key
+ push @$list_ref, "/etc/service.yml" ;
+ },
+ },
+);
+
+1;
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-perl/packages/libconfig-model-perl.git
More information about the Pkg-perl-cvs-commits
mailing list