NAME
Module::UseFrom - Safe compile-time module loading from a variable
SYNOPSIS
use Module::UseFrom;
BEGIN {
our $var = 'Scalar' . '::' . 'Util';
}
use_from $var; # use Scalar::Util;
DESCRIPTION
Many people have written about Perl's problem of loading a module from a string. This module attempts to solve that problem in a safe and useful manner. Using the magic of Devel::Declare, the contents of a variable are translated into a bareword use
statement. Since Module::UseFrom
leans on this, the safest of the loading mechanisms, it should be every bit as safe.
Said a different way, the final result is a bareword use
statement, so even if the translations/hueristics used internally fail, the system is not exposed to the insecurities introduced when translating to require FILE
statments or wrapping in a string eval
.
Further, Module::UseFrom
can do some rudimentary checking before writing the use
statement. Most usefully, it can be told only to write the use
statement if the module is installed or even of a high enough version.
INSTALLATION
During installation, one may see warnings like Name "ExtUtils::Packlist::FY1" used only once: possible typo at ...
. This seems to be related to ExtUtils::Installed bug 50315. A patch has been submitted which should fix it. It is not a concern and does not affect any functionality whatsoever, just ignore it.
FUNCTION use_from
The function use_from
is the basic interface provided by Module::UseFrom
. It takes one argument, a variable, called WITHOUT round braces (see "SYNOPSIS"). The variable can be a scalar, array, or hash (not a list), the usage for each of these forms will be discussed later.
Some things to keep in mind:
The variable must come after
use_from
on the same line. This is a limitation stemming from Devel::Declare.The
use_from
injects ause
statement taking the place of the original call and variable. This means if anything exists on the same line, it is left intact (even the ending semicolon is not affected). This behavior is by design, allowing the user to pass version or import directives as ifuse_from $var
was simply a regularuse Bareword::Module
statement. For an alternative method of passing these directives see "HASH".
THE VARIABLE
Since Devel::Declare and use
both do their work at compile-time, your variable must be populated by then. BEGIN
blocks allow you to do this. Module::UseFrom
examines the given variable's contents, therefore the variable must be accessible from outside the package, this usually will mean using an our
variable. See the "SYNOPSIS" to see an example.
Module::UseFrom
will inspect the variable for information. This variable must be a simple Scalar, Array or (not quite as simple) Hash. Each usage will have slightly different effects.
SCALAR
The most basic usage is as follows
use Module::UseFrom;
BEGIN {
our $var = 'Scalar::Util';
}
use_from $var; # use Scalar::Util;
If you need to import or specify a version, just do it as you would have if this was a simple use
call where your variable replaces the module.
use Module::UseFrom;
BEGIN {
our $var = 'Scalar::Util';
}
use_from $var qw/dualvar/; # use Scalar::Util qw/dualvar/;
ARRAY
Rather than making repeated calls to use_from
(which is fine), a shortcut is to pass an array which contains multiple module names. These will be translated to muliple use
directives. The last one will not be terminated, so conceivably this mechanism can be used to pass additional arguments to the last module in the array. Rather than do this though, check out the more useful "HASH" type of calling when doing this.
use Module::UseFrom;
BEGIN {
our @var = qw'Scalar::Util List::Util';
}
use_from @var; # use Scalar::Util; use List::Util;
HASH
When called with a hash, the interface suddenly becomes a little more flexible. The keys are always the module to be used.
SIMPLE SCALAR
If the value is a simple scalar, which are interpreted as version directives. Use 0
to allow any version (and in fact not even write the version to the use
directive).
ARRAY REFERENCE
If the value is an array reference, which is interpreted as import directives. These must (for now) be simple strings, not object/references etc. These are written out as a single quoted list, i.e. ('item0', 'item1', ..., 'itemN')
.
HASH REFERENCE
If the value is a hash reference. This may contain the keys version
and import
which behave just like the two previous calling types (taking a scalar and an array reference repectively). In fact this calling style is used internally by the "SIMPLE SCALAR" and "ARRAY REFERENCE" types anyway.
Further it also can take the key check_installed
with a true value. When this is done the module will only be written to a use
statement if Module::CoreList or ExtUtils::Install
can find them. This prevents the embarrassing not found in @INC
errors when the module isn't installed; of course this means that it will not be loaded at all, so only use this functionality when it is deserved. To check if the module was loaded, Module::UseFrom
adds the key found_version
which contains the imformation that the aforementioned modules obtained in checking for the module. If the module isn't loaded then found_module
will be zero. N.B. if you intend to inspect your variable after wards you might need to declare it before the BEGIN
block.
Finally, if a version
and check_installed
are both specified and the module is installed but of insufficient version, the use
directive will not be writte, just as in the check_installed
scenario.
use Module::UseFrom;
our %var;
BEGIN {
our %var = (
'Carp' => {
check_installed => 1,
version => 0.01,
'import' => [ qw/carp croak/ ]
},
);
}
use_from %var; # use Carp 0.01 ('carp', 'croak');
print $var{Carp}{found_version}; # prints version of Carp found by Module::CoreList
OPTIONS
Module::UseFrom
has a few options, controlled by package variables. These also must be inside a BEGIN
block, so that they are set in time to be useful.
$Module::UseFrom::verbose
When set to a true value, some additional information is printed to STDERR
(via warn
). In the special case that it is set to a reference to a scalar, the information is kept in that scalar rather than printing.
$Module::UseFrom::check_installed
When set to a true value, all modules inspected by use_from
are treated as though the check_installed
option from "HASH REFERENCE" was enabled, even if using the "SCALAR" and "ARRAY" forms.
SOURCE REPOSITORY
http://github.com/jberger/Module-UseFrom
AUTHOR
Joel Berger, <joel.a.berger@gmail.com>
COPYRIGHT AND LICENSE
Copyright (C) 2012 by Joel Berger
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.