David H. Adler wrote:


Tests pass. One "not numeric" warning:

t/00compile.........ok 1/6Argument "2.57_06" isn't numeric in subroutine
entry at t/lib/Test/More.pm line 670


This is the same warning I reported in an earlier message: http://groups.google.com/group/perl.qa/msg/fee69dde25cf42ec

Given the wise counsel of a former Phalanx strategos ("every warning your test suite throws is a bug which must be tracked down"), I spent several hours looking at this this morning. To cut to the chase, it will go away once v2.58 is uploaded to CPAN. If my analysis is correct, it only occurs when a module author uses a version number containing an underscore and when that is assigned as a *string* rather than a number to the module's $VERSION.

More detailed explanation follows.

The test which is throwing the warning is the last test in t/00compile.t:

    BEGIN { use_ok 'Test::Harness', 1.1601 }

Andy's test suite, apparently for reasons of backwards compatibility, is testing against v0.42 of Test::More, which is included beneath the t/lib/ directory. In v0.42, when use_ok is called with a version number as the second argument, Test::Harness::import is called. Since Test::Harness doesn't define an import method, it's really Exporter::import which is being called. Exporter::import, in this particular case, calls, in turn, Exporter::export, which calls Exporter::as_heavy, which calls Exporter::Heavy::heavy_export, which, deep in its guts, calls its VERSION method ...

    $pkg->VERSION($sym);

... which is really UNIVERSAL::VERSION which, if supplied with an argument, assumes that the argument is a number to be compared with the minimum version number needed. But if, way back at the top of the chain, the module author says,

    $VERSION = '2.57_06';

that 2.57_06 does not numerify, so the "non-numeric argument" warning gets thrown.

Got that?  (Take a deep breath.)

I experimented with several other ways of assigning to $VERSION. Each of the three following ways ...

    $VERSION = '2.5706';

    $VERSION = 2.57_06;

    $VERSION = 2.5706;

... avoids the non-numeric warning. The first case numerifies correctly; the latter two already qualify as numbers in Perl. However, each of these three cases fails the second test in Andy's t/version.t file ...

    ok( $ver =~ /^2.\d\d(_\d\d)?$/, "Version is proper format" );

which says that if there is anything after the "hundredths" place in the version number, an underscore is mandatory. Relaxing this requirement ...

    ok( $ver =~ /^2.\d\d(_?\d\d)?$/, "Version is proper format" );

... allows each of the three cases above to pass t/version.t and simultaneously avoid the non-numeric warning.


Now, I believe I've read somewhere that assigning a string containing an underscore to $VERSION is a way to tell the CPAN indexer to label this particular version of a module as a developer's release. I suppose someone could think of a different way of doing that that would not run the risk of a non-numeric warning, but it's probably not important enough to warrant many brain cycles.

But it raises the question of whether one should ever assign a string to a module's $VERSION unless it were a string like a CVS version number. I consulted the web versions of three relevant man pages:

  http://perldoc.perl.org/perlmod.html#Perl-Modules-module
  http://perldoc.perl.org/perlmodlib.html#Guidelines-for-Module-Creation
  http://perldoc.perl.org/Exporter.html#Module-Version-Checking

Only the second of these pages gives an example where a non-CVS version number is stringified before being assigned to $VERSION ...

    $VERSION = "0.01"

... but it doesn't provide a rationale for the stringification. The other two pages suggest that, with the exception of CVS-type strings, what should be assigned to $VERSION is what qualifies in Perl as a number. (My own thinking is that I'll go back to using only numbers, not stringified numbers, in my own modules, but this probably falls somewhere between TMTOWTDI and YMMV.)

Jim Keenan

Reply via email to