slurp_utf8 decode errors do not throw an exception, but just print warning messages and control returns normally.
This prevents doing e.g.
eval{ path(...)->slurp_utf8 } // handle_decode_error();
The problem is that Unicode::UTF8::decode_utf8 spews warnings if 'utf8' warnings are enabled, and the only way to detect errors programmatically is with use warnings FATAL => 'utf8' and catching the exception. Path::Tiny uses a file-scope use warnings; which overrides attempts to work around the problem in user code.
SUGGESTED SOLUTION:
Make sub slurp_utf8 use a localized use warnings FATAL => 'utf8'; so that an exception will be thrown if appropriate (and nothing will be printed to STDERR).
Here is a test version which seems to work:
sub slurp_utf8 {
# <test addition>
eval { use warnings FATAL => 'utf8';
# </test addition>
if ( defined($HAS_UU) ? $HAS_UU : ( $HAS_UU = _check_UU() ) ) {
return Unicode::UTF8::decode_utf8( slurp( $_[0], { binmode => ":unix" } ) );
}
elsif ( defined($HAS_PU) ? $HAS_PU : ( $HAS_PU = _check_PU() ) ) {
$_[1] = { binmode => ":unix:utf8_strict" };
goto &slurp;
}
else {
$_[1] = { binmode => ":unix:encoding(UTF-8)" };
goto &slurp;
}
# <test addition>
}
// do{
Path::Tiny::Error->throw( "slurp_utf8", $_[0], $@ );
}
# </test addition>
}
DEMO SCRIPT
#!/usr/bin/env perl
use strict; use warnings; use v5.32;
use open OUT => 'utf8', ':std'; STDOUT->autoflush(1); STDERR->autoflush(1);
#my $octets = "ABC";
my $octets = "\x{80}";
{
use Unicode::UTF8 qw[decode_utf8 encode_utf8];
use warnings FATAL => 'utf8'; # fatalize encoding glitches
my $chars = eval{ decode_utf8($octets) };
if ($@) {
warn "Caught decode_utf8 exception:\n $@\n";
} else {
warn "decode_utf8 SUCCEEDED! chars='$chars'\n";
}
}
{
use Path::Tiny;
my $tpath = Path::Tiny::tempfile("octets_XXXX"); $tpath->spew_raw($octets);
use warnings FATAL => 'utf8'; # makes no difference!
my $chars = eval{ $tpath->slurp_utf8; };
if ($@) {
warn "Caught slurp_utf8 exception: $@\n";
} else {
warn "slurp_utf8 SUCCEEDED! chars='$chars'\n";
}
}
Results using Path::Tiny version 0.146
Caught decode_utf8 exception:
Can't decode ill-formed UTF-8 octet sequence <80> in position 0 at /tmp/t1 line 11.
Can't decode ill-formed UTF-8 octet sequence <80> in position 0 at /home/jima/perl5/lib/perl5/Path/Tiny.pm line 2087.
slurp_utf8 SUCCEEDED!
slurp_utf8decode errors do not throw an exception, but just print warning messages and control returns normally.This prevents doing e.g.
eval{ path(...)->slurp_utf8 } // handle_decode_error();The problem is that
Unicode::UTF8::decode_utf8spews warnings if 'utf8' warnings are enabled, and the only way to detect errors programmatically is withuse warnings FATAL => 'utf8'and catching the exception. Path::Tiny uses a file-scopeuse warnings;which overrides attempts to work around the problem in user code.SUGGESTED SOLUTION:
Make sub
slurp_utf8use a localizeduse warnings FATAL => 'utf8';so that an exception will be thrown if appropriate (and nothing will be printed to STDERR).Here is a test version which seems to work:
DEMO SCRIPT
Results using Path::Tiny version 0.146