summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2014-08-21 16:58:41 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2014-08-21 16:58:41 +0000
commit7dd93df1d843cbb36356dbea8071fab21cf04c30 (patch)
tree7433801a3aebd8fd9976ca2ecd94fed7b643c337
downloadModule-Reader-tarball-master.tar.gz
Module-Reader-0.002003HEADModule-Reader-0.002003master
-rw-r--r--Changes26
-rw-r--r--MANIFEST12
-rw-r--r--META.json57
-rw-r--r--META.yml27
-rw-r--r--Makefile.PL80
-rw-r--r--README46
-rw-r--r--lib/Module/Reader.pm174
-rw-r--r--maint/Makefile.PL.include7
-rw-r--r--t/00-load.t6
-rw-r--r--t/lib/TestLib.pm3
-rw-r--r--t/main.t19
-rw-r--r--t/memory.t45
12 files changed, 502 insertions, 0 deletions
diff --git a/Changes b/Changes
new file mode 100644
index 0000000..4112dd1
--- /dev/null
+++ b/Changes
@@ -0,0 +1,26 @@
+Revision history for Module-Reader
+
+0.002003 - 2014-08-21
+ - fix dist name in meta files
+
+0.002002 - 2014-08-16
+ - include README in dist
+ - include additional metadata
+
+0.002001 - Nov 23, 2013
+ - fix module NAME in Makefile.PL
+ - minor doc corrections
+ - fix in-memory file test on perl 5.6
+
+0.002000 - Feb 11, 2013
+ - Improve documentation.
+ - Add 'found' option for always loading from specific files.
+
+0.001002 - Feb 2, 2013
+ - fix copyright attribution
+
+0.001001 - Feb 1, 2013
+ - fix version number format
+
+0.001000 - Feb 1, 2013
+ - initial version
diff --git a/MANIFEST b/MANIFEST
new file mode 100644
index 0000000..ad92939
--- /dev/null
+++ b/MANIFEST
@@ -0,0 +1,12 @@
+Changes
+lib/Module/Reader.pm
+maint/Makefile.PL.include
+Makefile.PL
+MANIFEST This list of files
+t/00-load.t
+t/lib/TestLib.pm
+t/main.t
+t/memory.t
+META.yml Module YAML meta-data (added by MakeMaker)
+META.json Module JSON meta-data (added by MakeMaker)
+README README file (added by Distar)
diff --git a/META.json b/META.json
new file mode 100644
index 0000000..a080149
--- /dev/null
+++ b/META.json
@@ -0,0 +1,57 @@
+{
+ "abstract" : "Read the source of a module like perl does",
+ "author" : [
+ "haarg - Graham Knop (cpan:HAARG) <haarg@haarg.org>"
+ ],
+ "dynamic_config" : 1,
+ "generated_by" : "ExtUtils::MakeMaker version 6.98, CPAN::Meta::Converter version 2.141520",
+ "license" : [
+ "perl_5"
+ ],
+ "meta-spec" : {
+ "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",
+ "version" : "2"
+ },
+ "name" : "Module-Reader",
+ "no_index" : {
+ "directory" : [
+ "t",
+ "inc"
+ ]
+ },
+ "prereqs" : {
+ "build" : {},
+ "configure" : {
+ "requires" : {
+ "ExtUtils::MakeMaker" : "0"
+ }
+ },
+ "runtime" : {
+ "requires" : {
+ "Scalar::Util" : "0",
+ "perl" : "5.006"
+ }
+ },
+ "test" : {
+ "requires" : {
+ "Test::More" : "0.88"
+ }
+ }
+ },
+ "release_status" : "stable",
+ "resources" : {
+ "bugtracker" : {
+ "mailto" : "bug-Module-Reader@rt.cpan.org",
+ "web" : "https://rt.cpan.org/Public/Dist/Display.html?Name=Module-Reader"
+ },
+ "license" : [
+ "http://dev.perl.org/licenses/"
+ ],
+ "repository" : {
+ "type" : "git",
+ "url" : "git://github.com/haarg/Module-Reader",
+ "web" : "https://github.com/haarg/Module-Reader"
+ }
+ },
+ "version" : "0.002003"
+}
diff --git a/META.yml b/META.yml
new file mode 100644
index 0000000..d64ec63
--- /dev/null
+++ b/META.yml
@@ -0,0 +1,27 @@
+---
+abstract: 'Read the source of a module like perl does'
+author:
+ - 'haarg - Graham Knop (cpan:HAARG) <haarg@haarg.org>'
+build_requires:
+ Test::More: '0.88'
+configure_requires:
+ ExtUtils::MakeMaker: '0'
+dynamic_config: 1
+generated_by: 'ExtUtils::MakeMaker version 6.98, CPAN::Meta::Converter version 2.141520'
+license: perl
+meta-spec:
+ url: http://module-build.sourceforge.net/META-spec-v1.4.html
+ version: '1.4'
+name: Module-Reader
+no_index:
+ directory:
+ - t
+ - inc
+requires:
+ Scalar::Util: '0'
+ perl: '5.006'
+resources:
+ bugtracker: https://rt.cpan.org/Public/Dist/Display.html?Name=Module-Reader
+ license: http://dev.perl.org/licenses/
+ repository: git://github.com/haarg/Module-Reader
+version: '0.002003'
diff --git a/Makefile.PL b/Makefile.PL
new file mode 100644
index 0000000..b184d36
--- /dev/null
+++ b/Makefile.PL
@@ -0,0 +1,80 @@
+use strict;
+use warnings FATAL => 'all';
+use 5.006;
+
+my %META = (
+ name => 'Module-Reader',
+ prereqs => {
+ configure => { requires => {
+ 'ExtUtils::MakeMaker' => 0,
+ } },
+ test => { requires => {
+ 'Test::More' => 0.88,
+ } },
+ runtime => { requires => {
+ 'perl' => '5.006',
+ 'Scalar::Util' => 0,
+ } },
+ },
+ resources => {
+ repository => {
+ url => 'git://github.com/haarg/Module-Reader',
+ web => 'https://github.com/haarg/Module-Reader',
+ type => 'git',
+ },
+ bugtracker => {
+ web => 'https://rt.cpan.org/Public/Dist/Display.html?Name=Module-Reader',
+ mailto => 'bug-Module-Reader@rt.cpan.org',
+ },
+ license => [ 'http://dev.perl.org/licenses/' ],
+ },
+);
+
+my %MM_ARGS = (
+ PREREQ_PM => {
+ ($] < 5.008 ? ('IO::String' => 0) : ()),
+ },
+);
+
+## BOILERPLATE ###############################################################
+require ExtUtils::MakeMaker;
+(do 'maint/Makefile.PL.include' or die $@) unless -f 'META.yml';
+
+# have to do this since old EUMM dev releases miss the eval $VERSION line
+my $eumm_version = eval $ExtUtils::MakeMaker::VERSION;
+my $mymeta = $eumm_version >= 6.57_02;
+my $mymeta_broken = $mymeta && $eumm_version < 6.57_07;
+
+($MM_ARGS{NAME} = $META{name}) =~ s/-/::/g;
+($MM_ARGS{VERSION_FROM} = "lib/$MM_ARGS{NAME}.pm") =~ s{::}{/}g;
+$META{license} = [ $META{license} ]
+ if $META{license} && !ref $META{license};
+$MM_ARGS{LICENSE} = $META{license}[0]
+ if $META{license} && $eumm_version >= 6.30;
+$MM_ARGS{NO_MYMETA} = 1
+ if $mymeta_broken;
+$MM_ARGS{META_ADD} = { 'meta-spec' => { version => 2 }, %META }
+ unless -f 'META.yml';
+
+for (qw(configure build test runtime)) {
+ my $key = $_ eq 'runtime' ? 'PREREQ_PM' : uc $_.'_REQUIRES';
+ my $r = $MM_ARGS{$key} = {
+ %{$META{prereqs}{$_}{requires} || {}},
+ %{delete $MM_ARGS{$key} || {}},
+ };
+ defined $r->{$_} or delete $r->{$_} for keys %$r;
+}
+
+$MM_ARGS{MIN_PERL_VERSION} = delete $MM_ARGS{PREREQ_PM}{perl} || 0;
+
+delete $MM_ARGS{MIN_PERL_VERSION}
+ if $eumm_version < 6.47_01;
+$MM_ARGS{BUILD_REQUIRES} = {%{$MM_ARGS{BUILD_REQUIRES}}, %{delete $MM_ARGS{TEST_REQUIRES}}}
+ if $eumm_version < 6.63_03;
+$MM_ARGS{PREREQ_PM} = {%{$MM_ARGS{PREREQ_PM}}, %{delete $MM_ARGS{BUILD_REQUIRES}}}
+ if $eumm_version < 6.55_01;
+delete $MM_ARGS{CONFIGURE_REQUIRES}
+ if $eumm_version < 6.51_03;
+
+ExtUtils::MakeMaker::WriteMakefile(%MM_ARGS);
+## END BOILERPLATE ###########################################################
diff --git a/README b/README
new file mode 100644
index 0000000..fdaf853
--- /dev/null
+++ b/README
@@ -0,0 +1,46 @@
+NAME
+ Module::Reader - Read the source of a module like perl does
+
+SYNOPSIS
+ use Module::Reader qw(:all);
+ my $io = module_handle('My::Module');
+ my $content = module_content('My::Module');
+
+ my $io = module_handle('My::Module', @search_dirs);
+
+ my $io = module_handle('My::Module', @search_dirs, { found => \%INC });
+
+DESCRIPTION
+ Reads the content of perl modules the same way perl does. This includes
+ reading modules available only by @INC hooks, or filtered through them.
+
+EXPORTS
+ module_handle( $module_name, @search_dirs, \%options )
+ Returns an IO handle to the given module. Searches the directories
+ specified, or @INC if none are.
+
+ Options
+ found
+ A reference to a hash like %INC with module file names (in the style
+ 'My/Module.pm') as keys and full file paths as values. Modules
+ listed in this will be used in preference to searching through
+ directories.
+
+ module_content( $module_name, @search_dirs, \%options )
+ Returns the content of the given module. Accepts the same options as
+ "module_handle".
+
+AUTHOR
+ haarg - Graham Knop (cpan:HAARG) <haarg@haarg.org>
+
+ CONTRIBUTORS
+ None yet.
+
+COPYRIGHT
+ Copyright (c) 2013 the Module::Reader "AUTHOR" and "CONTRIBUTORS" as
+ listed above.
+
+LICENSE
+ This library is free software and may be distributed under the same
+ terms as perl itself.
+
diff --git a/lib/Module/Reader.pm b/lib/Module/Reader.pm
new file mode 100644
index 0000000..f263915
--- /dev/null
+++ b/lib/Module/Reader.pm
@@ -0,0 +1,174 @@
+package Module::Reader;
+BEGIN { require 5.006 }
+use strict;
+use warnings;
+
+our $VERSION = '0.002003';
+$VERSION = eval $VERSION;
+
+use base 'Exporter';
+our @EXPORT_OK = qw(module_content module_handle);
+our %EXPORT_TAGS = (all => [@EXPORT_OK]);
+
+use File::Spec;
+use Scalar::Util qw(blessed reftype openhandle);
+use Carp;
+use constant _OPEN_STRING => $] >= 5.008;
+BEGIN {
+ require IO::String
+ if !_OPEN_STRING;
+}
+
+sub module_content {
+ my $module = _get_module(@_);
+ if (ref $module) {
+ local $/;
+ return scalar <$module>;
+ }
+ else {
+ return $module;
+ }
+}
+
+sub module_handle {
+ my $module = _get_module(@_);
+ if (ref $module) {
+ return $module;
+ }
+ elsif (_OPEN_STRING) {
+ open my $fh, '<', \$module;
+ return $fh;
+ }
+ else {
+ return IO::String->new($module);
+ }
+}
+
+sub _get_module {
+ my ($package, @inc) = @_;
+ (my $module = "$package.pm") =~ s{::}{/}g;
+ my $opts = ref $_[-1] && ref $_[-1] eq 'HASH' && pop @inc || {};
+ if (!@inc) {
+ @inc = @INC;
+ }
+ if (my $found = $opts->{found}) {
+ if (my $full_module = $found->{$module}) {
+ if (ref $full_module) {
+ @inc = $full_module;
+ }
+ elsif (-f $full_module) {
+ open my $fh, '<', $full_module
+ or die "Couldn't open ${full_module} for ${module}: $!";
+ return $fh;
+ }
+ }
+ }
+ for my $inc (@inc) {
+ if (!ref $inc) {
+ my $full_module = File::Spec->catfile($inc, $module);
+ next unless -f $full_module;
+ open my $fh, '<', $full_module
+ or die "Couldn't open ${full_module} for ${module}: $!";
+ return $fh;
+ }
+
+ my @cb = ref $inc eq 'ARRAY' ? $inc->[0]->($inc, $module)
+ : blessed $inc ? $inc->INC($module)
+ : $inc->($inc, $module);
+
+ next
+ unless ref $cb[0];
+ my $fh;
+ if (reftype $cb[0] eq 'GLOB' && openhandle $cb[0]) {
+ $fh = shift @cb;
+ }
+
+ if (ref $cb[0] eq 'CODE') {
+ my $cb = shift @cb;
+ # require docs are wrong, perl sends 0 as the first param
+ my @params = (0, @cb ? $cb[0] : ());
+
+ my $module = '';
+ while (1) {
+ local $_ = $fh ? <$fh> : '';
+ $_ = ''
+ if !defined;
+ last if !$cb->(@params);
+ $module .= $_;
+ }
+ return $module;
+ }
+ elsif ($fh) {
+ return $fh;
+ }
+ }
+ croak "Can't find module $module";
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Module::Reader - Read the source of a module like perl does
+
+=head1 SYNOPSIS
+
+ use Module::Reader qw(:all);
+ my $io = module_handle('My::Module');
+ my $content = module_content('My::Module');
+
+ my $io = module_handle('My::Module', @search_dirs);
+
+ my $io = module_handle('My::Module', @search_dirs, { found => \%INC });
+
+=head1 DESCRIPTION
+
+Reads the content of perl modules the same way perl does. This
+includes reading modules available only by L<@INC hooks|perlfunc/require>, or filtered
+through them.
+
+=head1 EXPORTS
+
+=head2 module_handle( $module_name, @search_dirs, \%options )
+
+Returns an IO handle to the given module. Searches the directories
+specified, or L<@INC|perlvar/@INC> if none are.
+
+=head3 Options
+
+=over 4
+
+=item found
+
+A reference to a hash like L<%INC|perlvar/%INC> with module file names (in the
+style 'F<My/Module.pm>') as keys and full file paths as values.
+Modules listed in this will be used in preference to searching
+through directories.
+
+=back
+
+=head2 module_content( $module_name, @search_dirs, \%options )
+
+Returns the content of the given module. Accepts the same options as C<module_handle>.
+
+=head1 AUTHOR
+
+haarg - Graham Knop (cpan:HAARG) <haarg@haarg.org>
+
+=head2 CONTRIBUTORS
+
+None yet.
+
+=head1 COPYRIGHT
+
+Copyright (c) 2013 the Module::Reader L</AUTHOR> and L</CONTRIBUTORS>
+as listed above.
+
+=head1 LICENSE
+
+This library is free software and may be distributed under the same terms
+as perl itself.
+
+=cut
diff --git a/maint/Makefile.PL.include b/maint/Makefile.PL.include
new file mode 100644
index 0000000..e3a9588
--- /dev/null
+++ b/maint/Makefile.PL.include
@@ -0,0 +1,7 @@
+BEGIN { -e 'Distar' or system("git clone git://git.shadowcat.co.uk/p5sagit/Distar.git") }
+use lib 'Distar/lib';
+use Distar;
+
+use ExtUtils::MakeMaker 6.58;
+
+author 'haarg - Graham Knop (cpan:HAARG) <haarg@haarg.org>';
diff --git a/t/00-load.t b/t/00-load.t
new file mode 100644
index 0000000..06de4f7
--- /dev/null
+++ b/t/00-load.t
@@ -0,0 +1,6 @@
+use strict;
+
+use Test::More tests => 1;
+
+require_ok('Module::Reader')
+ || BAIL_OUT("Stopping due to compile failure!");
diff --git a/t/lib/TestLib.pm b/t/lib/TestLib.pm
new file mode 100644
index 0000000..3e1b6ff
--- /dev/null
+++ b/t/lib/TestLib.pm
@@ -0,0 +1,3 @@
+package TestLib;
+
+1;
diff --git a/t/main.t b/t/main.t
new file mode 100644
index 0000000..67c86ae
--- /dev/null
+++ b/t/main.t
@@ -0,0 +1,19 @@
+use strict;
+use warnings;
+
+use Test::More 0.88;
+use Module::Reader qw(:all);
+
+my $mod_content = do {
+ open my $fh, '<', 't/lib/TestLib.pm';
+ local $/;
+ <$fh>;
+};
+
+{
+ local @INC = @INC;
+ unshift @INC, 't/lib';
+ is module_content('TestLib'), $mod_content, 'correctly load module from disk';
+}
+
+done_testing;
diff --git a/t/memory.t b/t/memory.t
new file mode 100644
index 0000000..d33974e
--- /dev/null
+++ b/t/memory.t
@@ -0,0 +1,45 @@
+use strict;
+use warnings;
+
+use Test::More 0.88;
+use Module::Reader qw(:all);
+
+my $mod_content = do {
+ open my $fh, '<', 't/lib/TestLib.pm';
+ local $/;
+ <$fh>;
+};
+
+{
+ local @INC = @INC;
+ unshift @INC, sub {
+ return unless $_[1] eq 'TestLib.pm';
+ if ($] < 5.008) {
+ my $mod = $mod_content;
+ return sub {
+ return 0 unless length $mod;
+ $mod =~ s/^([^\n]*\n?)//;
+ $_ = $1;
+ return 1;
+ };
+ }
+ open my $fh, '<', \$mod_content;
+ return $fh;
+ };
+ is module_content('TestLib'), $mod_content, 'correctly load module from sub @INC hook';
+ SKIP: {
+ skip 'found option doesn\'t work with @INC hooks in perl < 5.8', 2
+ if $] < 5.008;
+ require TestLib;
+ unshift @INC, sub {
+ return unless $_[1] eq 'TestLib.pm';
+ my $content = '1;';
+ open my $fh, '<', \$content;
+ return $fh;
+ };
+ is module_content('TestLib'), '1;', 'loads overridden module from sub @INC hook';
+ is module_content('TestLib', { found => \%INC } ), $mod_content, 'found => \%INC loads mod as it was required';
+ }
+}
+
+done_testing;