How do I use a certain version (or higher) of a perl module in my perl script? - perl

I'm using Term::ANSIColor in my Perl script to do colorization of terminal output, and I am using the colorstrip function, which was only added in Term::ANSIColor version 2.01, according to the changelog. So, is there a way to make my script automatically die with an appropriate error message if it doesn't find at least that version of Term::ANSIcolor?

Just:
use Term::ANSIColor 2.01;
See perldoc -f use:
use Module VERSION LIST
If the VERSION argument is present between Module and LIST, then the use will call the VERSION method in class Module with the given version as an argument. The default VERSION method, inherited from the UNIVERSAL class, croaks if the given version is larger than the value of the variable $Module::VERSION .

Most modules define the package variable $VERSION.
use Term::ANSIColor;
die "Sorry, this program needs Term::ANSIColor >= v2.01!\n"
unless $Term::ANSIColor::VERSION >= 2.01;
This is also a good way to specify a maximum version of a module.
use Module::Foo;
die "You need an *older* version of Module::Foo that ",
"still has the &barbaz method defined"
if $Module::Foo::VERSION >= 0.47;

Simply specify the version you want to use:
use Some::Module 2.13;
If the version is not at least 2.13, the operation will fail.
You can experiment with the version that is available on the command line:
perl -MSome::Module=9999 -e 'exit 0'
This will usually die with the wrong version number shown in the error message (unless the module you're trying to use happens to have a 5 digit or longer version number, or unless the module is like strict and doesn't like being loaded via the command line with a version number or like URI (see the comments for details)).
$ perl -MFile::Find=999 -e 'exit 0'
File::Find version 999 required--this is only version 1.07 at
/usr/perl5/5.8.4/lib/Exporter/Heavy.pm line 121.
BEGIN failed--compilation aborted.
$ perl -e 'use File::Find 999; exit 0'
File::Find version 999 required--this is only version 1.07 at -e line 1.
BEGIN failed--compilation aborted at -e line 1.
$
Run on a machine I don't normally use, hence the antiquated version of Perl.

Related

Perl: par packer executable with Unicode::GCString, Can't locate object method "new"

I'm using the PAR::Packer module to create a Windows executable of a Perl script that uses the Unicode::GCString module.
A stripped down version of the script is as follows:
mwe.pl
#!/usr/bin/env perl
use strict;
use warnings;
use Unicode::GCString;
my $gcs = Unicode::GCString->new("hello world");
print $gcs->columns();
exit(0);
When I run
perl mwe.pl
the output gives the 'width' of the string:
11
which is as expected.
I create mwe.exe using the command
pp -o mwe.exe mwe.pl
and when I run
mwe.exe
I receive the error
Can't locate object method "new" via package "Unicode::GCString" at
script/mwe.pl line 6
Having reviewed AppData\Local\Temp\par-xxxxxx\cache-xxxxx\inc\lib, I believe that Unicode::GCString is present, as is Unicode::LineBreak.
Does anyone have any ideas on how to fix this?
A solution can be to use this version of "pp" I call it "ppp.pl"
$ENV{PAR_VERBATIM}=1;
system 'pp', #ARGV;
Details at https://metacpan.org/pod/distribution/PAR/lib/PAR/Environment.pod#PAR_VERBATIM
The cause is related to this bug Bug #38271 for PAR-Packer: PodStrip does not strip "=encoding utf8" which cause the executable generated by pp failed to exec
Also the boilerplate inside Unicode::GCString

Perl PP doesn't include Switch module

I created a perl script that includes the Switch module.
hello_world.pl
use strict;
use warnings;
use Switch;
use Data::Dumper;
my $var = "Hello World\n";
print Dumper($var);
if I launch perl hello_world.pl everything works fine. But if I pack my script with pp hello_world.pl and than launch ./a.out it gives me back this error:
Can't locate Switch.pm in #INC (you may need to install the Switch module) (#INC contains: CODE(0x7fb2631e6a88) /var/folders/rb/2b5sbs355n57svwzjjh7cb9c0000gn/T/par-6967676c6f62616c33/cache-710e967842eb844ab8d6fe5f46968c1b6f49e019/inc/lib /var/folders/rb/2b5sbs355n57svwzjjh7cb9c0000gn/T/par-6967676c6f62616c33/cache-710e967842eb844ab8d6fe5f46968c1b6f49e019/inc CODE(0x7fb262988de0) CODE(0x7fb262989930)) at script/hello_world.pl line 3.
BEGIN failed--compilation aborted at script/hello_world.pl line 3
$ corelist Switch
Data for 2016-05-09
Switch was first released with perl v5.7.3, deprecated (will be CPAN-only) in v5.11.0 and removed from v5.13.1
Switch was never a good idea. It's a source filter which means it's a clever party trick but shouldn't be used in production code. For that reason it has removed from Perl several versions ago.
I suspect that you are running your packaged program on a more recent version of Perl than the unpackaged version - one that no longer includes Switch.
You can install Switch on your target system or you can work out how to get pp to include the module in the package. But the best solution is to rewrite the code to stop using Switch.
You can try to force the modules to be included, with -M option:
pp -M Switch -M YAML ...

