Array::Sticky::INC - lock your @INC hooks in place
Let's say you've written a module which hides the existence of certain modules:
package Module::Hider; my %hidden; my $set_up_already; sub hider { my ($module) = pop(); $module =~ s{/}{::}g; $module =~ s{\.pm$}{}; return undef if exists $hidden{$module}; } sub import { my ($class, @to_hide) = @_; @hidden{@to_hide} = @to_hide; if (! $set_up_already++) { # this works until some other piece of code issues a # use lib '/somewhere'; # or # unshift @INC, '/over'; # or # $INC[0] = '/the-rainbow'; unshift @INC, \&hider; } } 1;
To hide a module using this Module::Hider, you'd write:
use Module::Hider qw(strict warnings LWP::UserAgent);
Now any code which is running with that in place would encounter errors attempting to load strict.pm, warnings.pm, and LWP/UserAgent.pm.
Hiding modules is pretty nice; see Devel::Hide for a stronger treatment of why you might care to do so.
But there is one downside to the "stick a coderef in @INC" trick: if any piece of code manually updates @INC to steal the primary spot away from your coderef, then your coderef may be rendered ineffective.
This module provides a simple interface to tie @INC in a way that you specify so that attempts to manipulate @INC succeed in a way that you choose.
Now you may write Module::Hider like this:
package Module::Hider; use Array::Sticky::INC; my %hidden; my $set_up_already; sub hider { my ($module) = pop(); $module =~ s{/}{::}g; $module =~ s{\.pm$}{}; return undef if exists $hidden{$module}; } sub import { my ($class, @to_hide) = @_; @hidden{@to_hide} = @to_hide; if (! $set_up_already++) { unshift @INC, \&hider; Array::Sticky::INC->make_sticky; } } 1;
This module only makes the foremost element of @INC sticky. If you need to make different elements of @INC sticky, then use Array::Sticky:
If you're using like The::Net or Acme::Intraweb to automatically install modules that you're missing, then you might want to lock their behaviors to the end of @INC:
package My::The::Net; use The::Net; use Array::Sticky; sub import { tie @INC, 'Array::Sticky', body => [@INC], tail => [shift @INC]; }
Devel::INC::Sorted solves this same problem slightly differently.
'perldoc -f require' and 'perldoc perltie' talk about code hooks in @INC, and tied arrays, respectively
Acme::Intraweb - places a coderef at the tail of @INC
The::Net - places a coderef at the tail of @INC
Devel::Hide - places a coderef at the head of @INC
Test::Without::Module - places a coderef at the head of @INC
If you do something like:
local @INC = @INC; unshift @INC, '/some/path';
then this module won't be able to preserve your hooks at the head of @INC.
Please report bugs on this project's Github Issues page: http://github.com/belden/perl-array-sticky/issues.
The repository for this software is freely available on this project's Github page: http://github.com/belden/perl-array-sticky. You may fork it there and submit pull requests in the standard fashion.
(c) 2013 by Belden Lyman
This library is free software: you may redistribute it and/or modify it under the same terms as Perl itself; either Perl version 5.8.8 or, at your option, any later version of Perl 5 you may have available.
}
1;
__END__ =pod
Devel::TraceINC - Trace who is loading which perl modules
version 1.100850
$ perl -MDevel::TraceINC t/01_my_test.t Test/More.pm loaded from package main, file t/01_my_test.t, line 6 Test/Builder/Module.pm loaded from package Test::More, file /usr/local/svn/perl/Test/More.pm, line 22 Test/Builder.pm loaded from package Test::Builder::Module, file /usr/local/svn/perl/Test/Builder/Module.pm, line 3 Exporter/Heavy.pm loaded from package Exporter, file /System/Library/Perl/5.8.6/Exporter.pm, line 17 ...
I had a situation where a program was loading a module but I couldn't find where in the code it was loaded. It turned out that I loaded some module, which loaded another module, which loaded the module in question. To be able to track down who loads what, I wrote Devel::TraceINC.
Just use() the module and it will print a warning every time a module is searched for in @INC, i.e., loaded.
use()
@INC
See perlmodinstall for information and options on installing Perl modules.
No bugs have been reported.
Please report any bugs or feature requests through the web interface at http://rt.cpan.org/Public/Dist/Display.html?Name=Devel-TraceINC.
The latest version of this module is available from the Comprehensive Perl Archive Network (CPAN). Visit http://www.perl.com/CPAN/ to find a CPAN site near you, or see http://search.cpan.org/dist/Devel-TraceINC/.
The development version lives at http://github.com/marcelgrunauer/Devel-TraceINC/. Instead of sending patches, please fork this project using the standard git and github infrastructure.
Marcel Gruenauer <marcel@cpan.org>
This software is copyright (c) 2007 by Marcel Gruenauer.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.
To install Devel::TraceINC, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Devel::TraceINC
CPAN shell
perl -MCPAN -e shell install Devel::TraceINC
For more information on module installation, please visit the detailed CPAN module installation guide.