Как я могу кратко проверить категории предупреждений вплоть до корня иерархии в моем пакете? - PullRequest
2 голосов
/ 11 июня 2019

Я знаю, как use warnings::register создавать собственные категории предупреждений для моего модуля. Однако, если я создаю категорию предупреждений Module::category и предупреждаю с помощью warnif(), no warnings 'Module' не подавляет предупреждения. Как я могу кратко проверить и Module::category и Module?

MCVE

package Provider;
use strict; use warnings;

use warnings::register qw(undefined);

sub foo {
    warnings::warnif('Provider::undefined', "Undefined parameter!");
}

package Consumer;
use strict; use warnings;

Provider::foo;      # warns - OK

{
    no warnings 'Provider::undefined';
    Provider::foo;  # does not warn - OK
}

{
    no warnings 'Provider';
    Provider::foo;  # _DOES_ warn - oops  <===========
}

Другое расследование

Если я проверяю состояние предупреждений внутри Provider::foo(), я вижу, что no warnings 'Provider' не касается Provider::undefined:

sub foo {
    print "$_: @{[warnings::enabled($_) ? 'enabled' : 'disabled']}\n"
        foreach qw(Provider::undefined Provider);
 }

дает

Provider::undefined: enabled
Provider: enabled
Provider::undefined: disabled
Provider: enabled
Provider::undefined: enabled
Provider: disabled

для трех тестов, приведенных выше.

Обходной путь

sub foo {
    my $should_warn = 1;
    foreach (qw(Provider::undefined Provider)) {
        if(!warnings::enabled($_)) {
            $should_warn = 0;
            last;
        }
    }
    warnings::warn('Provider::undefined', "Undefined parameter!")
        if $should_warn;
}

... но перед тем, как обернуть это в модуль и поместить его в CPAN, я бы хотел узнать, сделал ли это кто-нибудь еще или знает лучший способ :). Поиск в Google и SO был недоступен.

1 Ответ

3 голосов
/ 11 июня 2019

В операторе use warnings::register qw(undefined); введены две новые категории предупреждений: 'Provider' и 'Provider::undefined'. Так что проверяйте оба

sub foo {
    if (warnings::enabled('Provider') and 
        warnings::enabled('Provider::undefined')) 
    {
        warnings::warn('Undefined parameter');
    }   
}

Не сработает, если подавлена ​​любая из категорий

{
    no warnings 'Provider';               # EITHER stops it
    #no warnings 'Provider::undefined';

    Provider::foo;                        # does not warn
}

Чтобы оба no warnings требовали их остановки, используйте or в ::enabled условии в foo.


Чтобы уменьшить ввод Provider в подпрограммах модуля, вы можете настроить вспомогательную подпрограмму для этого, например

my $to_warn = sub  {
    return 0 if not warnings::enabled(__PACKAGE__);
    warnings::enabled(__PACKAGE__ . '::' . $_) 
        or return 0  for @_;
    return 1;
};

и тогда можно сделать

warnings::warn('Undefined parameter') if $to_warn->('undefined');

В $to_warn можно установить больше значений по умолчанию. Теперь имя Provider не нужно вводить вообще:)

Напомним, что $to_warn должно быть определено до его использования или, по крайней мере, предварительно объявлено.

...