Why does HTTP::Message::decodable complain about "Can't use an undefined value as a HASH reference"?

I'm getting a Can't use an undefined value as a HASH reference error trying to call HTTP::Message::decodable() using Perl 5.10 / libwww installed on Debian Lenny OS using the aptitude package manager. I'm really stuck so would appreciate some help please.
Here's the error:
Can't use an undefined value as a HASH reference at (eval 2) line 1.
at test.pl line 4
main::__ANON__('Can\'t use an undefined value as a HASH reference at
enter code here`(eval 2)...') called at (eval 2) line 1
HTTP::Message::__ANON__() called at test.pl line 6
Here's the code:
use strict;
use HTTP::Request::Common;
use Carp;
$SIG{ __DIE__ } = sub { Carp::confess( #_ ) };
print HTTP::Message::decodable();
Looking at the changelog, it looks like HTTP::Message::decodable() was added in version 5.814. Are you sure you are reading the right documentation for your version?
Try:
perl -MHTTP::Message -e 'warn $HTTP::Message::VERSION'
.. it should return 5.814 or more...
Gavin was right - I had an old version of libwww-perl installed. I was relying on using the latest version available on Debian Lenny (assuming this was fairly up to date). Turns out the latest version available is 5.813 but I need 5.814 or more to use this function. As there's no packaged version available via aptitude I installed the latest using CPAN instead:
$ perl -MCPAN -e shell
cpan[1]> upgrade HTTP::Message
All done!

How do I get the Perl's DateTime::Format::DateManip version number from the command line?

I'm using this from the command line:
perl -MDateTime::Format::DateManip -le 'print $Some::Module::VERSION'
but only return a blank line, any thoughts?
It is pseudo-code, Some isn't set so it is just printing out undef with the -l flag, like perl -le'print undef;
For evidence turn on warnings with -w
$ perl -MDateTime::Format::DateManip -wle 'print $Some::Module::VERSION'
Use of uninitialized value $Some::Module::VERSION in print at -e line 1.
Substitute Some::Module with the module you want the version of.
Also, just for fun ;)
Perl Shorthands for testing version numbers
These are quick ways to get version numbers by utilizing the use <module> <version> syntax and perl's vocal rejection of versions that aren't new enough.
These are all equivalent of creating a perl script with use DateTime 9999;
$ perl -MDateTime\ 9999
DateTime version 9999 required--this is only version 0.51.
BEGIN failed--compilation aborted.
However, this fashion isn't cross-platform, because you're simply telling bash to escape a space. This doesn't work in windows cmd, for that you'll have to
$ perl -M"DateTime 9999"
DateTime version 9999 required--this is only version 0.51.
BEGIN failed--compilation aborted.
Here, you just put it in quotes - that tells cmd to send it all as an argument to perl and it gets the same job done.
If you find yourself doing this frequently, you can download and install pmvers from CPAN. The script will save you from typing a potentially lengthy module name twice:
pmvers DateTime::Format::DateManip

How can I find the version of an installed Perl module?

How do you find the version of an installed Perl module?
This is in an answer down at the bottom, but I figure it important enough to live up here. With these suggestions, I create a function in my .bashrc
function perlmodver {
perl -M$1 -e 'print "Version " . $ARGV[0]->VERSION . " of " . $ARGV[0] . \
" is installed.\n"' $1
}
Most modules (especially ones from The CPAN) have a $VERSION variable:
perl -MSome::Module -le 'print $Some::Module::VERSION'
Why are you trying to get the version of the module? Do you need this from within a program, do you just need the number to pass to another operation, or are you just trying to find out what you have?
I have this built into the cpan (which comes with perl) with the -D switch so you can see the version that you have installed and the current version on CPAN:
$ cpan -D Text::CSV_XS
Text::CSV_XS
-------------------------------------------------------------------------
Fast 8bit clean version of Text::CSV
H/HM/HMBRAND/Text-CSV_XS-0.54.tgz
/usr/local/lib/perl5/site_perl/5.8.8/darwin-2level/Text/CSV_XS.pm
Installed: 0.32
CPAN: 0.54 Not up to date
H.Merijn Brand (HMBRAND)
h.m.brand#xs4all.nl
If you want to see all of the out-of-date modules, use the -O (capital O) switch:
$ cpan -O
Module Name Local CPAN
-------------------------------------------------------------------------
Apache::DB 0.1300 0.1400
Apache::SOAP 0.0000 0.7100
Apache::Session 1.8300 1.8700
Apache::SizeLimit 0.0300 0.9100
Apache::XMLRPC::Lite 0.0000 0.7100
... and so on
If you want to see this for all modules you have installed, try the -a switch to create an autobundle.
VERSION is a UNIVERSAL method of all Perl classes. You can use it to get the module version (if it has been set which it usually has).
Here is a one liner where you only have to add the module name once:
perl -le 'eval "require $ARGV[0]" and print $ARGV[0]->VERSION' Some::Module
There is a less-typing trick, that works provided your module doesn't have something insane like a Unix timestamp as a version number.
perl -MFoo::Bar\ 9999
This works because what it translates to is
use Foo::Bar 9999;
i.e. a version of Foo::Bar that's at least version 9999 or newer.
And what you get is
Foo::Bar version 9999 required--this is only version 1.1.
BEGIN failed--compilation aborted.
(Neat trick I learned from Matt Trout.)
If you are lucky, the module will have a package variable named $VERSION:
$ perl -MCPAN -e 'print "$CPAN::VERSION\n"'
1.9205
This is needed for modules to be distributed on CPAN, but internally developed modules might follow a different convention or none at all.
Thanks for the answers! I've created a function in my .bashrc to easily find the version of a Perl module:
function perlmodver {
perl -M$1 -e 'print $ARGV[0]->VERSION . "\n"' $1
}
Easiest to remember and most robust version for me:
perl -e 'use Search::Elasticsearch; print $Search::Elasticsearch::VERSION;'
Check out the pmtools scripts on CPAN. If you're using a Debian(-based) distro, there's also a handy pmtools package. This includes a script "pmvers" that tells you a module's version. It's quite handy.
It does something similar to the various one-liners folks posted, but it's a bit smarter about error handling, and can give you the version of more than one module at once.
I wrote a small script to report that: perlver.
This is a simple little tool that
tells you what version of a module you
have installed, and where the .pm file
is located. It also ensures the module
can be loaded successfully. It
automatically converts ‘-’, ‘/’, or
‘\’ to ‘::’, so you can use a pathname
or distribution name instead of the
canonical module name.
It assumes that the module defines a $VERSION. If the module doesn't define a $VERSION, it will still tell you where the .pm file is, so you can examine it manually. You can also check several modules at once:
$ perlver CPAN DBD-Pg Getopt::Long
CPAN 1.7602 is
/usr/lib/perl5/5.8.8/CPAN.pm
DBD::Pg 1.49 is
/usr/lib/perl5/vendor_perl/5.8.8/i686-linux/DBD/Pg.pm
Getopt::Long 2.36 is
/usr/lib/perl5/vendor_perl/5.8.8/Getopt/Long.pm
In addition, for modules that use Exporter.pm, you can get this information with this trick:
perl -MSome::Module=99999 -ex
Some::Module version 99999 required--this is only version 1.9205 at ...
For modules that don't use Exporter.pm, a slightly longer trick reports the same information:
perl -e'use Some::Module 99999'
Some::Module version 99999 required--this is only version 1.9205 at ...
We have the system perl (/usr/bin/perl) in Solaris 10, and above solutions are useless. Some of them report "module.pm is not installed", some of them have no output.
Here is the code which is helpful, which can list all modules and their version.
#!/usr/bin/perl
use strict;
use ExtUtils::Installed;
my #modules;
my $installed = ExtUtils::Installed->new();
if (scalar(#ARGV) > 0) {
#modules = #ARGV;
} else {
#modules = $installed->modules();
}
print "Module\tVersion\n";
foreach (#modules) {
print $_ . "\t" . $installed->version($_) . "\n";
}
You can also take a look at App::module::version
$ module-version
The version of App::module::version in /home/yourself/perl5/lib/perl5 is 1.004