Skip Menu |

This queue is for tickets about the Config-Tiny CPAN distribution.

Report information
The Basics
Id: 71029
Status: resolved
Priority: 0/
Queue: Config-Tiny

People
Owner: Nobody in particular
Requestors: nomad [...] null.net
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: (no value)



Subject: Config::Tiny does not handle or enable non-ascii config text
Date: Sat, 17 Sep 2011 10:44:58 +1200
To: bug-Config-Tiny [...] rt.cpan.org
From: Mark Lawrence <nomad [...] null.net>
Config files containing non-ascii characters (for example 'รค') are not read with the correct file-handle encoding. I presume they are not written correctly either. Config::Tiny does not provide an encoding setting as part of its API, and I can't seem to find any hacks to force it. Any chance of recognizing this as a feature request? Mark. -- Mark Lawrence
Subject: [rt.cpan.org #71029] [PATCH] Add an optional encoding argument to read() and write().
Date: Sat, 17 Sep 2011 12:00:17 +1200
To: Bugs in Config-Tiny via RT <bug-Config-Tiny [...] rt.cpan.org>
From: Mark Lawrence <nomad [...] null.net>
Show quoted text
> Config::Tiny does not provide an encoding setting as part of its API, > and I can't seem to find any hacks to force it. Any chance of > recognizing this as a feature request?
I quickly worked something up which does what I need: my $conf = Config::Tiny->read('file', 'utf-8') # hack hack hack $conf->write('file', 'utf-8') It relies on the PerlIO layer so may or may not be portable for all Perls that have ever been written. The patch below will not apply to the latest release (I cleaned up my local copy of the code using perltidy and podtidy before hand) but shows what I'm suggesting. If you want the full patch set see: git clone git@github.com:mlawren/Config-Tiny.git or via browser at https://github.com/mlawren/Config-Tiny Mark. --- lib/Config/Tiny.pm | 32 ++++++++++++++++++++------------ 1 files changed, 20 insertions(+), 12 deletions(-) diff --git a/lib/Config/Tiny.pm b/lib/Config/Tiny.pm index 25b9b7c..05aaf8b 100644 --- a/lib/Config/Tiny.pm +++ b/lib/Config/Tiny.pm @@ -25,9 +25,13 @@ sub read { return $class->_error("Insufficient permissions to read '$file'") unless -r _; + my $encoding = @_ ? '<:encoding(' . (shift) . ')' : '<'; + # Slurp in the file local $/ = undef; - open CFG, $file or return $class->_error("Failed to open file '$file': $!"); + + open CFG, $encoding, $file + or return $class->_error("Failed to open file '$file': $!"); my $contents = <CFG>; close CFG; @@ -76,12 +80,13 @@ sub read_string { # Save an object to a file sub write { - my $self = shift; - my $file = shift or return $self->_error( 'No file name provided' ); + my $self = shift; + my $file = shift or return $self->_error('No file name provided'); + my $encoding = @_ ? '>:' . (shift) : '>'; # Write it to the file - open( CFG, '>' . $file ) - or return $self->_error( "Failed to open file '$file' for writing: $!" ); + open CFG, $encoding, $file + or return $self->_error("Failed to open file '$file' for writing: $!"); print CFG $self->write_string; close CFG; } @@ -93,7 +98,8 @@ sub write_string { my $contents = ''; foreach my $section ( sort { ( ( $b eq '_' ) <=> ( $a eq '_' ) ) || ( $a cmp $b ) } - keys %$self ) + keys %$self + ) { my $block = $self->{$section}; $contents .= "\n" if length $contents; @@ -139,7 +145,7 @@ possible my $Config = Config::Tiny->new(); # Open the config - $Config = Config::Tiny->read( 'file.conf' ); + $Config = Config::Tiny->read( 'file.conf', 'utf-8' ); # Reading properties my $rootproperty = $Config->{_}->{rootproperty}; @@ -152,7 +158,7 @@ possible delete $Config->{_}; # Delete a value or section # Save a config - $Config->write( 'file.conf' ); + $Config->write( 'file.conf', 'utf-8' ); =head1 DESCRIPTION @@ -197,10 +203,11 @@ something better, this module is not for you. The constructor C<new> creates and returns an empty C<Config::Tiny> object. -=head2 read $filename +=head2 read $filename [$encoding] The C<read> constructor reads a config file, and returns a new -C<Config::Tiny> object containing the properties in the file. +C<Config::Tiny> object containing the properties in the file. An +optional argument specifies the encoding. Returns the object on success, or C<undef> on error. @@ -215,10 +222,11 @@ C<$!> variable. The C<read_string> method takes as argument the contents of a config file as a string and returns the C<Config::Tiny> object for it. -=head2 write $filename +=head2 write $filename [$encoding] The C<write> method generates the file content for the properties, and -writes it to disk to the filename specified. +writes it to disk to the filename specified. The encoding can be +optionally specified as well. Returns true on success or C<undef> on error. -- Mark Lawrence
I have just released Alt::Config::Tiny::utf8 to CPAN with an alternative Config::Tiny inside with this fix/feature added. I'll remove it as soon as this bug is fixed. See the "Alt" distribution for details. -- Mark Lawrence
I wrote a letter to Adam. He said he is ok with this changes, "but moving to three-argument open() might be a bit premature (It adds a Perl 5.6 dependency)". I suggest something like this: diff --git a/Tiny.pm b/Tiny.pm index 2496129..7271c3e 100644 --- a/Tiny.pm +++ b/Tiny.pm @@ -22,9 +22,18 @@ sub read { return $class->_error( "'$file' is a directory, not a file" ) unless -f _; return $class->_error( "Insufficient permissions to read '$file'" ) unless -r _; + my $encoding = shift; + # Slurp in the file local $/ = undef; - open( CFG, $file ) or return $class->_error( "Failed to open file '$file': $!" ); + my $open_result; + if ( defined $encoding ) { + require 5.006; + $open_result = open( CFG, "<:encoding($encoding)", $file ); + } else { + $open_result = open( CFG, $file ); + } + return $class->_error( "Failed to open file '$file': $!" ) unless $open_result; my $contents = <CFG>; close( CFG ); @@ -76,13 +85,19 @@ sub write { my $file = shift or return $self->_error( 'No file name provided' ); + my $encoding = shift; # Write it to the file my $string = $self->write_string; return undef unless defined $string; - open( CFG, '>' . $file ) or return $self->_error( - "Failed to open file '$file' for writing: $!" - ); + my $open_result; + if ( $encoding ) { + require 5.006; + $open_result = open( CFG, ">:($encoding)", $file ); + } else { + $open_result = open( CFG, '>' . $file ); + } + return $self->_error( "Failed to open file '$file' for writing: $!" ) unless $open_result; print CFG $string; close CFG; } @@ -161,6 +176,10 @@ Config::Tiny - Read/Write .ini style files with as little code as possible # Save a config $Config->write( 'file.conf' ); + # Also with encoding + $Config = Config::Tiny->read( 'utf8_file.conf', 'utf8' ); + $Config->write( 'utf8_file.conf', 'utf8' ); + =head1 DESCRIPTION C<Config::Tiny> is a perl class to read and write .ini style configuration @@ -200,10 +219,11 @@ something better, this module is not for you. The constructor C<new> creates and returns an empty C<Config::Tiny> object. -=head2 read $filename +=head2 read $filename [$encoding] The C<read> constructor reads a config file, and returns a new -C<Config::Tiny> object containing the properties in the file. +C<Config::Tiny> object containing the properties in the file. An +optional argument specifies the encoding. Returns the object on success, or C<undef> on error. @@ -218,10 +238,11 @@ the C<$!> variable. The C<read_string> method takes as argument the contents of a config file as a string and returns the C<Config::Tiny> object for it. -=head2 write $filename +=head2 write $filename [$encoding] The C<write> method generates the file content for the properties, and -writes it to disk to the filename specified. +writes it to disk to the filename specified. The encoding can be +optionally specified as well. Returns true on success or C<undef> on error.
By the way, the current workaround I use is: use Config::Tiny; use File::Slurp; my $conf = Config::Tiny->read_string( scalar read_file( $file, binmode => ':utf8' ) );
Subject: Re: [rt.cpan.org #71029] Config::Tiny does not handle or enable non-ascii config text
Date: Thu, 13 Sep 2012 09:41:53 +1200
To: Pushtaev Vadim via RT <bug-Config-Tiny [...] rt.cpan.org>
From: Mark Lawrence <nomad [...] null.net>
On Wed Sep 12, 2012 at 02:26:52AM -0400, Pushtaev Vadim via RT wrote: Show quoted text
> > I wrote a letter to Adam. He said he is ok with this changes, "but > moving to three-argument open() might be a bit premature (It adds a > Perl 5.6 dependency)".
It is up to Adam how much compatability he wishes to retain, but it is worth noting that CPAN testers do not appear to be testing against anything less than 5.6.2: http://matrix.cpantesters.org/?dist=Config-Tiny Show quoted text
> I suggest something like this: > ... > + my $open_result; > + if ( defined $encoding ) { > + require 5.006;
That doesn't feel right to me, as it looks like an unpleasant surprise in the making. The distribution could pass all tests during installation but still fail at runtime, depending on some combination of Perl version and Config::Tiny usage. If this feature is added I think it should also come with a minimum version requirement from the beginning. Mark. -- Mark Lawrence
Subject: Re: [rt.cpan.org #71029] Config::Tiny does not handle or enable non-ascii config text
Date: Thu, 13 Sep 2012 09:46:37 +1200
To: Pushtaev Vadim via RT <bug-Config-Tiny [...] rt.cpan.org>
From: Mark Lawrence <nomad [...] null.net>
On Wed Sep 12, 2012 at 02:37:11AM -0400, Pushtaev Vadim via RT wrote: Show quoted text
> <URL: https://rt.cpan.org/Ticket/Display.html?id=71029 > > > By the way, the current workaround I use is: > > use Config::Tiny; > use File::Slurp; > my $conf = Config::Tiny->read_string( > scalar read_file( $file, binmode => ':utf8' ) > );
Have you seen the amount of code in File::Slurp and the number of modules it pulls in? Sort of cancels out the "Tiny" part of Config::Tiny :-/ That's why I built the Alt::Config::Tiny::utf8 distribution. -- Mark Lawrence
On Wed Sep 12 17:46:56 2012, nomad@null.net wrote: Show quoted text
> Have you seen the amount of code in File::Slurp and the number of > modules it pulls in? Sort of cancels out the "Tiny" part of > Config::Tiny :-/ > > That's why I built the Alt::Config::Tiny::utf8 distribution. >
In my case, I need freebsd-port within perl module I want to use, and there are not standard ports of alt-modules. On the other hand I don't really care about "tiny" part. But you are right, in some cases this workaround isn't appropriate. Talking about "require 5.006", it's Adam to decide (but I share your opinion).
Adam, we still need your decision. Thanks in advance.
Thanx for the ideas. V 2.15 handles utf8.