Skip Menu |

Preferred bug tracker

Please visit the preferred bug tracker to report your issue.

This queue is for tickets about the Class-Inspector CPAN distribution.

Report information
The Basics
Id: 42846
Status: resolved
Priority: 0/
Queue: Class-Inspector

People
Owner: Nobody in particular
Requestors: TJC [...] cpan.org
Cc: tobyc [...] strategicdata.com.au
AdminCc:

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



CC: tobyc [...] strategicdata.com.au
Subject: installed() fails when the module was inside a PAR file, but script was not.
Class::Inspector's installed() method fails to locate a module if that module.pm was inside a PAR file, and the PAR file was being accessed from a script via the "use PAR 'foobar.par';" method. If both the script.pl and module.pm are inside the PAR, and you access via 'parl foobar.par script.pl' then it works fine. See attached files for demonstration, by doing: $ parl foobar.par test_inspector.pl Foo::Bar is found :) $ ./test_inspector_par.pl Foo::Bar not found! :( $
Subject: test_inspector_par.pl
#!/usr/bin/perl use strict; use warnings; use PAR 'foobar.par'; use Class::Inspector; if (Class::Inspector->installed('Foo::Bar')) { print "Foo::Bar is found :)\n"; } else { die "Foo::Bar not found! :(\n"; }
Subject: foobar.par
Download foobar.par
application/octet-stream 844b

Message body not shown because it is not plain text.

See line 636, function resolved_filename(): # Look through the @INC path to find the file foreach ( @try_first, @INC ) { my $full = "$_/$filename"; next unless -e $full; return $UNIX ? $full : $class->_inc_to_local($full); } That'll be trying to test: -e "CODE(0xd34db33f)/Foo/Bar.pm" which will where it all falls down..
I propose the attached patch. This essentially changes the behavior of ->installed to check code refs @INC. It works with PAR Left unaddressed with this patch: 1. What resolved_filename should return (if anything) for a file inside a PAR archive. 2. support for other @INC hooks, like arrays and objects. I do not know that these are commonly used, but the implementation can be easily extended to support these methods too, if this patch is acceptable for simple coderef @INC hooks.
Subject: ci.patch
diff --git a/lib/Class/Inspector.pm b/lib/Class/Inspector.pm index d54de9a..a9735df 100644 --- a/lib/Class/Inspector.pm +++ b/lib/Class/Inspector.pm @@ -87,9 +87,25 @@ or C<undef> if the class name is invalid. =cut +sub _resolved_inc_handler { + my $class = shift; + my $filename = $class->_inc_filename(shift) or return undef; + + foreach my $inc ( @INC ) { + if(ref $inc eq 'CODE') { + my @ret = $inc->($inc, $filename); + if(@ret) { + return 1; + } + } + } + + ''; +} + sub installed { my $class = shift; - !! ($class->loaded_filename($_[0]) or $class->resolved_filename($_[0])); + !! ($class->loaded_filename($_[0]) or $class->resolved_filename($_[0]) or $class->_resolved_inc_handler($_[0])); } =pod diff --git a/t/02_main.t b/t/02_main.t index 4899523..461240a 100644 --- a/t/02_main.t +++ b/t/02_main.t @@ -21,7 +21,7 @@ use constant CI => 'Class::Inspector'; use constant BAD => 'Class::Inspector::Nonexistant'; # How many functions and public methods are there in Class::Inspector -my $base_functions = 17; +my $base_functions = 18; my $base_public = 12; my $base_private = $base_functions - $base_public; diff --git a/t/04_main_functions.t b/t/04_main_functions.t index e7c9df5..8018d89 100644 --- a/t/04_main_functions.t +++ b/t/04_main_functions.t @@ -11,7 +11,7 @@ BEGIN { # $DB::single = 1; } -use Test::More tests => 21; +use Test::More tests => 22; use Class::Inspector::Functions; # To make maintaining this a little faster, @@ -68,7 +68,18 @@ ok( ($filename eq $inc_filename or index( loaded_filename(CI), $inc_filename ) = ok( index( resolved_filename(CI), $filename ) >= 0, "resolved_filename works" ); ok( ($filename eq $inc_filename or index( resolved_filename(CI), $inc_filename ) == -1), "resolved_filename works" ); +unshift @INC, sub { + my $coderef = shift; + my $filename = shift; + + if ($filename eq 'Foo/Bar.pm') { + open my $fh, '<', __FILE__; + return (undef, $fh); + } + return +}; + # Check the installed stuff ok( installed( CI ), "installed detects installed" ); ok( ! installed( BAD ), "installed detects not installed" ); - +ok( installed( 'Foo::Bar'), "installed detects coderef installed" );
I believe this to be fixed in 1.29_01. Please let me know if you find otherwise.