Added Cyg-Win

This commit is contained in:
Frank Harris 2026-06-06 18:46:40 -04:00
parent 82cbc206eb
commit 413c315806
10586 changed files with 3806249 additions and 0 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,256 @@
=head1 NAME
Module::CoreList - what modules shipped with versions of perl
=head1 SYNOPSIS
use Module::CoreList;
print $Module::CoreList::version{5.00503}{CPAN}; # prints 1.48
print Module::CoreList->first_release('File::Spec');
# prints 5.00405
print Module::CoreList->first_release_by_date('File::Spec');
# prints 5.005
print Module::CoreList->first_release('File::Spec', 0.82);
# prints 5.006001
if (Module::CoreList::is_core('File::Spec')) {
print "File::Spec is a core module\n";
}
print join ', ', Module::CoreList->find_modules(qr/Data/);
# prints 'Data::Dumper'
print join ', ',
Module::CoreList->find_modules(qr/test::h.*::.*s/i, 5.008008);
# prints 'Test::Harness::Assert, Test::Harness::Straps'
print join ", ", @{ $Module::CoreList::families{5.005} };
# prints "5.005, 5.00503, 5.00504"
=head1 DESCRIPTION
Module::CoreList provides information on which core and dual-life modules shipped
with each version of L<perl>.
It provides a number of mechanisms for querying this information.
There is a utility called L<corelist> provided with this module
which is a convenient way of querying from the command-line.
There is a functional programming API available for programmers to query
information.
Programmers may also query the contained hash structures to find relevant
information.
=head1 FUNCTIONS API
These are the functions that are available, they may either be called as functions or class methods:
Module::CoreList::first_release('File::Spec'); # as a function
Module::CoreList->first_release('File::Spec'); # class method
=over
=item C<first_release( MODULE )>
Behaviour since version 2.11
Requires a MODULE name as an argument, returns the perl version when that module first
appeared in core as ordered by perl version number or undef ( in scalar context )
or an empty list ( in list context ) if that module is not in core.
=item C<first_release_by_date( MODULE )>
Requires a MODULE name as an argument, returns the perl version when that module first
appeared in core as ordered by release date or undef ( in scalar context )
or an empty list ( in list context ) if that module is not in core.
=item C<find_modules( REGEX, [ LIST OF PERLS ] )>
Takes a regex as an argument, returns a list of modules that match the regex given.
If only a regex is provided applies to all modules in all perl versions. Optionally
you may provide a list of perl versions to limit the regex search.
=item C<find_version( PERL_VERSION )>
Takes a perl version as an argument. Upon successful completion, returns a
reference to a hash. Each element of that hash has a key which is the name of
a module (I<e.g.,> 'File::Path') shipped with that version of perl and a value
which is the version number (I<e.g.,> '2.09') of that module which shipped
with that version of perl . Returns C<undef> otherwise.
=item C<is_core( MODULE, [ MODULE_VERSION, [ PERL_VERSION ] ] )>
Available in version 2.99 and above.
Returns true if MODULE was bundled with the specified version of Perl.
You can optionally specify a minimum version of the module,
and can also specify a version of Perl.
If a version of Perl isn't specified,
C<is_core()> will use the numeric version of Perl that is running (ie C<$]>).
If you want to specify the version of Perl, but don't care about
the version of the module, pass C<undef> for the module version:
=item C<is_deprecated( MODULE, PERL_VERSION )>
Available in version 2.22 and above.
Returns true if MODULE is marked as deprecated in PERL_VERSION. If PERL_VERSION is
omitted, it defaults to the current version of Perl.
=item C<deprecated_in( MODULE )>
Available in version 2.77 and above.
Returns the first perl version where the MODULE was marked as deprecated. Returns C<undef>
if the MODULE has not been marked as deprecated.
=item C<removed_from( MODULE )>
Available in version 2.32 and above
Takes a module name as an argument, returns the first perl version where that module
was removed from core. Returns undef if the given module was never in core or remains
in core.
=item C<removed_from_by_date( MODULE )>
Available in version 2.32 and above
Takes a module name as an argument, returns the first perl version by release date where that module
was removed from core. Returns undef if the given module was never in core or remains
in core.
=item C<changes_between( PERL_VERSION, PERL_VERSION )>
Available in version 2.66 and above.
Given two perl versions, this returns a list of pairs describing the changes in
core module content between them. The list is suitable for storing in a hash.
The keys are library names and the values are hashrefs. Each hashref has an
entry for one or both of C<left> and C<right>, giving the versions of the
library in each of the left and right perl distributions.
For example, it might return these data (among others) for the difference
between 5.008000 and 5.008001:
'Pod::ParseLink' => { left => '1.05', right => '1.06' },
'Pod::ParseUtils' => { left => '0.22', right => '0.3' },
'Pod::Perldoc' => { right => '3.10' },
'Pod::Perldoc::BaseTo' => { right => undef },
This shows us two libraries being updated and two being added, one of which has
an undefined version in the right-hand side version.
=back
=head1 DATA STRUCTURES
These are the hash data structures that are available:
=over
=item C<%Module::CoreList::version>
A hash of hashes that is keyed on perl version as indicated
in $]. The second level hash is module => version pairs.
Note, it is possible for the version of a module to be unspecified,
whereby the value is C<undef>, so use C<exists $version{$foo}{$bar}> if
that's what you're testing for.
Starting with 2.10, the special module name C<Unicode> refers to the version of
the Unicode Character Database bundled with Perl.
=item C<%Module::CoreList::delta>
Available in version 3.00 and above.
It is a hash of hashes that is keyed on perl version. Each keyed hash will have the
following keys:
delta_from - a previous perl version that the changes are based on
changed - a hash of module/versions that have changed
removed - a hash of modules that have been removed
=item C<%Module::CoreList::released>
Keyed on perl version this contains ISO
formatted versions of the release dates, as gleaned from L<perlhist>.
=item C<%Module::CoreList::families>
New, in 1.96, a hash that
clusters known perl releases by their major versions.
=item C<%Module::CoreList::deprecated>
A hash of hashes keyed on perl version and on module name.
If a module is defined it indicates that that module is
deprecated in that perl version and is scheduled for removal
from core at some future point.
=item C<%Module::CoreList::upstream>
A hash that contains information on where patches should be directed
for each core module.
UPSTREAM indicates where patches should go. C<undef> implies
that this hasn't been discussed for the module at hand.
C<blead> indicates that the copy of the module in the blead
sources is to be considered canonical, C<cpan> means that the
module on CPAN is to be patched first. C<first-come> means
that blead can be patched freely if it is in sync with the
latest release on CPAN.
=item C<%Module::CoreList::bug_tracker>
A hash that contains information on the appropriate bug tracker
for each core module.
BUGS is an email or url to post bug reports. For modules with
UPSTREAM => 'blead', use L<mailto:perl5-porters@perl.org>. rt.cpan.org
appears to automatically provide a URL for CPAN modules; any value
given here overrides the default:
L<http://rt.cpan.org/Public/Dist/Display.html?Name=$ModuleName>
=back
=head1 CAVEATS
Module::CoreList currently covers the 5.000, 5.001, 5.002, 5.003_07,
5.004, 5.004_05, 5.005, 5.005_03, 5.005_04 and 5.7.3 releases of perl.
All stable releases of perl since 5.6.0 are covered.
All development releases of perl since 5.9.0 are covered.
=head1 HISTORY
Moved to Changes file.
=head1 AUTHOR
Richard Clamp E<lt>richardc@unixbeard.netE<gt>
Currently maintained by the perl 5 porters E<lt>perl5-porters@perl.orgE<gt>.
=head1 LICENSE
Copyright (C) 2002-2009 Richard Clamp. All Rights Reserved.
This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.
=head1 SEE ALSO
L<corelist>, L<Module::Info>, L<perl>, L<http://perlpunks.de/corelist>
=cut

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,373 @@
package Module::Load;
use strict;
use warnings;
use File::Spec ();
our $VERSION = '0.36';
sub import {
my $who = _who();
my $h; shift;
{ no strict 'refs';
@_ or (
*{"${who}::load"} = \&load, # compat to prev version
*{"${who}::autoload"} = \&autoload,
return
);
map { $h->{$_} = () if defined $_ } @_;
(exists $h->{none} or exists $h->{''})
and shift, last;
((exists $h->{autoload} and shift,1) or (exists $h->{all} and shift))
and *{"${who}::autoload"} = \&autoload;
((exists $h->{load} and shift,1) or exists $h->{all})
and *{"${who}::load"} = \&load;
((exists $h->{load_remote} and shift,1) or exists $h->{all})
and *{"${who}::load_remote"} = \&load_remote;
((exists $h->{autoload_remote} and shift,1) or exists $h->{all})
and *{"${who}::autoload_remote"} = \&autoload_remote;
}
}
sub load(*;@){
goto &_load;
}
sub autoload(*;@){
unshift @_, 'autoimport';
goto &_load;
}
sub load_remote($$;@){
my ($dst, $src, @exp) = @_;
eval "package $dst;Module::Load::load('$src', qw/@exp/);";
$@ && die "$@";
}
sub autoload_remote($$;@){
my ($dst, $src, @exp) = @_;
eval "package $dst;Module::Load::autoload('$src', qw/@exp/);";
$@ && die "$@";
}
sub _load{
my $autoimport = $_[0] eq 'autoimport' and shift;
my $mod = shift or return;
my $who = _who();
if( _is_file( $mod ) ) {
require $mod;
} else {
LOAD: {
my $err;
for my $flag ( qw[1 0] ) {
my $file = _to_file( $mod, $flag);
eval { require $file };
$@ ? $err .= $@ : last LOAD;
}
die $err if $err;
}
}
### This addresses #41883: Module::Load cannot import
### non-Exporter module. ->import() routines weren't
### properly called when load() was used.
{ no strict 'refs';
my $import;
((@_ or $autoimport) and (
$import = $mod->can('import')
) and (
unshift(@_, $mod),
goto &$import
)
);
}
}
sub _to_file{
local $_ = shift;
my $pm = shift || '';
## trailing blanks ignored by default. [rt #69886]
my @parts = split /::|'/, $_, -1;
## make sure that we can't hop out of @INC
shift @parts if @parts && !$parts[0];
### because of [perl #19213], see caveats ###
my $file = $^O eq 'MSWin32'
? join "/", @parts
: File::Spec->catfile( @parts );
$file .= '.pm' if $pm;
### on perl's before 5.10 (5.9.5@31746) if you require
### a file in VMS format, it's stored in %INC in VMS
### format. Therefor, better unixify it first
### Patch in reply to John Malmbergs patch (as mentioned
### above) on p5p Tue 21 Aug 2007 04:55:07
$file = VMS::Filespec::unixify($file) if $^O eq 'VMS';
return $file;
}
sub _who { (caller(1))[0] }
sub _is_file {
local $_ = shift;
return /^\./ ? 1 :
/[^\w:']/ ? 1 :
undef
#' silly bbedit..
}
1;
__END__
=pod
=head1 NAME
Module::Load - runtime require of both modules and files
=head1 SYNOPSIS
use Module::Load;
my $module = 'Data::Dumper';
load Data::Dumper; # loads that module, but not import any functions
# -> cannot use 'Dumper' function
load 'Data::Dumper'; # ditto
load $module # tritto
autoload Data::Dumper; # loads that module and imports the default functions
# -> can use 'Dumper' function
my $script = 'some/script.pl'
load $script;
load 'some/script.pl'; # use quotes because of punctuations
load thing; # try 'thing' first, then 'thing.pm'
load CGI, ':all'; # like 'use CGI qw[:standard]'
=head1 DESCRIPTION
C<Module::Load> eliminates the need to know whether you are trying
to require either a file or a module.
If you consult C<perldoc -f require> you will see that C<require> will
behave differently when given a bareword or a string.
In the case of a string, C<require> assumes you are wanting to load a
file. But in the case of a bareword, it assumes you mean a module.
This gives nasty overhead when you are trying to dynamically require
modules at runtime, since you will need to change the module notation
(C<Acme::Comment>) to a file notation fitting the particular platform
you are on.
C<Module::Load> eliminates the need for this overhead and will
just DWYM.
=head2 Difference between C<load> and C<autoload>
C<Module::Load> imports the two functions - C<load> and C<autoload>
C<autoload> imports the default functions automatically,
but C<load> do not import any functions.
C<autoload> is usable under C<BEGIN{};>.
Both the functions can import the functions that are specified.
Following codes are same.
load File::Spec::Functions, qw/splitpath/;
autoload File::Spec::Functions, qw/splitpath/;
=head1 FUNCTIONS
=over 4
=item load
Loads a specified module.
See L</Rules> for detailed loading rule.
=item autoload
Loads a specified module and imports the default functions.
Except importing the functions, 'autoload' is same as 'load'.
=item load_remote
Loads a specified module to the specified package.
use Module::Load 'load_remote';
my $pkg = 'Other::Package';
load_remote $pkg, 'Data::Dumper'; # load a module to 'Other::Package'
# but do not import 'Dumper' function
A module for loading must be quoted.
Except specifing the package and quoting module name,
'load_remote' is same as 'load'.
=item autoload_remote
Loads a specified module and imports the default functions to the specified package.
use Module::Load 'autoload_remote';
my $pkg = 'Other::Package';
autoload_remote $pkg, 'Data::Dumper'; # load a module to 'Other::Package'
# and imports 'Dumper' function
A module for loading must be quoted.
Except specifing the package and quoting module name,
'autoload_remote' is same as 'load_remote'.
=back
=head1 Rules
All functions have the following rules to decide what it thinks
you want:
=over 4
=item *
If the argument has any characters in it other than those matching
C<\w>, C<:> or C<'>, it must be a file
=item *
If the argument matches only C<[\w:']>, it must be a module
=item *
If the argument matches only C<\w>, it could either be a module or a
file. We will try to find C<file.pm> first in C<@INC> and if that
fails, we will try to find C<file> in @INC. If both fail, we die with
the respective error messages.
=back
=head1 IMPORTS THE FUNCTIONS
'load' and 'autoload' are imported by default, but 'load_remote' and
'autoload_remote' are not imported.
To use 'load_remote' or 'autoload_remote', specify at 'use'.
=over 4
=item "load","autoload","load_remote","autoload_remote"
Imports the selected functions.
# imports 'load' and 'autoload' (default)
use Module::Load;
# imports 'autoload' only
use Module::Load 'autoload';
# imports 'autoload' and 'autoload_remote', but don't import 'load';
use Module::Load qw/autoload autoload_remote/;
=item 'all'
Imports all the functions.
use Module::Load 'all'; # imports load, autoload, load_remote, autoload_remote
=item '','none',undef
Not import any functions (C<load> and C<autoload> are not imported).
use Module::Load '';
use Module::Load 'none';
use Module::Load undef;
=back
=head1 Caveats
Because of a bug in perl (#19213), at least in version 5.6.1, we have
to hardcode the path separator for a require on Win32 to be C</>, like
on Unix rather than the Win32 C<\>. Otherwise perl will not read its
own %INC accurately double load files if they are required again, or
in the worst case, core dump.
C<Module::Load> cannot do implicit imports, only explicit imports.
(in other words, you always have to specify explicitly what you wish
to import from a module, even if the functions are in that modules'
C<@EXPORT>)
=head1 SEE ALSO
L<Module::Runtime> provides functions for loading modules,
checking the validity of a module name,
converting a module name to partial C<.pm> path,
and related utility functions.
L<"require" in perlfunc|https://metacpan.org/pod/perlfunc#require>
and
L<"use" in perlfunc|https://metacpan.org/pod/perlfunc#use>.
L<Mojo::Loader> is a "class loader and plugin framework",
and is included in the
L<Mojolicious|https://metacpan.org/release/Mojolicious> distribution.
L<Module::Loader> is a module for finding and loading modules
in a given namespace, inspired by C<Mojo::Loader>.
=head1 ACKNOWLEDGEMENTS
Thanks to Jonas B. Nielsen for making explicit imports work.
=head1 BUG REPORTS
Please report bugs or other issues to E<lt>bug-module-load@rt.cpan.orgE<gt>.
=head1 AUTHOR
This module by Jos Boumans E<lt>kane@cpan.orgE<gt>.
=head1 COPYRIGHT
This library is free software; you may redistribute and/or modify it
under the same terms as Perl itself.
=cut

View file

@ -0,0 +1,624 @@
package Module::Load::Conditional;
use strict;
use Module::Load qw/load autoload_remote/;
use Params::Check qw[check];
use Locale::Maketext::Simple Style => 'gettext';
use Carp ();
use File::Spec ();
use FileHandle ();
use version;
use Module::Metadata ();
use constant ON_VMS => $^O eq 'VMS';
use constant ON_WIN32 => $^O eq 'MSWin32' ? 1 : 0;
use constant QUOTE => do { ON_WIN32 ? q["] : q['] };
BEGIN {
use vars qw[ $VERSION @ISA $VERBOSE $CACHE @EXPORT_OK $DEPRECATED
$FIND_VERSION $ERROR $CHECK_INC_HASH $FORCE_SAFE_INC ];
use Exporter;
@ISA = qw[Exporter];
$VERSION = '0.74';
$VERBOSE = 0;
$DEPRECATED = 0;
$FIND_VERSION = 1;
$CHECK_INC_HASH = 0;
$FORCE_SAFE_INC = 0;
@EXPORT_OK = qw[check_install can_load requires];
}
=pod
=head1 NAME
Module::Load::Conditional - Looking up module information / loading at runtime
=head1 SYNOPSIS
use Module::Load::Conditional qw[can_load check_install requires];
my $use_list = {
CPANPLUS => 0.05,
LWP => 5.60,
'Test::More' => undef,
};
print can_load( modules => $use_list )
? 'all modules loaded successfully'
: 'failed to load required modules';
my $rv = check_install( module => 'LWP', version => 5.60 )
or print 'LWP is not installed!';
print 'LWP up to date' if $rv->{uptodate};
print "LWP version is $rv->{version}\n";
print "LWP is installed as file $rv->{file}\n";
print "LWP requires the following modules to be installed:\n";
print join "\n", requires('LWP');
### allow M::L::C to peek in your %INC rather than just
### scanning @INC
$Module::Load::Conditional::CHECK_INC_HASH = 1;
### reset the 'can_load' cache
undef $Module::Load::Conditional::CACHE;
### don't have Module::Load::Conditional issue warnings --
### default is '1'
$Module::Load::Conditional::VERBOSE = 0;
### The last error that happened during a call to 'can_load'
my $err = $Module::Load::Conditional::ERROR;
=head1 DESCRIPTION
Module::Load::Conditional provides simple ways to query and possibly load any of
the modules you have installed on your system during runtime.
It is able to load multiple modules at once or none at all if one of
them was not able to load. It also takes care of any error checking
and so forth.
=head1 Methods
=head2 $href = check_install( module => NAME [, version => VERSION, verbose => BOOL ] );
C<check_install> allows you to verify if a certain module is installed
or not. You may call it with the following arguments:
=over 4
=item module
The name of the module you wish to verify -- this is a required key
=item version
The version this module needs to be -- this is optional
=item verbose
Whether or not to be verbose about what it is doing -- it will default
to $Module::Load::Conditional::VERBOSE
=back
It will return undef if it was not able to find where the module was
installed, or a hash reference with the following keys if it was able
to find the file:
=over 4
=item file
Full path to the file that contains the module
=item dir
Directory, or more exact the C<@INC> entry, where the module was
loaded from.
=item version
The version number of the installed module - this will be C<undef> if
the module had no (or unparsable) version number, or if the variable
C<$Module::Load::Conditional::FIND_VERSION> was set to true.
(See the C<GLOBAL VARIABLES> section below for details)
=item uptodate
A boolean value indicating whether or not the module was found to be
at least the version you specified. If you did not specify a version,
uptodate will always be true if the module was found.
If no parsable version was found in the module, uptodate will also be
true, since C<check_install> had no way to verify clearly.
See also C<$Module::Load::Conditional::DEPRECATED>, which affects
the outcome of this value.
=back
=cut
### this checks if a certain module is installed already ###
### if it returns true, the module in question is already installed
### or we found the file, but couldn't open it, OR there was no version
### to be found in the module
### it will return 0 if the version in the module is LOWER then the one
### we are looking for, or if we couldn't find the desired module to begin with
### if the installed version is higher or equal to the one we want, it will return
### a hashref with he module name and version in it.. so 'true' as well.
sub check_install {
my %hash = @_;
my $tmpl = {
version => { default => '0.0' },
module => { required => 1 },
verbose => { default => $VERBOSE },
};
my $args;
unless( $args = check( $tmpl, \%hash, $VERBOSE ) ) {
warn loc( q[A problem occurred checking arguments] ) if $VERBOSE;
return;
}
my $file = File::Spec->catfile( split /::/, $args->{module} ) . '.pm';
my $file_inc = File::Spec::Unix->catfile(
split /::/, $args->{module}
) . '.pm';
### where we store the return value ###
my $href = {
file => undef,
version => undef,
uptodate => undef,
};
my $filename;
### check the inc hash if we're allowed to
if( $CHECK_INC_HASH ) {
$filename = $href->{'file'} =
$INC{ $file_inc } if defined $INC{ $file_inc };
### find the version by inspecting the package
if( defined $filename && $FIND_VERSION ) {
no strict 'refs';
$href->{version} = ${ "$args->{module}"."::VERSION" };
}
}
### we didn't find the filename yet by looking in %INC,
### so scan the dirs
unless( $filename ) {
local @INC = @INC[0..$#INC-1] if $FORCE_SAFE_INC && $INC[-1] eq '.';
DIR: for my $dir ( @INC ) {
my $fh;
if ( ref $dir ) {
### @INC hook -- we invoke it and get the filehandle back
### this is actually documented behaviour as of 5.8 ;)
my $existed_in_inc = $INC{$file_inc};
if (UNIVERSAL::isa($dir, 'CODE')) {
($fh) = $dir->($dir, $file);
} elsif (UNIVERSAL::isa($dir, 'ARRAY')) {
($fh) = $dir->[0]->($dir, $file, @{$dir}{1..$#{$dir}})
} elsif (UNIVERSAL::can($dir, 'INC')) {
($fh) = $dir->INC($file);
}
if (!UNIVERSAL::isa($fh, 'GLOB')) {
warn loc(q[Cannot open file '%1': %2], $file, $!)
if $args->{verbose};
next;
}
$filename = $INC{$file_inc} || $file;
delete $INC{$file_inc} if not $existed_in_inc;
} else {
$filename = File::Spec->catfile($dir, $file);
next unless -e $filename;
$fh = FileHandle->new();
if (!$fh->open($filename)) {
warn loc(q[Cannot open file '%1': %2], $file, $!)
if $args->{verbose};
next;
}
}
### store the directory we found the file in
$href->{dir} = $dir;
### files need to be in unix format under vms,
### or they might be loaded twice
$href->{file} = ON_VMS
? VMS::Filespec::unixify( $filename )
: $filename;
### if we don't need the version, we're done
last DIR unless $FIND_VERSION;
### otherwise, the user wants us to find the version from files
{
local $SIG{__WARN__} = sub {};
my $ver = eval {
my $mod_info = Module::Metadata->new_from_handle( $fh, $filename );
$mod_info->version( $args->{module} );
};
if( defined $ver ) {
$href->{version} = $ver;
last DIR;
}
}
}
}
### if we couldn't find the file, return undef ###
return unless defined $href->{file};
### only complain if we're expected to find a version higher than 0.0 anyway
if( $FIND_VERSION and not defined $href->{version} ) {
{ ### don't warn about the 'not numeric' stuff ###
local $^W;
### if we got here, we didn't find the version
warn loc(q[Could not check version on '%1'], $args->{module} )
if $args->{verbose} and $args->{version} > 0;
}
$href->{uptodate} = 1;
} else {
### don't warn about the 'not numeric' stuff ###
local $^W;
### 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?
###
### Update from JPeacock: apparently qv() and version->new
### are different things, and we *must* use version->new
### here, or things like #30056 might start happening
### We have to wrap this in an eval as version-0.82 raises
### exceptions and not warnings now *sigh*
eval {
$href->{uptodate} =
version->new( $args->{version} ) <= version->new( $href->{version} )
? 1
: 0;
};
}
if ( $DEPRECATED and "$]" >= 5.011 ) {
local @INC = @INC[0..$#INC-1] if $FORCE_SAFE_INC && $INC[-1] eq '.';
require Module::CoreList;
require Config;
no warnings 'once';
$href->{uptodate} = 0 if
exists $Module::CoreList::version{ 0+$] }{ $args->{module} } and
Module::CoreList::is_deprecated( $args->{module} ) and
$Config::Config{privlibexp} eq $href->{dir}
and $Config::Config{privlibexp} ne $Config::Config{sitelibexp};
}
return $href;
}
=head2 $bool = can_load( modules => { NAME => VERSION [,NAME => VERSION] }, [verbose => BOOL, nocache => BOOL, autoload => BOOL] )
C<can_load> will take a list of modules, optionally with version
numbers 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) to
solve a problem in a program, and only wish to continue down a path
if all modules could be loaded, and not load them if they couldn't.
This function uses the C<load> function or the C<autoload_remote> function
from Module::Load under the hood.
C<can_load> takes the following arguments:
=over 4
=item modules
This is a hashref of module/version pairs. The version indicates the
minimum version to load. If no version is provided, any version is
assumed to be good enough.
=item verbose
This controls whether warnings should be printed if a module failed
to load.
The default is to use the value of $Module::Load::Conditional::VERBOSE.
=item nocache
C<can_load> keeps its results in a cache, so it will not load the
same module twice, nor will it attempt to load a module that has
already failed to load before. By default, C<can_load> will check its
cache, but you can override that by setting C<nocache> to true.
=item autoload
This controls whether imports the functions of a loaded modules to the caller package. The default is no importing any functions.
See the C<autoload> function and the C<autoload_remote> function from L<Module::Load> for details.
=cut
sub can_load {
my %hash = @_;
my $tmpl = {
modules => { default => {}, strict_type => 1 },
verbose => { default => $VERBOSE },
nocache => { default => 0 },
autoload => { 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?
###
### Update from JPeacock: apparently qv() and version->new
### are different things, and we *must* use version->new
### here, or things like #30056 might start happening
if ( !$args->{nocache}
&& defined $CACHE->{$mod}->{usable}
&& (version->new( $CACHE->{$mod}->{version}||0 )
>= version->new( $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} ) {
local @INC = @INC[0..$#INC-1] if $FORCE_SAFE_INC && $INC[-1] eq '.';
if ( $args->{autoload} ) {
my $who = (caller())[0];
eval { autoload_remote $who, $mod };
} else {
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 module
requires. This is particularly useful when you're intending to write
a 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, and
return undef if it can't.
Otherwise, it will return a list of modules and pragmas that would
have been loaded on the module's behalf.
Note: The list C<require> returns has originated from your current
perl and your current install.
=cut
sub requires {
my $who = shift;
unless( check_install( module => $who ) ) {
warn loc(q[You do not have module '%1' installed], $who) if $VERBOSE;
return undef;
}
local @INC = @INC[0..$#INC-1] if $FORCE_SAFE_INC && $INC[-1] eq '.';
my $lib = join " ", map { qq["-I$_"] } @INC;
my $oneliner = 'print(join(qq[\n],map{qq[BONG=$_]}keys(%INC)),qq[\n])';
my $cmd = join '', qq["$^X" $lib -M$who -e], QUOTE, $oneliner, QUOTE;
return sort
grep { !/^$who$/ }
map { chomp; s|/|::|g; $_ }
grep { s|\.pm$||i; }
map { s!^BONG\=!!; $_ }
grep { m!^BONG\=! }
`$cmd`;
}
1;
__END__
=head1 Global Variables
The behaviour of Module::Load::Conditional can be altered by changing the
following global variables:
=head2 $Module::Load::Conditional::VERBOSE
This controls whether Module::Load::Conditional will issue warnings and
explanations as to why certain things may have failed. If you set it
to 0, Module::Load::Conditional will not output any warnings.
The default is 0;
=head2 $Module::Load::Conditional::FIND_VERSION
This 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>. Understand
then that version comparisons are not possible, and Module::Load::Conditional
can 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_HASH
This controls whether C<Module::Load::Conditional> checks your
C<%INC> hash to see if a module is available. By default, only
C<@INC> is scanned to see if a module is physically on your
filesystem, or available via an C<@INC-hook>. Setting this variable
to C<true> will trust any entries in C<%INC> and return them for
you.
The default is 0;
=head2 $Module::Load::Conditional::FORCE_SAFE_INC
This controls whether C<Module::Load::Conditional> sanitises C<@INC>
by removing "C<.>". The current default setting is C<0>, but this
may change in a future release.
=head2 $Module::Load::Conditional::CACHE
This holds the cache of the C<can_load> function. If you explicitly
want to remove the current cache, you can set this variable to
C<undef>
=head2 $Module::Load::Conditional::ERROR
This holds a string of the last error that happened during a call to
C<can_load>. It is useful to inspect this when C<can_load> returns
C<undef>.
=head2 $Module::Load::Conditional::DEPRECATED
This controls whether C<Module::Load::Conditional> checks if
a dual-life core module has been deprecated. If this is set to
true C<check_install> will return false to C<uptodate>, if
a dual-life module is found to be loaded from C<$Config{privlibexp}>
The default is 0;
=head1 See Also
C<Module::Load>
=head1 BUG REPORTS
Please report bugs or other issues to E<lt>bug-module-load-conditional@rt.cpan.orgE<gt>.
=head1 AUTHOR
This module by Jos Boumans E<lt>kane@cpan.orgE<gt>.
=head1 COPYRIGHT
This library is free software; you may redistribute and/or modify it
under the same terms as Perl itself.
=cut

View file

@ -0,0 +1,142 @@
package Module::Loaded;
use strict;
use Carp qw[carp];
BEGIN { use base 'Exporter';
use vars qw[@EXPORT $VERSION];
$VERSION = '0.08';
@EXPORT = qw[mark_as_loaded mark_as_unloaded is_loaded];
}
=head1 NAME
Module::Loaded - mark modules as loaded or unloaded
=head1 SYNOPSIS
use Module::Loaded;
$bool = mark_as_loaded('Foo'); # Foo.pm is now marked as loaded
$loc = is_loaded('Foo'); # location of Foo.pm set to the
# loaders location
eval "require 'Foo'"; # is now a no-op
$bool = mark_as_unloaded('Foo'); # Foo.pm no longer marked as loaded
eval "require 'Foo'"; # Will try to find Foo.pm in @INC
=head1 DESCRIPTION
When testing applications, often you find yourself needing to provide
functionality in your test environment that would usually be provided
by external modules. Rather than munging the C<%INC> by hand to mark
these external modules as loaded, so they are not attempted to be loaded
by perl, this module offers you a very simple way to mark modules as
loaded and/or unloaded.
=head1 FUNCTIONS
=head2 $bool = mark_as_loaded( PACKAGE );
Marks the package as loaded to perl. C<PACKAGE> can be a bareword or
string.
If the module is already loaded, C<mark_as_loaded> will carp about
this and tell you from where the C<PACKAGE> has been loaded already.
=cut
sub mark_as_loaded (*) {
my $pm = shift;
my $file = __PACKAGE__->_pm_to_file( $pm ) or return;
my $who = [caller]->[1];
my $where = is_loaded( $pm );
if ( defined $where ) {
carp "'$pm' already marked as loaded ('$where')";
} else {
$INC{$file} = $who;
}
return 1;
}
=head2 $bool = mark_as_unloaded( PACKAGE );
Marks the package as unloaded to perl, which is the exact opposite
of C<mark_as_loaded>. C<PACKAGE> can be a bareword or string.
If the module is already unloaded, C<mark_as_unloaded> will carp about
this and tell you the C<PACKAGE> has been unloaded already.
=cut
sub mark_as_unloaded (*) {
my $pm = shift;
my $file = __PACKAGE__->_pm_to_file( $pm ) or return;
unless( defined is_loaded( $pm ) ) {
carp "'$pm' already marked as unloaded";
} else {
delete $INC{ $file };
}
return 1;
}
=head2 $loc = is_loaded( PACKAGE );
C<is_loaded> tells you if C<PACKAGE> has been marked as loaded yet.
C<PACKAGE> can be a bareword or string.
It returns falls if C<PACKAGE> has not been loaded yet and the location
from where it is said to be loaded on success.
=cut
sub is_loaded (*) {
my $pm = shift;
my $file = __PACKAGE__->_pm_to_file( $pm ) or return;
return $INC{$file} if exists $INC{$file};
return;
}
sub _pm_to_file {
my $pkg = shift;
my $pm = shift or return;
my $file = join '/', split '::', $pm;
$file .= '.pm';
return $file;
}
=head1 BUG REPORTS
Please report bugs or other issues to E<lt>bug-module-loaded@rt.cpan.org<gt>.
=head1 AUTHOR
This module by Jos Boumans E<lt>kane@cpan.orgE<gt>.
=head1 COPYRIGHT
This library is free software; you may redistribute and/or modify it
under the same terms as Perl itself.
=cut
# Local variables:
# c-indentation-style: bsd
# c-basic-offset: 4
# indent-tabs-mode: nil
# End:
# vim: expandtab shiftwidth=4:
1;

File diff suppressed because it is too large Load diff