Declare packages outside of their block

Perl v5.14 gets a step closer to a saner way to declare classes with its new package NAME BLOCK syntax that lets you easily group everything that goes in a package. » Read more…

Experimental features now warn (reaching back to v5.10)

Perl 5.18 provides a new way to introduce experimental features in a program, augmenting the feature pragma that v5.10 added. This change marks certain broken v5.10 features as experimental with an eye toward possible removal from the language.

Smart matching in v5.10 led to several broken and conflated features. The given used a lexical version of $_, which broke many other common uses of that variable inside the given, which I explain in Use for() instead of given() and you can see in given/when and lexical $_ …. » Read more…

Perl 5.18 new features

Perl v5.18 is out and there are some major changes that you should know about before you upgrade. Most notably, some features from v5.10 are now marked experimental. If you use those features, you get warnings.

You can download the Perl source from CPAN. For Windows, Strawberry Perl 5.18 is available now. » Read more…

The vertical tab is part of \s in Perl 5.18

Up to v5.18, the vertical tab wasn’t part of the \s character class shortcut for ASCII whitespace. No one really knows why. It was curious trivia that I pointed out in Know your character classes under different semantics. Whitespace in ASCII, POSIX, and Unicode represented different sets. Perl whitespace was different from POSIX whitespace by only the exclusion of the vertical tab. Now that little oversight is fixed. » Read more…

Perl v5.12 adds the package NAME VERSION syntax

Perl v5.12 modifies the package statement to take a version as well as a name. This allows you to implicitly declare the $VERSION variable: » Read more…

The Perl 5.12 yada yada operator

Perl v5.12 adds a placeholder operator, ..., called the yada yada operator, after an episode of Seinfeld where the interesting parts of the story are replaced with “yada yada yada”. » Read more…

Effective Perler discounts during OSCON

I’ll be at OSCON on Tuesday, July 17, but you don’t have to find me to get up to 37% off Effective Perl Programming. That’s a slightly lower price than Amazon. To get that discount, you have to buy the book at Pearson’s booth in the exhibition hall. You’ll need to track me down on Tuesday afternoon or evening if you want me to sign your book.

If you can’t make it to OSCON, you can still get 35% off the cover price by ordering directly from the InformIT discount link or using the OSCON2012 discount code when you check out. Instead of navigating their site, you can go directly to our book.

If you’re not sure you want the book, you can look at a free sample chapter, which is also 35% off during OSCON.

Declare your Pod encoding

Pod::Simple 3.21 changed its behavior when it encountered a non-ASCII character in Pod without an encoding. Instead of handling it quietly, it now gives a warning. That’s not so bad, but Test::Pod uses Pod::Simple, and whenever it sees a warning, pod_ok fails, as it did in my Mac::Errors module:


#   Failed test 'POD test for blib/lib/Mac/Errors.pm'
#   at .../Test/Pod.pm line 182.
# blib/lib/Mac/Errors.pm (2776): Non-ASCII character seen before =encoding in 'donÍt'. Assuming ISO8859-1
# Looks like you failed 1 test of 2.
t/pod.t ........... 
Dubious, test returned 1 (wstat 256, 0x100)
Failed 1/2 subtests 

Unfortunately, the Pod tests are the sort that shouldn’t stop an installation, which is why many developers have a separate area for author tests (which I’ll cover in an upcoming Item). Outside of that, you have to fix the Pod.

There are two things here. First, I have a genuine error here. The module is auto generated from other source files and the “donÍt” is a mistake; it should be “don’t” (with a smart quote) or even better, “don’t”. Test::Pod didn’t catch this before. So, that’s not bad.

More importantly, telling Perl that the source code is UTF-8 isn’t enough. When you use the utf8 pragma, the perl interpreter reads the source as UTF-8:

use utf8;

However, a Pod parser ignores all the code. It looks for Pod sections and never sees that pragma, nor does it care. You have to tell the pod which encoding you have if you want to use something outside of ASCII:

=encoding utf8

I hadn’t used that in Mac::Errors, or any of my other modules, although in some of them I had used genuine UTF-8 sequences. Now any person using Test::Pod with the latest Pod::Simple won’t be able to install those modules normally. That is, until I fix them.

I could use other encodings, such as ISO-8859-1, as long as I declare the right thing and save the file correctly.

Things to remember

  • The utf8 pragma doesn’t affect the Pod
  • Pod::Simple assumes ASCII unless you tell it otherwise
  • Declare your Pod encoding with the =encoding directive

Hide namespaces from PAUSE

