Disallow numbers in imports for consistency with Sub::Exporter
Toby Inkster [Sat, 9 Mar 2013 16:21:03 +0000 (10:21 -0600)]
Exporter.pm does this silly thing where it interprets import arguments
starting with a digit as being a version check.

For example, given this, Exporter.pm will check that Carp.pm's version
number is at least 1000 (unlikely!)

   $ perl -e'use Carp carp => "1000"'

If the number appears first in the import list, Perl will already do
this for you, not involving Exporter.pm at all:

   $ perl -e'use Carp 1000, "carp"'

So it's not obvious why this feature was included in Exporter.pm at all.
Not many people seem to have noticed the feature is even there, though
it is documented. (However, the documentation of it does not quite match
its implementation!)

Anyhow, this feature seems a bad idea to use, and more importantly it
leads to a difference between how Exporter.pm and Sub::Exporter work.
Sub::Exporter::Progressive should attempt to smooth over such differences,
so it should I<always> die in this situation, whether Exporter.pm or
Sub::Exporter is being used.

lib/Sub/Exporter/Progressive.pm
t/version-check.t [new file with mode: 0644]

index 4529aaa..1d01d57 100644 (file)
@@ -29,6 +29,8 @@ sub import {
          $full_exporter ||= Sub::Exporter::build_exporter($export_data->{original});
 
          goto $full_exporter;
+      } elsif (defined(my $num = first { !ref and m/^\d/ } @args)) {
+         die "cannot export symbols with a leading digit: '$num'";
       } else {
          require Exporter;
          s/ \A - /:/xm for @args;
diff --git a/t/version-check.t b/t/version-check.t
new file mode 100644 (file)
index 0000000..5fe1062
--- /dev/null
@@ -0,0 +1,42 @@
+
+use strict;
+use warnings;
+use Test::More;
+
+BEGIN {
+   package AAA;
+   our $VERSION = 2;
+   use Sub::Exporter::Progressive -setup => {
+      exports => ['aaa'],
+   };
+   sub aaa { 'aaa' };
+   $INC{'AAA.pm'} = __FILE__;
+};
+
+ok(eval('use AAA 1; 1'), 'perl built-in module version check');
+
+{
+   local $@;
+   ok(!eval('use AAA 3; 1'), 'perl built-in module version check');
+   like(
+      $@,
+      qr/^AAA version 3 required/,
+      'perl built-in module version check error message',
+   );
+}
+
+{
+   local $@;
+   ok(
+      !eval('use AAA aaa => 1; 1'),
+      'Exporter.pm-style version check',
+   );
+   like(
+      $@,
+      qr{^cannot export symbols with a leading digit: '1'},
+      'Sub::Exporter::Progressive error message',
+   );
+}
+
+done_testing;
+