Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Dear wise monks, I was trying to get "use" to check the version number of a patched module from CPAN, and I discovered that it seems to test only numeric values (1.3, etc.) and not a typical three-part value of VERSION. In this case, version 1.2.5 won't work and 1.2.6 will. Do you know a way to get version checking to behave right? I have the following work-around, but it's a little ugly.
BEGIN { # Note: doing version check by hand because the following doesn't s +eem to work. # use Tk::WorldCanvas 1.2.6; require Tk::WorldCanvas; $Tk::WorldCanvas::VERSION ge "1.2.6" or croak "Need Tk::WorldCanvas + 1.2.6 or higher"; }

Replies are listed 'Best First'.
Re: Module version checking flaw?
by dada (Chaplain) on Nov 07, 2002 at 16:48 UTC
    from the most authoritative source, section 2, paragraph 9, comma 1:
    To be fully compatible with the Exporter and MakeMaker modules you should store your module's version number in a non-my package variable called $VERSION. This should be a valid floating point number with at least two digits after the decimal (ie hundredths, e.g, $VERSION = "0.01"). See for details.

    Don't use a "1.3.2" style version directly. If you use RCS or a similar system which supports multilevel versions/branches you can use this (but put it all on one line for MakeMaker VERSION_FROM):

    $VERSION = do { my @r=(q$Revision: 3.112 $=~/\d+/g); sprintf "%d."."%03d"x$#r,@r };

    so I presume the author of Tk::WorldCanvas is to blame :-)


    King of Laziness, Wizard of Impatience, Lord of Hubris

(tye)Re: Module version checking flaw?
by tye (Sage) on Nov 07, 2002 at 18:28 UTC

    In case you also run into more complex version numbers like "v1.3a.4beta", you can get good results with:

    sub cmpVersions { my( $x, $y )= @_; for my $v ( $x, $y ) { $v =~ s/(\d+)/ pack "N", $1 /ge; } return $x cmp $y; }

            - tye
Re: Module version checking flaw?
by mirod (Canon) on Nov 07, 2002 at 17:22 UTC

    sprintf looks like a good solution.

    As I am not very familiar with pack I thought I'd try using it in this case, and here is what I got. Note that this code is tested but it is by no means authoritative, feel free to point my mistakes.

    #!/usr/bin/perl -w use strict; while( <DATA>) { chomp; my( $v1, $expected_res, $v2)= split /\s+/; my $pv1= pack( 'I3', split( /\./, $v1)); my $pv2= pack( 'I3', split( /\./, $v2)); my $res; if( $pv1 gt $pv2) { $res= '>'; } elsif( $pv1 lt $pv2) { $res= '<'; } elsif( $pv1 eq $pv2) { $res= '='; } if( $res eq $expected_res) { print "ok $v1 $res $v2\n"; } else { print "NOK $v1 $res $v2 should be $v +1 $expected_res $v2\n"; } } __DATA__ 1.2 < 1.3 1.3 > 1.2 1.2.1 > 1.2 1.2.1 < 1.3 1.2.1 < 1.2.2 1.2.2 > 1.2.1 1.2.10 > 1.2.2 1.2.2 < 1.2.10 1.2 = 1.2 1.2.1 = 1.2.1 1.2.10 = 1.2.10
Re: Module version checking flaw?
by John M. Dlugosz (Monsignor) on Nov 07, 2002 at 21:07 UTC
    Check out Everything you wanted to know about Module Version Numbers and Checking.

    The v1.2.6 (the v is implied in the use parameter) is totally different from the string "1.2.6".

    You can't pass a string to the VERSION check via the indirect object parameter to use.

    You might try passing it as a normal argument to the import function via the import list, instead.

    Perhaps the module implements checking one way but not the other; after all, they are incompatible in what you need to have in $VERSION.

    See also Ordered Comparison of Generalized Version Strings., which is similar to tye's code but taken to the limit.