The Perl Authors Upload Server (PAUSE) is responsible for analyzing distributions on their way to CPAN. PAUSE indexes the distributions to discover the package names that it contains so it can add them to the data files that many of the CPAN clients use to figure out what to download to install the module that you request. It also compares the package names that it finds to a list of permissions it maintains.

The mldistwatch program is reponsible for this bit. It tries two things to find the packages in the distribution. If it can read the META.yml (or META.json) to get the data. Otherwise, it examines files directory to look for package declarations. Sometimes these come up with the wrong answers.

First, there’s an easy fix to package statements in code. After ignoring text in Pod or after __END__ or __DATA__, PAUSE looks for package statements appearing on a single line:

# from PAUSE::pmfile::packages_per_pmfile()
           $pline =~ m{
                      (.*)
                      \bpackage\s+
                      ([\w\:\']+)
                      \s*
                      (?: $ | [\}\;] | ($version::STRICT) )
                    }x

If your complete package statement isn’t on a single line, then that won’t match it. Since Perl has insignificant whitespace, including vertical whitespace, you could to this:

package
    hide::this::package;

You might even leave yourself (or other developers) a note about the importance of that whitespace now:

package # hide from pause
    hide::this::package;

Indeed, if you grep CPAN, you’ll find hide from pause in many distributions.

That’s the easy way, although it’s kludgey and relies on a special case in the PAUSE code. Other indexers might not honor it. There’s a better way for you to explicitly tell an indexer what namespaces you want to advertise. You add them to the provides section of META.yml:

provides:
  Cats::Buster:
	file: lib/Cats/Buster.pm
	version: 0.01

The data in come from the META-spec. Module::Build will automatically create these entries in META.yml for you. The indexer can use these to know what’s in the distribution without directly examining module files.

If there are multiple packages declarations, all of them shown up in META.yml:

provides:
  Cats::Buster:
    file: lib/Test/Provides.pm
    version: 0.01
  Cats::Mimi:
    file: lib/Test/Provides.pm
    version: 0,02
  version:
    file: lib/Test/Provides.pm
    version: 0.01

Notice that version shows up in that list. You may have included it in your module to extend or override parts of that core module, but you don’t want people who want the real version to install your module to get it. You might only declare that package in your module as a temporary workaround and don’t intend it to be a permanent part of the work. They probably wouldn’t be able to do that anyway since PAUSE would recognize that you included a package for which you do not have permissions and would not index it. A site such as CPAN Search might mark your otherwise good distribution as “UNAUTHORIZED. Module::Build doesn’t know to exclude version, at least not by default.

To hide that package from indexers, you can specify it in no_index. In Build.PL, you can use META_ADD to specify that parts of the META-spec not already supported by other arguments to new:

use Module::Build;

my $builder = Module::Build->new(
	...,
	meta_add => {
		no_index => {
			package   => [ qw( version Local ) ],
			directory => [ qw( t/inc inc ) ],
			file      => [ qw( t/lib/test.pm ) ],
			namespace => [ qw( Local ) ],
			},
		},
);

The directory and file keys tell the indexer to ignore those parts of the distribution. The package tells the indexer to ignore exactly those packages. The curious one is namespace, which tells the indexer to ignore namespaces under that namespace.

Likewise, you can do the same in Makefile.PL with a recent enough version:

use ExtUtils::Makemaker 6.48;

WriteMakefile(
	...,
	META_ADD => {
		no_index => {
			package   => [ qw( version Local ) ],
			directory => [ qw( t/inc inc ) ],
			file      => [ qw( t/lib/test.pm ) ],
			namespace => [ qw( Local ) ],
			},
		},
	);

Otherwise, it examines the module files to find package statements, but it does it without running the code.

But, what if provides and no_index have conflicting instructions? The META-spec doesn’t give any guidance for indexers in those cases. PAUSE filters on no_index last. This means that PAUSE and other indexers might leave out files you specify in provides but then exclude in no_index.

Things to remember

  • Spread the package statement over two or more lines to hide it from PAUSE
  • Use provides to advertise the namespaces a distribution comprises.
  • Use no_index to limit what an indexer sees or reports.

Don’t use auto-dereferencing with each or keys

[Update: Perl v5.24 removes this experimental feature, for the reasons I list, among others.]

Perl 5.14 added an auto-dereferencing features to the hash and array operators, and I wrote about those in Use array references with the array operators. I’ve never particularly liked that feature, but I don’t have to like everything. Additionally, Perl 5.12 expanded the job of keys and values to also work on arrays. » Read more…

7ads6x98y