Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Safe compile-time module loading from a variable

branch: master

Fetching latest commit…

Octocat-spinner-32-eaf2f5

Cannot retrieve the latest commit at this time

Octocat-spinner-32 lib
Octocat-spinner-32 t
Octocat-spinner-32 README.pod
Octocat-spinner-32 dist.ini
README.pod

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. Even if the translations/hueristics used internally should 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.

FUNCTIONS

Module::UseFrom exports use_from by default. Any of the following functions may be requested in the usual manner. The tag :all will request them all.

use_from

The function use_from is the basic interface provided by Module::UseFrom. It takes one scalar variable, called WITHOUT round braces. Module::UseFrom will inspect the variable for information. This variable must be a simple scalar (i.e. not a reference).

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/;

Some things to keep in mind:

  • The variable must follow use_from on the same line. This is a limitation stemming from Devel::Declare.
  • The use_from injects a use statement taking the place of the original call and variable. This means if anything else exists on the same line or if the statement continues to further lines, 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 if use_from $var was simply a regular use Bareword::Module statement.
  • 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.

use_if_available

use_if_available is called in the same way as use_from, however unlike that function, it checks to see if the module is available before injecting the use statement. Further if it detects a version declaration following the variable, it will only inject the use statement if the version restriction can be satisfied.

To check if the module was useed, you may examine your original value in numeric context, which will contain the version as determined by Module::CoreList or ExtUtils::Installed (for core or non-core modules respectively) or 0 if the module is not found.

 use Module::UseFrom 'use_if_available';
 our $var; # declared outside BEGIN for later inspection
 BEGIN {
   $var = 'Scalar::Util';
 }
 use_if_available $var 999 qw/reftype/; # Scalar::Util is not loaded

 die "I guess I really wanted $var" unless $var > 0;

Unlike use_from, which naively injects the proper use statement in-place, use_if_available is smarter and will inject a list-prototyped no-op call in front of any import list should the module not be available or not of the proper version. If you don't know what this means, don't fret, just know that use_if_available behaves as you think it should.

VERBOSE OUTPUT

Verbose output is controlled by the package variable $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. Activating this feature will most likely need to be performed inside a BEGIN block, so that it is set in time to be useful.

INSTALLATION ISSUES

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 accepted which should fix it. It is not a concern and does not affect any functionality whatsoever, just ignore it.

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.

Something went wrong with that request. Please try again.