The Perl and Raku Conference 2025: Greenville, South Carolina - June 27-29 Learn more

use strict;
our $VERSION = '0.03';
use Carp;
sub import {
my($class, @args) = @_;
my $is_autoload = (@args && $args[0] eq '-autoload') ? shift @args : undef;
my $caller = caller(0);
my $target = $is_autoload ? $caller : join '::', __PACKAGE__, '_load_tmp_', $caller;
my @errors;
my $i = 0;
my $len = scalar(@args);
my @imports;
LOOP:
while ($len > $i) {
# prepare args
my $name = $args[$i++];
my $val = $args[$i++];
my $import;
my $version;
if ($len > $i-1 && $val =~ /^[0-9]+(?:\.[0-9]+)*$/) {
# simple version
$version = $val;
} elsif (ref($val) eq 'ARRAY') {
# detail version
$version = $val;
} elsif (ref($val) eq 'HASH') {
# autoload
unless ($is_autoload) {
push @errors, "$name is unloaded because -autoload an option is lacking.";
next LOOP;
}
$import = $val->{import};
$version = $val->{version};
} elsif (ref($val)) {
confess 'args format error';
} else {
$i--;
}
# load module
eval qq{package $target; require $name}; ## no critic.
if ($is_autoload) {
push @imports, [ $name, $import ];
}
if (my $e = $@) {
push @errors, "Can't load $name\n$e";
next LOOP;
}
# version check
if ($version) {
my $mod_ver = do {
no strict 'refs';
${"$name\::VERSION"};
};
if (defined $mod_ver) {
if (ref($version) eq 'ARRAY') {
# detail version
if (@{ $version } % 2 == 0) {
my @terms;
my $is_error;
while (my($k, $v) = splice @{ $version }, 0, 2) {
push @terms, "$k $v";
if ($k eq '>') {
$is_error = 1 unless $mod_ver > $v;
} elsif ($k eq '>=') {
$is_error = 1 unless $mod_ver >= $v;
} elsif ($k eq '<') {
$is_error = 1 unless $mod_ver < $v;
} elsif ($k eq '<=') {
$is_error = 1 unless $mod_ver <= $v;
} elsif ($k eq '!=') {
$is_error = 1 unless $mod_ver != $v;
} else {
push @errors, "$name version check syntax error";
next LOOP;
}
}
if ($is_error) {
push @errors, "$name version @{[ join ' AND ', @terms ]} required--this is only version $mod_ver";
next LOOP;
}
} else {
push @errors, "$name version check syntax error";
next LOOP;
}
} elsif ($mod_ver < $version) {
push @errors, "$name version $version required--this is only version $mod_ver";
next LOOP;
}
} else {
push @errors, "$name does not define \$$name\::VERSION--version check failed";
next LOOP;
}
}
}
# show the errors
if (@errors) {
confess join "\n", @errors;
}
# run import method
for my $obj (@imports) {
if (defined $obj->[1]) {
if (@{ $obj->[1] }) {
eval qq{package $target;\$obj->[0]->import(\@{ \$obj->[1] })}; ## no critic.
} else {
# same the "use Module ();", it case is do not call import method
}
} else {
eval qq{package $target;\$obj->[0]->import}; ## no critic.
}
}
}
1;
__END__
=head1 NAME
Module::Requires - Checks to see if the module can be loaded
=head1 SYNOPSIS
more simply
use Module::Requires 'Class::Trigger', 'Class::Accessor';
use Class::Trigger;
use Class::Accessor;
with version Checks
use Module::Requires
'Class::Trigger' => 0.13,
'Class::Accessor';
use Class::Trigger;
use Class::Accessor;
detailed check of version
# It is more than 0.10 and is except 0.12.
use Module::Requires
'Class::Trigger' => [ '>' => 0.10, '!=', 0.12 ],
'Class::Accessor';
use Class::Trigger;
use Class::Accessor;
with autoloader
use Module::Requires -autoload,
'Class::Trigger', 'Class::Accessor';
with autoloader and import params
use Module::Requires -autoload,
'Class::Trigger' => { import => [qw/ foo bar baz /] },
'Class::Accessor';
with autoloader and import params and version check
use Module::Requires -autoload,
'Class::Trigger' => {
import => [qw/ foo bar baz /],
version => [ '>' => 0.10, '!=', 0.12 ],
},
'Class::Accessor';
=head1 DESCRIPTION
Module::Requires is Checks to see if the module can be loaded.
required modules warns of not installed if Inside of Makefile.PL With feature When specifying require module.
When writing modules, such as plugin, required modules which runs short is displayed on a user.
=head1 AUTHOR
Kazuhiro Osawa E<lt>yappo <at> shibuya <döt> plE<gt>
=head1 THANKS TO
nekokak, lestrrat
=head1 SEE ALSO
L<Test::Requires>, idea by L<DBIx::Class::Storage::DBI::Replicated>
=head1 LICENSE
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
=cut