1 package Module::Load::Conditional;
6 use Params::Check qw[check];
7 use Locale::Maketext::Simple Style => 'gettext';
14 use vars qw[ $VERSION @ISA $VERBOSE $CACHE @EXPORT_OK
15 $FIND_VERSION $ERROR $CHECK_INC_HASH];
22 @EXPORT_OK = qw[check_install can_load requires];
29 Module::Load::Conditional - Looking up module information / loading at runtime
33 use Module::Load::Conditional qw[can_load check_install requires];
39 'Test::More' => undef,
42 print can_load( modules => $use_list )
43 ? 'all modules loaded successfully'
44 : 'failed to load required modules';
47 my $rv = check_install( module => 'LWP', version => 5.60 )
48 or print 'LWP is not installed!';
50 print 'LWP up to date' if $rv->{uptodate};
51 print "LWP version is $rv->{version}\n";
52 print "LWP is installed as file $rv->{file}\n";
55 print "LWP requires the following modules to be installed:\n";
56 print join "\n", requires('LWP');
58 ### allow M::L::C to peek in your %INC rather than just
60 $Module::Load::Conditional::CHECK_INC_HASH = 1;
62 ### reset the 'can_load' cache
63 undef $Module::Load::Conditional::CACHE;
65 ### don't have Module::Load::Conditional issue warnings --
67 $Module::Load::Conditional::VERBOSE = 0;
69 ### The last error that happened during a call to 'can_load'
70 my $err = $Module::Load::Conditional::ERROR;
75 Module::Load::Conditional provides simple ways to query and possibly load any of
76 the modules you have installed on your system during runtime.
78 It is able to load multiple modules at once or none at all if one of
79 them was not able to load. It also takes care of any error checking
84 =head1 $href = check_install( module => NAME [, version => VERSION, verbose => BOOL ] );
86 C<check_install> allows you to verify if a certain module is installed
87 or not. You may call it with the following arguments:
93 The name of the module you wish to verify -- this is a required key
97 The version this module needs to be -- this is optional
101 Whether or not to be verbose about what it is doing -- it will default
102 to $Module::Load::Conditional::VERBOSE
106 It will return undef if it was not able to find where the module was
107 installed, or a hash reference with the following keys if it was able
114 Full path to the file that contains the module
118 The version number of the installed module - this will be C<undef> if
119 the module had no (or unparsable) version number, or if the variable
120 C<$Module::Load::Conditional::FIND_VERSION> was set to true.
121 (See the C<GLOBAL VARIABLES> section below for details)
125 A boolean value indicating whether or not the module was found to be
126 at least the version you specified. If you did not specify a version,
127 uptodate will always be true if the module was found.
128 If no parsable version was found in the module, uptodate will also be
129 true, since C<check_install> had no way to verify clearly.
135 ### this checks if a certain module is installed already ###
136 ### if it returns true, the module in question is already installed
137 ### or we found the file, but couldn't open it, OR there was no version
138 ### to be found in the module
139 ### it will return 0 if the version in the module is LOWER then the one
140 ### we are looking for, or if we couldn't find the desired module to begin with
141 ### if the installed version is higher or equal to the one we want, it will return
142 ### a hashref with he module name and version in it.. so 'true' as well.
147 version => { default => '0.0' },
148 module => { required => 1 },
149 verbose => { default => $VERBOSE },
153 unless( $args = check( $tmpl, \%hash, $VERBOSE ) ) {
154 warn loc( q[A problem occurred checking arguments] ) if $VERBOSE;
158 my $file = File::Spec->catfile( split /::/, $args->{module} ) . '.pm';
159 my $file_inc = File::Spec::Unix->catfile(
160 split /::/, $args->{module}
163 ### where we store the return value ###
172 ### check the inc hash if we're allowed to
173 if( $CHECK_INC_HASH ) {
174 $filename = $href->{'file'} =
175 $INC{ $file_inc } if defined $INC{ $file_inc };
177 ### find the version by inspecting the package
178 if( defined $filename && $FIND_VERSION ) {
180 $href->{version} = ${ "$args->{module}"."::VERSION" };
184 ### we didnt find the filename yet by looking in %INC,
186 unless( $filename ) {
188 DIR: for my $dir ( @INC ) {
193 ### @INC hook -- we invoke it and get the filehandle back
194 ### this is actually documented behaviour as of 5.8 ;)
196 if (UNIVERSAL::isa($dir, 'CODE')) {
197 ($fh) = $dir->($dir, $file);
199 } elsif (UNIVERSAL::isa($dir, 'ARRAY')) {
200 ($fh) = $dir->[0]->($dir, $file, @{$dir}{1..$#{$dir}})
202 } elsif (UNIVERSAL::can($dir, 'INC')) {
203 ($fh) = $dir->INC->($dir, $file);
206 if (!UNIVERSAL::isa($fh, 'GLOB')) {
207 warn loc(q[Cannot open file '%1': %2], $file, $!)
212 $filename = $INC{$file_inc} || $file;
215 $filename = File::Spec->catfile($dir, $file);
216 next unless -e $filename;
218 $fh = new FileHandle;
219 if (!$fh->open($filename)) {
220 warn loc(q[Cannot open file '%1': %2], $file, $!)
226 $href->{file} = $filename;
228 ### user wants us to find the version from files
229 if( $FIND_VERSION ) {
232 while (local $_ = <$fh> ) {
234 ### stolen from EU::MM_Unix->parse_version to address
235 ### #24062: "Problem with CPANPLUS 0.076 misidentifying
236 ### versions after installing Text::NSP 1.03" where a
237 ### VERSION mentioned in the POD was found before
238 ### the real $VERSION declaration.
239 $in_pod = /^=(?!cut)/ ? 1 : /^=cut/ ? 0 : $in_pod;
242 ### skip commented out lines, they won't eval to anything.
245 ### the following regexp comes from the ExtUtils::MakeMaker
247 ### Following #18892, which tells us the original
248 ### regex breaks under -T, we must modifiy it so
249 ### it captures the entire expression, and eval /that/
250 ### rather than $_, which is insecure.
251 if ( /([\$*][\w\:\']*\bVERSION\b.*\=.*)/ ) {
253 ### this will eval the version in to $VERSION if it
254 ### was declared as $VERSION in the module.
255 ### else the result will be in $res.
256 ### this is a fix on skud's Module::InstalledVersion
261 ### default to '0.0' if there REALLY is no version
262 ### all to satisfy warnings
263 $href->{version} = $VERSION || $res || '0.0';
272 ### if we couldn't find the file, return undef ###
273 return unless defined $href->{file};
275 ### only complain if we expected fo find a version higher than 0.0 anyway
276 if( $FIND_VERSION and not defined $href->{version} ) {
277 { ### don't warn about the 'not numeric' stuff ###
280 ### if we got here, we didn't find the version
281 warn loc(q[Could not check version on '%1'], $args->{module} )
282 if $args->{verbose} and $args->{version} > 0;
284 $href->{uptodate} = 1;
287 ### don't warn about the 'not numeric' stuff ###
289 $href->{uptodate} = $args->{version} <= $href->{version} ? 1 : 0;
295 =head2 $bool = can_load( modules => { NAME => VERSION [,NAME => VERSION] }, [verbose => BOOL, nocache => BOOL] )
297 C<can_load> will take a list of modules, optionally with version
298 numbers and determine if it is able to load them. If it can load *ALL*
299 of them, it will. If one or more are unloadable, none will be loaded.
301 This is particularly useful if you have More Than One Way (tm) to
302 solve a problem in a program, and only wish to continue down a path
303 if all modules could be loaded, and not load them if they couldn't.
305 This function uses the C<load> function from Module::Load under the
308 C<can_load> takes the following arguments:
314 This is a hashref of module/version pairs. The version indicates the
315 minimum version to load. If no version is provided, any version is
316 assumed to be good enough.
320 This controls whether warnings should be printed if a module failed
322 The default is to use the value of $Module::Load::Conditional::VERBOSE.
326 C<can_load> keeps its results in a cache, so it will not load the
327 same module twice, nor will it attempt to load a module that has
328 already failed to load before. By default, C<can_load> will check its
329 cache, but you can override that by setting C<nocache> to true.
337 modules => { default => {}, strict_type => 1 },
338 verbose => { default => $VERBOSE },
339 nocache => { default => 0 },
344 unless( $args = check( $tmpl, \%hash, $VERBOSE ) ) {
345 $ERROR = loc(q[Problem validating arguments!]);
346 warn $ERROR if $VERBOSE;
350 ### layout of $CACHE:
355 ### file => /path/to/file,
359 $CACHE ||= {}; # in case it was undef'd
363 my $href = $args->{modules};
366 for my $mod ( keys %$href ) {
368 next if $CACHE->{$mod}->{usable} && !$args->{nocache};
370 ### else, check if the hash key is defined already,
371 ### meaning $mod => 0,
372 ### indicating UNSUCCESSFUL prior attempt of usage
373 if ( !$args->{nocache}
374 && defined $CACHE->{$mod}->{usable}
375 && (($CACHE->{$mod}->{version}||0) >= $href->{$mod})
377 $error = loc( q[Already tried to use '%1', which was unsuccessful], $mod);
381 my $mod_data = check_install(
383 version => $href->{$mod}
386 if( !$mod_data or !defined $mod_data->{file} ) {
387 $error = loc(q[Could not find or check module '%1'], $mod);
388 $CACHE->{$mod}->{usable} = 0;
393 $CACHE->{$mod}->{$_} = $mod_data->{$_}
394 } qw[version file uptodate];
399 for my $mod ( @load ) {
401 if ( $CACHE->{$mod}->{uptodate} ) {
405 ### in case anything goes wrong, log the error, the fact
406 ### we tried to use this module and return 0;
409 $CACHE->{$mod}->{usable} = 0;
412 $CACHE->{$mod}->{usable} = 1;
415 ### module not found in @INC, store the result in
416 ### $CACHE and return 0
419 $error = loc(q[Module '%1' is not uptodate!], $mod);
420 $CACHE->{$mod}->{usable} = 0;
427 if( defined $error ) {
429 Carp::carp( loc(q|%1 [THIS MAY BE A PROBLEM!]|,$error) ) if $args->{verbose};
436 =head2 @list = requires( MODULE );
438 C<requires> can tell you what other modules a particular module
439 requires. This is particularly useful when you're intending to write
440 a module for public release and are listing its prerequisites.
442 C<requires> takes but one argument: the name of a module.
443 It will then first check if it can actually load this module, and
444 return undef if it can't.
445 Otherwise, it will return a list of modules and pragmas that would
446 have been loaded on the module's behalf.
448 Note: The list C<require> returns has originated from your current
449 perl and your current install.
456 unless( check_install( module => $who ) ) {
457 warn loc(q[You do not have module '%1' installed], $who) if $VERBOSE;
461 my $lib = join " ", map { qq["-I$_"] } @INC;
462 my $cmd = qq[$^X $lib -M$who -e"print(join(qq[\\n],keys(%INC)))"];
466 map { chomp; s|/|::|g; $_ }
475 =head1 Global Variables
477 The behaviour of Module::Load::Conditional can be altered by changing the
478 following global variables:
480 =head2 $Module::Load::Conditional::VERBOSE
482 This controls whether Module::Load::Conditional will issue warnings and
483 explanations as to why certain things may have failed. If you set it
484 to 0, Module::Load::Conditional will not output any warnings.
487 =head2 $Module::Load::Conditional::FIND_VERSION
489 This controls whether Module::Load::Conditional will try to parse
490 (and eval) the version from the module you're trying to load.
492 If you don't wish to do this, set this variable to C<false>. Understand
493 then that version comparisons are not possible, and Module::Load::Conditional
494 can not tell you what module version you have installed.
495 This may be desirable from a security or performance point of view.
496 Note that C<$FIND_VERSION> code runs safely under C<taint mode>.
500 =head2 $Module::Load::Conditional::CHECK_INC_HASH
502 This controls whether C<Module::Load::Conditional> checks your
503 C<%INC> hash to see if a module is available. By default, only
504 C<@INC> is scanned to see if a module is physically on your
505 filesystem, or avialable via an C<@INC-hook>. Setting this variable
506 to C<true> will trust any entries in C<%INC> and return them for
511 =head2 $Module::Load::Conditional::CACHE
513 This holds the cache of the C<can_load> function. If you explicitly
514 want to remove the current cache, you can set this variable to
517 =head2 $Module::Load::Conditional::ERROR
519 This holds a string of the last error that happened during a call to
520 C<can_load>. It is useful to inspect this when C<can_load> returns
530 Jos Boumans E<lt>kane@cpan.orgE<gt>.
534 This module is copyright (c) 2002-2007 Jos Boumans
535 E<lt>kane@cpan.orgE<gt>. All rights reserved.
537 This library is free software; you may redistribute and/or modify
538 it under the same terms as Perl itself.