require describes inserting hooks into @INC.
I've been testing this out for use in a module I'm writing.
Here's a very cutdown version of the code:
package RequireHookTest;
use 5.032;
use warnings;
use Moose;
use namespace::autoclean;
sub dynamic_require {
my ($self, $ns_extension) = @_;
{
my $class = join '::', __PACKAGE__, $ns_extension;
my $source = <<~EOF;
package $class;
use Moose;
extends 'RequireHookTest';
use namespace::autoclean;
__PACKAGE__->meta->make_immutable;
1;
EOF
my sub for_inc {
my ($coderef, $filename) = @_;
return \$source
};
my $for_inc_ref = \&for_inc;
push @INC, $for_inc_ref;
eval "require $class;";
}
return;
}
__PACKAGE__->meta->make_immutable;
1;
Calling dynamic_require() worked a treat at first;
however, when testing with an additional call, I got the quite unexpected message:
Can't locate object method "new" ... for the second call (the first call still worked fine).
Here's an SSCCE:
#!perl
use 5.032;
use warnings;
use FindBin;
use lib "$FindBin::Bin/lib";
use Test::More tests => 6;
use RequireHookTest;
my $rht = RequireHookTest::->new();
is(defined $rht, 1, 'Test RequireHookTest::->new()');
isa_ok($rht, 'RequireHookTest', 'Test RequireHookTest::->new() ISA');
$rht->dynamic_require('Test1');
my $rht_test1 = RequireHookTest::Test1->new();
is(defined $rht_test1, 1, 'Test RequireHookTest::Test1->new()');
isa_ok($rht_test1, 'RequireHookTest::Test1', 'Test RequireHookTest::Te
+st1->new() ISA');
$rht->dynamic_require('Test2');
my $rht_test2 = RequireHookTest::Test2->new();
is(defined $rht_test2, 1, 'Test RequireHookTest::Test2->new()');
isa_ok($rht_test2, 'RequireHookTest::Test2', 'Test RequireHookTest::Te
+st2->new() ISA');
Example run:
$ prove -v sscce_require_hook_test.t
sscce_require_hook_test.t ..
1..6
ok 1 - Test RequireHookTest::->new()
ok 2 - 'Test RequireHookTest::->new() ISA' isa 'RequireHookTest'
ok 3 - Test RequireHookTest::Test1->new()
ok 4 - 'Test RequireHookTest::Test1->new() ISA' isa 'RequireHookTest::
+Test1'
Can't locate object method "new" via package "RequireHookTest::Test2"
+at sscce_require_hook_test.t line 23.
# Looks like your test exited with 255 just after 4.
Dubious, test returned 255 (wstat 65280, 0xff00)
Failed 2/6 subtests
Test Summary Report
-------------------
sscce_require_hook_test.t (Wstat: 65280 Tests: 4 Failed: 0)
Non-zero exit status: 255
Parse errors: Bad plan. You planned 6 tests but ran 4.
Files=1, Tests=4, 0 wallclock secs ( 0.00 usr 0.03 sys + 0.20 cusr
+ 0.09 csys = 0.33 CPU)
Result: FAIL
If I swap the last two blocks of code around, "Test2" works and "Test1" has the new() problem:
...
ok 3 - Test RequireHookTest::Test2->new()
ok 4 - 'Test RequireHookTest::Test2->new() ISA' isa 'RequireHookTest::
+Test2'
Can't locate object method "new" via package "RequireHookTest::Test1"
+at sscce_require_hook_test.t line 23.
...
In the module code, I tried pushing an ARRAYREF, instead of a CODEREF, onto @INC:
push @INC, [ $for_inc_ref ];
but the result was the same.
I've also tried various versions where use namespace::autoclean; and/or __PACKAGE__->meta->make_immutable;
were excluded just in case that made any difference: it didn't.
This one's got me stumped. Any help would be very much appreciated.
Note:
My (real) code is using version 5.32.0 so I've left that specified.