File-Read-0.0801/0000755000076400001440000000000010705757447014472 5ustar maddingueusers00000000000000File-Read-0.0801/t/0000755000076400001440000000000010705757446014734 5ustar maddingueusers00000000000000File-Read-0.0801/t/samples/0000755000076400001440000000000010705757446016400 5ustar maddingueusers00000000000000File-Read-0.0801/t/samples/config0000444000076400001440000000022110705757446017561 0ustar maddingueusers00000000000000# something that looks like a configuration file # with a few comments, and some empty lines # enable debug debug = 1 # be verbose verbose = 1 File-Read-0.0801/t/samples/jerkcity26300000444000076400001440000000014310705757446020456 0ustar maddingueusers00000000000000DEUCE: PLEASE DO THESE STEPS IN THE FOLLOWING ORDERS: DEUCE: 1. SHUT UP DEUCE: 2. GET THE FUCK OUT File-Read-0.0801/t/samples/hello-world0000444000076400001440000000001410705757446020544 0ustar maddingueusers00000000000000Hello world File-Read-0.0801/t/samples/newline0000444000076400001440000000000110705757446017751 0ustar maddingueusers00000000000000 File-Read-0.0801/t/samples/pi0000444000076400001440000000002110705757446016722 0ustar maddingueusers000000000000003.14159265358979 File-Read-0.0801/t/samples/latin10000444000076400001440000000016410705757446017512 0ustar maddingueusers00000000000000agrave:à aelig:æ eacute:é szlig:ß eth:ð thorn:þ mu:µ pound:£ laquo:« raquo:» sect:§ para:¶ middot:· File-Read-0.0801/t/samples/world0000444000076400001440000000000610705757446017444 0ustar maddingueusers00000000000000world File-Read-0.0801/t/samples/space0000444000076400001440000000000110705757446017403 0ustar maddingueusers00000000000000 File-Read-0.0801/t/samples/hello0000444000076400001440000000000510705757446017417 0ustar maddingueusers00000000000000HelloFile-Read-0.0801/t/samples/empty0000444000076400001440000000000010705757446017445 0ustar maddingueusers00000000000000File-Read-0.0801/t/distchk.t0000444000076400001440000000025610705757446016553 0ustar maddingueusers00000000000000use strict; use Test::More; eval "use Test::Distribution not => [qw(versions podcover use)]"; plan skip_all => "Test::Distribution required for checking distribution" if $@; File-Read-0.0801/t/portfs.t0000444000076400001440000000033110705757446016431 0ustar maddingueusers00000000000000#!/usr/bin/perl -T use strict; use Test::More; eval "use Test::Portability::Files"; plan skip_all => "Test::Portability::Files required for testing filenames portability" if $@; # run the selected tests run_tests(); File-Read-0.0801/t/00-load.t0000444000076400001440000000022710705757446016254 0ustar maddingueusers00000000000000#!perl -T use strict; use Test::More tests => 1; BEGIN { use_ok( 'File::Read' ); } diag( "Testing File::Read $File::Read::VERSION, Perl $], $^X" ); File-Read-0.0801/t/pod-coverage.t0000444000076400001440000000026710705757446017477 0ustar maddingueusers00000000000000#!perl -T use strict; use Test::More; eval "use Test::Pod::Coverage 1.04"; plan skip_all => "Test::Pod::Coverage 1.04 required for testing POD coverage" if $@; all_pod_coverage_ok(); File-Read-0.0801/t/pod.t0000444000076400001440000000022710705757446015702 0ustar maddingueusers00000000000000#!perl -T use strict; use Test::More; eval "use Test::Pod 1.14"; plan skip_all => "Test::Pod 1.14 required for testing POD" if $@; all_pod_files_ok(); File-Read-0.0801/t/file-read.t0000444000076400001440000001375710705757446016764 0ustar maddingueusers00000000000000use strict; eval 'use warnings'; use Cwd qw(abs_path); use File::Spec; use Test::More; my $has_unidecode = eval "require 5.008; require Text::Unidecode; 1"; # describe the tests my @one_result_tests = ( { args => [ File::Spec->catfile(qw(t samples empty)) ], expected => '', }, { args => [ File::Spec->catfile(qw(t samples space)) ], expected => ' ', }, { args => [ File::Spec->catfile(qw(t samples newline)) ], expected => $/, }, { args => [ File::Spec->catfile(qw(t samples pi)) ], expected => "3.14159265358979\n", }, { args => [ File::Spec->catfile(qw(t samples hello)) ], expected => 'Hello', }, { args => [ File::Spec->catfile(qw(t samples world)) ], expected => "world\n", }, { args => [ File::Spec->catfile(qw(t samples hello)), File::Spec->catfile(qw(t samples space)), File::Spec->catfile(qw(t samples world)), ], expected => "Hello world\n", }, { args => [ File::Spec->catfile(qw(t samples jerkcity2630)) ], expected => "DEUCE: PLEASE DO THESE STEPS IN THE FOLLOWING ORDERS:\n" . "DEUCE: 1. SHUT UP\n" . "DEUCE: 2. GET THE FUCK OUT\n", }, { args => [ File::Spec->catfile(qw(t samples config)) ], expected => "# something that looks like a configuration file\n" . "# with a few comments, and some empty lines\n" . "\n" . "# enable debug\n" . "debug = 1\n" . "\n" . "# be verbose\n" . "verbose = 1\n", }, { args => [ { skip_comments => 1 }, File::Spec->catfile(qw(t samples config)) ], expected => "\n" . "debug = 1\n" . "\n" . "verbose = 1\n", }, { args => [ { skip_blanks => 1 }, File::Spec->catfile(qw(t samples config)) ], expected => "# something that looks like a configuration file\n" . "# with a few comments, and some empty lines\n" . "# enable debug\n" . "debug = 1\n" . "# be verbose\n" . "verbose = 1\n", }, { args => [ { skip_comments => 1, skip_blanks => 1 }, File::Spec->catfile(qw(t samples config)) ], expected => "debug = 1\n" . "verbose = 1\n", }, { args => [ { to_ascii => 1 }, File::Spec->catfile(qw(t samples latin1)) ], expected => $has_unidecode ? # Text::Unidecode is available "agrave:a aelig:ae eacute:e szlig:ss eth:d thorn:th mu:u\n" . "pound:PS laquo:<< raquo:>> sect:SS para:P middot:*\n" : # Text::Unidecode isn't available, non-ASCII chars should be deleted "agrave: aelig: eacute: szlig: eth: thorn: mu:\n" . "pound: laquo: raquo: sect: para: middot:\n" , }, { args => [ { as_root => 1 }, File::Spec->catfile(qw(t samples hello)) ], expected => "ROOT:Hello", }, ); my @many_results_tests = ( { args => [ File::Spec->catfile(qw(t samples empty)), File::Spec->catfile(qw(t samples newline)), File::Spec->catfile(qw(t samples space)) ], expected => [ '', $/, ' ' ], }, { args => [ { aggregate => 0 }, File::Spec->catfile(qw(t samples jerkcity2630)) ], expected => [ "DEUCE: PLEASE DO THESE STEPS IN THE FOLLOWING ORDERS:\n", "DEUCE: 1. SHUT UP\n", "DEUCE: 2. GET THE FUCK OUT\n" ] }, ); # determine the path of the current perl(1) my $perl = abs_path($^X) || $^X; $perl = qq{"$perl"} if $perl =~ m/\s/; # "I love it when a plan comes together" plan tests => 7 + @one_result_tests * 2 + @many_results_tests * 3; # load File::Read use_ok( "File::Read", "cmd=$perl -pe s/^/ROOT:/" ); # check that the advertised functions are present can_ok( 'File::Read' => qw(read_file read_files) ); # check that the exported functions are available in the current package can_ok( __PACKAGE__, qw(read_file read_files) ); # check diagnostics eval { read_file() }; like( $@, '/^error: This function needs at least one path/', "calling read_file() with no argument" ); eval { read_files() }; like( $@, '/^error: This function needs at least one path/', "calling read_files() with no argument" ); eval { read_file('not/such/file') }; like( $@, q{/^error: read_file 'not/such/file' - /}, "calling read_file() with a file that does not exist" ); eval { read_files({ err_mode => 'pwadak' }) }; like( $@, q{/^error: Bad value 'pwadak' for option 'err_mode'/}, "calling read_files() with invalid value for option 'err_mode'" ); # having Data::Dumper might be useful eval 'use Data::Dumper'; $Data::Dumper::Indent = 0; $Data::Dumper::Indent = 0; # read files, returning one result for my $test (@one_result_tests) { (eval { Dumper($test->{args}) } || '') =~ /\[(.+)\];$/; my $args_str = $1 || "@{$test->{args}}"; my $file = eval { read_file( @{$test->{args}} ) }; is( $@, '', "calling read_file() with args: $args_str" ); is( $file, $test->{expected}, "checking result" ); } # read files, returning several results for my $test (@many_results_tests) { (eval { Dumper($test->{args}) } || '') =~ /\[(.+)\];$/; my $args_str = $1 || "@{$test->{args}}"; my @files = eval { read_file( @{$test->{args}} ) }; is( $@, '', "calling read_file() with args: $args_str" ); is( @files, scalar @{ $test->{expected} }, "checking results: number of elements" ); is_deeply( \@files, $test->{expected}, "checking results: deep compare" ); } File-Read-0.0801/eg/0000755000076400001440000000000010705757446015064 5ustar maddingueusers00000000000000File-Read-0.0801/eg/read_host.pl0000444000076400001440000000061710705757446017373 0ustar maddingueusers00000000000000#!/usr/bin/perl use strict; use Data::Dumper; use File::Read; # read /etc/hosts and put the the contents in a hash which gives the IP # address of the hostnames, thus providing an el-Cheapo resolving thingy :) my %addr = map { my ($ip,@names) = split /\s+/; map { $_ => $ip } @names } read_file({ aggregate => 0, skip_blanks => 1, skip_comments => 1 }, '/etc/hosts'); print Dumper(\%addr); File-Read-0.0801/Changes0000444000076400001440000000357310705757446015772 0ustar maddingueusers00000000000000Revision history for File-Read 0.0801 2007.10.19 (SAPER) [DIST] CPAN-RT#30104: Converted the few accented characters to UTF-8 (Damyan Ivanov). 0.0800 2007.10.18 (SAPER) [BUGFIX] Don't use Text::Unidecode on 5.6 because it doesn't really work. Thanks to Andreas Koenig for finding this bug. [TESTS] Fixed for passing again under Perl 5.5 and 5.4 [DIST] Have to change the version to 4 digits because packaging tools are plain stupid. 0.07 2007.10.17 (SAPER) [FEATURE] Option "cmd" to set the command used to read files as root. [TESTS] Removed the clunky tests for "as_root" as the "cmd" option allows for easy mocking. [TESTS] t/file-read.t also tests if the functions are actually exported. [DIST] eg/read_hosts.pl really present now. 0.0602 2006.10.13 (SAPER) [DIST] Added example eg/read_hosts.pl [DOC] Small Pod changes. 0.0601 2006.07.22 (SAPER) [TESTS] Fixed t/file-read.t so it skips when file doesn't exist. 0.06 2006.07.05 (SAPER) [CODE] _to_ascii(): Improved the substitution. 0.0501 2005.03.30 (SAPER) [DIST] Updated MANIFEST.. 0.05 2005.03.30 (SAPER) [FEATURE] Added new filter: to_ascii. 0.04 2006.03.29 (SAPER) [DOC] Added a rationale subsection. [DOC] Added a See Also section. [DOC] Small presentation change. 0.03 2006.03.27 (SAPER) [CODE] Small improvment: replaced an eval-string with an eval-code. [DIST] Added missing prereq File::Slurp in Build.PL, Makefile.PL 0.02 2006.02.08 (SAPER) [BUGFIX] Fixed a problem when reading files as root. [API] Changed the semantic of the aggregate option for a more useful one. [DOC] Fixed a few pod typos. 0.01 2006.02.03 (SAPER) First version, released on an unsuspecting world. File-Read-0.0801/MANIFEST0000444000076400001440000000051710705757446015623 0ustar maddingueusers00000000000000Build.PL Changes MANIFEST META.yml Makefile.PL README eg/read_host.pl lib/File/Read.pm t/00-load.t t/distchk.t t/file-read.t t/pod-coverage.t t/pod.t t/portfs.t t/samples/config t/samples/empty t/samples/hello t/samples/hello-world t/samples/jerkcity2630 t/samples/latin1 t/samples/newline t/samples/pi t/samples/space t/samples/world File-Read-0.0801/lib/0000755000076400001440000000000010705757446015237 5ustar maddingueusers00000000000000File-Read-0.0801/lib/File/0000755000076400001440000000000010705757446016116 5ustar maddingueusers00000000000000File-Read-0.0801/lib/File/Read.pm0000444000076400001440000001751110705757446017332 0ustar maddingueusers00000000000000package File::Read; use strict; use Carp; use File::Slurp (); require Exporter; { no strict; $VERSION = '0.0801'; @ISA = qw(Exporter); @EXPORT = qw(read_file read_files); } *read_files = \&read_file; =head1 NAME File::Read - Unique interface for reading one or more files =head1 VERSION Version 0.0801 =head1 SYNOPSIS use File::Read; # read a file $file = read_file($path); # read several files @files = read_files(@paths); # aggregate several files $file = read_files(@paths); # read a file as root, skip comments and blank lines $file = read_file({ as_root => 1, skip_comments => 1, skip_blanks => 1 }, $path); =head1 DESCRIPTION This module mainly proposes functions for reading one or more files, with different options. See below for more details and examples. =head2 Rationale This module was created to address a quite specific need: reading many files, some as a normal user and others as root, and eventually do a little more processing, all while being at the same time compatible with Perl 5.004. C addresses the first point, but not the others, hence the creation of C. If you don't need reading files as root or the post-processing features, then it's faster to directly use C. =head1 EXPORT By default, this module exports all the functions documented afterhand. It also recognizes import options. For example use File::Read 'err_mode=quiet'; set C's C option default value to C<"quiet">. =head1 FUNCTIONS =over =item B Read the files given in argument and return their content, as as list, one element per file, when called in list context, or as one big chunk of text when called in scalar context. Options can be set using a hashref as first parameter. B =over =item * C controls how the function returns the content of the files that were successfully read. By default, When set to true (default), the function returns the content as a scalar; when set to false, the content is returned as a list. =item * C tells the function to read the given file(s) as root using the command indicated by the C option. =item * C sets the shell command used for reading files as root. Default is C<"sudo cat">. Therefore you need B and B on your system, and F must be set so the user can execute B. =item * C controls how the function behaves when an error occurs. Available values are C<"croak">, C<"carp"> and C<"quiet">. Default value is C<"croak">. =item * C tells the functions to remove all comment lines from the read files. =item * C tells the functions to remove all blank lines from the read files. =item * C tells the functions to convert the text to US-ASCII using C. If this module is not available, non-ASCII data are deleted. =back B Just read a file: my $file = read_file($path); Read a file, returning it as list: my @file = read_file({ aggregate => 0 }, $path); Read a file, skipping comments: my $file = read_file({ skip_comments => 1 }, $path); Read several files, skipping blank lines and comments: my @files = read_file({ skip_comments => 1, skip_blanks => 1 }, @paths); =item B C is just an alias for C so that it look more sane when reading several files. =cut my %defaults = ( aggregate => 1, cmd => "sudo cat", err_mode => 'croak', skip_comments => 0, skip_blanks => 0, to_ascii => 0, ); sub import { my ($module, @args) = @_; my @new = (); # parse arguments for my $arg (@args) { if (index($arg, '=') >= 0) { my ($opt, $val) = split '=', $arg; $defaults{$opt} = $val if exists $defaults{$opt}; } else { push @new, $arg } } $module->export_to_level(1, $module, @new); } sub read_file { my %opts = ref $_[0] eq 'HASH' ? %{+shift} : (); my @paths = @_; my @files = (); # check options for my $opt (keys %defaults) { $opts{$opt} = $defaults{$opt} unless defined $opts{$opt} } # define error handler $opts{err_mode} =~ /^(?:carp|croak|quiet)$/ or croak "error: Bad value '$opts{err_mode}' for option 'err_mode'"; my %err_with = ( 'carp' => \&carp, 'croak' => \&croak, 'quiet' => sub{}, ); my $err_sub = $err_with{$opts{err_mode}}; $err_sub->("error: This function needs at least one path") unless @paths; for my $path (@paths) { my @lines = (); my $error = ''; # first, read the file if ($opts{as_root}) { # ... as root my $redir = $opts{err_mode} eq 'quiet' ? '2>&1' : ''; @lines = `$opts{cmd} $path $redir`; if ($?) { if (not -f $path) { $! = eval { require Errno; Errno->import(":POSIX"); ENOENT() } || 2 } elsif (not -r $path) { $! = eval { require Errno; Errno->import(":POSIX"); EACCES() } || 13 } else { $! = 1024 } ($error = "$!") =~ s/ 1024//; } } else { # ... as a normal user @lines = eval { File::Slurp::read_file($path) }; $error = $@; } # if there's an error $error and $err_sub->("error: $error"); # if there's any content at all... if (@lines) { # ... then do some filtering work if asked so @lines = grep { ! /^$/ } @lines if $opts{skip_blanks}; @lines = grep { ! /^\s*#/ } @lines if $opts{skip_comments}; @lines = map { _to_ascii($_) } @lines if $opts{to_ascii}; } push @files, $opts{aggregate} ? join('', @lines) : @lines; } # how to return the content(s)? return wantarray ? @files : join '', @files } # Text::Unidecode doesn't work on Perl 5.6 my $has_unidecode = eval "require 5.008; require Text::Unidecode; 1"; $@ = ""; sub _to_ascii { # use Text::Unidecode if available if ($has_unidecode) { return Text::Unidecode::unidecode(@_) } else { # use a simple s/// my @text = @_; map { s/[^\x00-\x7f]//g } @text; return @text } } =back =head1 DIAGNOSTICS =over =item C B<(E)> You gave a bad value for the indicated option. Please check the documentation for the valid values. =item C B<(E)> You called a function without giving it argument. =back =head1 SEE ALSO L L =head1 AUTHOR SEbastien Aperghis-Tramoni, C<< >> =head1 BUGS Please report any bugs or feature requests to C, or through the web interface at L. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes. =head1 SUPPORT You can find documentation for this module with the perldoc command. perldoc File::Read You can also look for information at: =over 4 =item * AnnoCPAN: Annotated CPAN documentation - L =item * CPAN Ratings - L =item * RT: CPAN's request tracker - L =item * Search CPAN - L =back =head1 COPYRIGHT & LICENSE Copyright (C) 2006, 2007 SEbastien Aperghis-Tramoni, all rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut 1; # End of File::Read File-Read-0.0801/META.yml0000444000076400001440000000073610705757446015746 0ustar maddingueusers00000000000000--- name: File-Read version: 0.0801 author: - 'Sébastien Aperghis-Tramoni ' abstract: Unique interface for reading one or more files license: perl resources: license: http://dev.perl.org/licenses/ build_requires: File::Slurp: 0 Test::More: 0 provides: File::Read: file: lib/File/Read.pm version: 0.0801 generated_by: Module::Build version 0.2808 meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.2.html version: 1.2 File-Read-0.0801/README0000444000076400001440000000354110705757447015353 0ustar maddingueusers00000000000000NAME File::Read - Unique interface for reading one or more files DESCRIPTION This module mainly proposes functions for reading one or more files, with different options. See the documentation for more details and examples. INSTALLATION To install this module, run the following commands: perl Makefile.PL make make test make install Alternatively, to install with Module::Build, you can use the following commands: perl Build.PL ./Build ./Build test ./Build install File::Read has been tested by the author to ensure that it works with the following versions of Perl: - Perl 5.4.5 i686-linux (custom build) - Perl 5.4.5 x86_64-linux (custom build) - Perl 5.5.3 i686-linux (custom build) - Perl 5.5.3 x86_64-linux (custom build) - Perl 5.6.2 i686-linux (custom build) - Perl 5.6.2 x86_64-linux (custom build) - Perl 5.8.5 i686-linux (vendor build) - Perl 5.8.7 x86_64-linux (vendor build) See also the corresponding CPAN Testers page: http://testers.cpan.org/show/File-Read.html SUPPORT AND DOCUMENTATION After installing, you can find documentation for this module with the perldoc command. perldoc File::Read You can also look for information at: Search CPAN http://search.cpan.org/dist/File-Read CPAN Request Tracker: http://rt.cpan.org/NoAuth/Bugs.html?Dist=File-Read AnnoCPAN, annotated CPAN documentation: http://annocpan.org/dist/File-Read CPAN Ratings: http://cpanratings.perl.org/d/File-Read COPYRIGHT AND LICENCE Copyright (C) 2006-2007 Sébastien Aperghis-Tramoni This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. File-Read-0.0801/Makefile.PL0000444000076400001440000000112310705757447016437 0ustar maddingueusers00000000000000use strict; use ExtUtils::MakeMaker; eval 'use ExtUtils::MakeMaker::Coverage'; WriteMakefile( NAME => 'File::Read', LICENSE => 'perl', AUTHOR => 'Sébastien Aperghis-Tramoni ', VERSION_FROM => 'lib/File/Read.pm', ABSTRACT_FROM => 'lib/File/Read.pm', PL_FILES => {}, PREREQ_PM => { 'File::Slurp' => 0, 'Test::More' => 0, }, dist => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', }, clean => { FILES => 'File-Read-*' }, ); File-Read-0.0801/Build.PL0000444000076400001440000000067610705757447015775 0ustar maddingueusers00000000000000use strict; use Module::Build; my $builder = Module::Build->new( module_name => 'File::Read', license => 'perl', dist_author => 'Sébastien Aperghis-Tramoni ', dist_version_from => 'lib/File/Read.pm', build_requires => { 'File::Slurp' => 0, 'Test::More' => 0, }, add_to_cleanup => [ 'File-Read-*' ], ); $builder->create_build_script();