📄 conditional.pm
字号:
### regex breaks under -T, we must modifiy it so ### it captures the entire expression, and eval /that/ ### rather than $_, which is insecure. if( $str =~ /(?<!\\)([\$*])(([\w\:\']*)\bVERSION)\b.*\=/ ) { print "Evaluating: $str\n" if $verbose; ### this creates a string to be eval'd, like: # package Module::Load::Conditional::_version; # no strict; # # local $VERSION; # $VERSION=undef; do { # use version; $VERSION = qv('0.0.3'); # }; $VERSION my $eval = qq{ package Module::Load::Conditional::_version; no strict; local $1$2; \$$2=undef; do { $str }; \$$2 }; print "Evaltext: $eval\n" if $verbose; my $result = do { local $^W = 0; eval($eval); }; my $rv = defined $result ? $result : '0.0'; print( $@ ? "Error: $@\n" : "Result: $rv\n" ) if $verbose; return $rv; } ### unable to find a version in this string return;}=head2 $bool = can_load( modules => { NAME => VERSION [,NAME => VERSION] }, [verbose => BOOL, nocache => BOOL] )C<can_load> will take a list of modules, optionally with versionnumbers and determine if it is able to load them. If it can load *ALL*of them, it will. If one or more are unloadable, none will be loaded.This is particularly useful if you have More Than One Way (tm) tosolve a problem in a program, and only wish to continue down a pathif all modules could be loaded, and not load them if they couldn't.This function uses the C<load> function from Module::Load under thehood.C<can_load> takes the following arguments:=over 4=item modulesThis is a hashref of module/version pairs. The version indicates theminimum version to load. If no version is provided, any version isassumed to be good enough.=item verboseThis controls whether warnings should be printed if a module failedto load.The default is to use the value of $Module::Load::Conditional::VERBOSE.=item nocacheC<can_load> keeps its results in a cache, so it will not load thesame module twice, nor will it attempt to load a module that hasalready failed to load before. By default, C<can_load> will check itscache, but you can override that by setting C<nocache> to true.=cutsub can_load { my %hash = @_; my $tmpl = { modules => { default => {}, strict_type => 1 }, verbose => { default => $VERBOSE }, nocache => { default => 0 }, }; my $args; unless( $args = check( $tmpl, \%hash, $VERBOSE ) ) { $ERROR = loc(q[Problem validating arguments!]); warn $ERROR if $VERBOSE; return; } ### layout of $CACHE: ### $CACHE = { ### $ module => { ### usable => BOOL, ### version => \d, ### file => /path/to/file, ### }, ### }; $CACHE ||= {}; # in case it was undef'd my $error; BLOCK: { my $href = $args->{modules}; my @load; for my $mod ( keys %$href ) { next if $CACHE->{$mod}->{usable} && !$args->{nocache}; ### else, check if the hash key is defined already, ### meaning $mod => 0, ### indicating UNSUCCESSFUL prior attempt of usage ### use qv(), as it will deal with developer release number ### ie ones containing _ as well. This addresses bug report ### #29348: Version compare logic doesn't handle alphas? if ( !$args->{nocache} && defined $CACHE->{$mod}->{usable} && (qv($CACHE->{$mod}->{version}||0) >= qv($href->{$mod})) ) { $error = loc( q[Already tried to use '%1', which was unsuccessful], $mod); last BLOCK; } my $mod_data = check_install( module => $mod, version => $href->{$mod} ); if( !$mod_data or !defined $mod_data->{file} ) { $error = loc(q[Could not find or check module '%1'], $mod); $CACHE->{$mod}->{usable} = 0; last BLOCK; } map { $CACHE->{$mod}->{$_} = $mod_data->{$_} } qw[version file uptodate]; push @load, $mod; } for my $mod ( @load ) { if ( $CACHE->{$mod}->{uptodate} ) { eval { load $mod }; ### in case anything goes wrong, log the error, the fact ### we tried to use this module and return 0; if( $@ ) { $error = $@; $CACHE->{$mod}->{usable} = 0; last BLOCK; } else { $CACHE->{$mod}->{usable} = 1; } ### module not found in @INC, store the result in ### $CACHE and return 0 } else { $error = loc(q[Module '%1' is not uptodate!], $mod); $CACHE->{$mod}->{usable} = 0; last BLOCK; } } } # BLOCK if( defined $error ) { $ERROR = $error; Carp::carp( loc(q|%1 [THIS MAY BE A PROBLEM!]|,$error) ) if $args->{verbose}; return; } else { return 1; }}=back=head2 @list = requires( MODULE );C<requires> can tell you what other modules a particular modulerequires. This is particularly useful when you're intending to writea module for public release and are listing its prerequisites.C<requires> takes but one argument: the name of a module.It will then first check if it can actually load this module, andreturn undef if it can't.Otherwise, it will return a list of modules and pragmas that wouldhave been loaded on the module's behalf.Note: The list C<require> returns has originated from your currentperl and your current install.=cutsub requires { my $who = shift; unless( check_install( module => $who ) ) { warn loc(q[You do not have module '%1' installed], $who) if $VERBOSE; return undef; } my $lib = join " ", map { qq["-I$_"] } @INC; my $cmd = qq[$^X $lib -M$who -e"print(join(qq[\\n],keys(%INC)))"]; return sort grep { !/^$who$/ } map { chomp; s|/|::|g; $_ } grep { s|\.pm$||i; } `$cmd`;}1;__END__=head1 Global VariablesThe behaviour of Module::Load::Conditional can be altered by changing thefollowing global variables:=head2 $Module::Load::Conditional::VERBOSEThis controls whether Module::Load::Conditional will issue warnings andexplanations as to why certain things may have failed. If you set itto 0, Module::Load::Conditional will not output any warnings.The default is 0;=head2 $Module::Load::Conditional::FIND_VERSIONThis controls whether Module::Load::Conditional will try to parse(and eval) the version from the module you're trying to load. If you don't wish to do this, set this variable to C<false>. Understandthen that version comparisons are not possible, and Module::Load::Conditionalcan not tell you what module version you have installed.This may be desirable from a security or performance point of view. Note that C<$FIND_VERSION> code runs safely under C<taint mode>.The default is 1;=head2 $Module::Load::Conditional::CHECK_INC_HASHThis controls whether C<Module::Load::Conditional> checks yourC<%INC> hash to see if a module is available. By default, onlyC<@INC> is scanned to see if a module is physically on yourfilesystem, or avialable via an C<@INC-hook>. Setting this variableto C<true> will trust any entries in C<%INC> and return them foryou.The default is 0;=head2 $Module::Load::Conditional::CACHEThis holds the cache of the C<can_load> function. If you explicitlywant to remove the current cache, you can set this variable toC<undef>=head2 $Module::Load::Conditional::ERRORThis holds a string of the last error that happened during a call toC<can_load>. It is useful to inspect this when C<can_load> returnsC<undef>.=head1 See AlsoC<Module::Load>=head1 BUG REPORTSPlease report bugs or other issues to E<lt>bug-module-load-conditional@rt.cpan.orgE<gt>.=head1 AUTHORThis module by Jos Boumans E<lt>kane@cpan.orgE<gt>.=head1 COPYRIGHTThis library is free software; you may redistribute and/or modify it under the same terms as Perl itself.=cut
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -