Recipe 12.15 Customizing Warnings

12.15.1 Problem

You would like your module to respect its caller's settings for lexical warnings, but you can't inspect the predefined $^W[2] variable to determine those settings.

[2] That's $WARNING if you've used English.

12.15.2 Solution

Your module should use this pragma:

use warnings::register;

Then from inside your module, use the warnings::enabled function from that module as described in the Discussion to check whether the caller has warnings enabled. This works for both the old-style, global warnings and for lexical warnings set via the use warnings pragma.

12.15.3 Discussion

Perl's -w command-line flag, mirrored by the global $^W variable, suffers from several problems. For one thing, it's an all-or-nothing affair, so if you turn it on for the program, module code included by that program including code you may not have written is also affected by it. For another, it's at best cumbersome to control compile-time warnings with it, forcing you to resort to convoluted BEGIN blocks. Finally, suppose you were interested in numeric warnings but not any other sort; you'd have to write a $SIG{_ _WARN_ _} handler to sift through all warnings to find those you did or did not want to see.

Lexical warnings, first introduced in Perl v5.6, address all this and more. By lexical, we mean that their effects are constrained to the lexical scope in which use warnings or no warnings occurs. Lexical warnings pay no attention to the -w command-line switch. Now when you turn warnings on in one scope, such as the main program's file scope, that doesn't enable warnings in modules you load. You can also selectively enable or disable individual categories of warnings. For example:

use warnings qw(numeric uninitialized); use warnings qw(all); no warnings qw(syntax);

The warnings::register pragma permits a module to check the warnings preferences of its caller's lexical scope. The pragma also creates a new warning category, taken from the name of the current package. These user-defined warning categories are easily distinguishable from the built-in warning categories because a module's package always starts (or should always start) with an uppercase letter. This way lowercase warning categories, like lowercase module names, are reserved to Perl itself.

Built-in warnings categories are organized into several groups. The all category means all built-in warnings categories, including subcategories such as unsafe, io, syntax, etc. (see Figure 12-1). The syntax category comprises particular warnings categories, such as ambiguous, precedence, and deprecated. These can be added and subtracted at will, but order matters:

Figure 12-1. Warnings categories
figs/pcb2_1201.gif
use warnings;                 # turn on all warnings no  warnings "syntax";        # turn off the syntax group use warnings "deprecated";    # but turn back on deprecated warnings

Back to your module. Suppose you write a module called Whiskey. The Whiskey.pm file begins this way:

package Whiskey; use warnings::register;

Now code using that module does this:

use Whiskey; use warnings qw(Whiskey);

It's important to load the module before asking to use warnings for that module. Otherwise, the Whiskey warning category hasn't been registered yet, and you'll raise an exception if you try to use it as a warnings category.

Here's a whimsical Whiskey module:

package Whiskey; use strict; use warnings;  # for our own code, not our caller use warnings::register; sub drink {     if (warnings::enabled( ) && (localtime( ))[2] < 12) {         warnings:warn("Sun not yet over the yardarm");     }      print "Merry!\n"; }  sub quaff {     if (warnings::enabled("deprecated")) {         warnings::warn("deprecated",              "quaffing deprecated in favor of chugging");     }      &drink; }  # chuggers care not of the hour sub chug {     print "Very merry\n"; }  1;

The Whiskey::drink function uses the warnings::enabled function to check whether its caller has warnings enabled. Any of these in the caller's scope is enough to make that function return true:

use warnings; use warnings qw(all);  # means same as previous use warnings qw(Whiskey);

The function will also return true if global warnings are enabled using -w or $^W.

In the Whiskey::quaff function, a specific category of warnings is checked: deprecated. This is enabled if all warnings have been selected, if the syntax warnings have been selected (because deprecated warnings are considered a subcategory of syntax warnings, which is a subcategory of all warnings), or if deprecated warnings have been specifically selected. It will not be enabled just because the caller has enabled Whiskey warnings. Any category you create is considered a subcategory of all, but not of anything else. Check for Whiskey warnings using:

warnings::enabled("Whiskey")

The warnings::warn function is used instead of the warn built-in, in case Whiskey warnings have been promoted into exceptions:

use warnings FATAL => "Whiskey";

12.15.4 See Also

The documentation on the use warnings pragma in Chapter 31 of Programming Perl and perllexwarn(1)



Perl Cookbook
Perl Cookbook, Second Edition
ISBN: 0596003137
EAN: 2147483647
Year: 2003
Pages: 501

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net