Created
April 4, 2021 10:49
-
-
Save neilb/708dfe8f43363a89e85fab07515d81e5 to your computer and use it in GitHub Desktop.
A module for optionally loading other modules and importing functions from them
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package optionally; | |
# optionally load a module and import functions | |
# | |
# use optionally 'Some::Module', '1.23', qw/ fnA fnB /; | |
# | |
use 5.010; | |
use strict; | |
use warnings; | |
use Carp qw/ croak /; | |
use Module::Runtime qw/ require_module /; | |
my %have_loaded; | |
sub import | |
{ | |
my $exporting_package = shift; | |
my $importing_package = caller; | |
croak "optionally: no package specified" unless @_ > 0; | |
my $optional_package = shift; | |
# If we can't even load the specified package, then silently do no more | |
return unless require_module($optional_package); | |
# Was a minimum version specified? | |
if (@_ > 0 && _looks_like_version_number($_[0])) { | |
my $required_version = shift; | |
eval "${optional_package}->VERSION($required_version)"; | |
if ($@) { | |
# we've got the optional module available | |
# but it's an old version, which we're not interested in | |
# so we bail and pretend it was never loaded | |
delete $INC{ $optional_package }; | |
# TODO: Possibly do more of what Class::Unload does as well? | |
return; | |
} | |
} | |
$have_loaded{ $optional_package } = 1; | |
return unless @_ > 0; | |
no strict 'refs'; | |
foreach my $subname (@_) { | |
*{"${importing_package}::$subname"} = *{"${optional_package}::$subname"}{CODE} | |
// croak "No $subname() available for import from $optional_package"; | |
} | |
} | |
# TODO: is there an official regexp for valid package version numbers? | |
sub _looks_like_version_number | |
{ | |
my $string = shift; | |
return $string =~ m!^[0-9\.]+$!; | |
} | |
sub loaded | |
{ | |
my $module_name = shift; | |
return $have_loaded{ $module_name }; | |
} | |
1; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment