Moo: попытка перезагрузки отменена

У меня есть модуль, который использует несколько (автономных) модулей, и все эти модули имеют одинаковый атрибут (дескриптор объекта локализации). Вместо добавления этого атрибута ко всем классам я переместил этот атрибут в роль, которая затем используется всеми классами верхнего уровня.

К сожалению, теперь я получаю фатальную ошибку "Попытка перезагрузки" Роль "прервана" + "Сбой компиляции по требованию в строке 317" Модуль / время выполнения "".

Я дважды и тройно проверил, что я не использую Роль более одного раза во всех классах, но немного озадачен тем, как атаковать проблему и найти ошибку. Так как это происходит очень рано (в / до BEGIN), теперь есть (как мне известно) способ его отладки.

Иерархия классов Moo и приемники выглядят в основном так (это способ много кода для публикации всего, и это все еще слишком много):

Основной класс:

SwitchInfo.pm: use Foo::SwitchInfo::DeviceIdent;
SwitchInfo.pm: use Foo::SwitchInfo::Factory;
SwitchInfo.pm: use Foo::SwitchInfo::L10N;
SwitchInfo.pm: use Moo;

Роль:

SwitchInfo/Role/L10N.pm: use Moo::Role;

Первый уровень самостоятельных классов:

SwitchInfo/L10N: use base 'Locale::Maketext';

SwitchInfo/StackTable.pm: use Moo;
SwitchInfo/StackTable.pm: with 'Foo::SwitchInfo::Role::L10N';

SwitchInfo/DeviceIdent.pm: use Moo;
SwitchInfo/DeviceIdent.pm: with 'Foo::SwitchInfo::Role::L10N';

SwitchInfo/NameTable.pm: use Moo;
SwitchInfo/NameTable.pm: with 'Foo::SwitchInfo::Role::L10N';

SwitchInfo/Factory.pm: use Moo;
SwitchInfo/Factory.pm: with 'Foo::SwitchInfo::Role::L10N';

SwitchInfo/AliasTable.pm: use Moo;
SwitchInfo/AliasTable.pm: with 'Foo::SwitchInfo::Role::L10N';

SwitchInfo/Domain.pm: use Moo;

SwitchInfo/Driver.pm: use Foo::SwitchInfo::AliasTable;
SwitchInfo/Driver.pm: use Foo::SwitchInfo::Domain;
SwitchInfo/Driver.pm: use Foo::SwitchInfo::NameTable;
SwitchInfo/Driver.pm: use Foo::SwitchInfo::StackTable;
SwitchInfo/Driver.pm: use Moo;
SwitchInfo/Driver.pm: with 'Foo::SwitchInfo::Role::L10N';

Подклассы для второго уровня классов:

SwitchInfo/Driver/Cisco.pm: use Moo;
SwitchInfo/Driver/Cisco.pm: extends 'Foo::SwitchInfo::Driver';

SwitchInfo/Driver/Extreme.pm: use Foo::SwitchInfo::Domain;
SwitchInfo/Driver/Extreme.pm: use Foo::SwitchInfo::Driver::Extreme::NameTable;
SwitchInfo/Driver/Extreme.pm: use Foo::SwitchInfo::Driver::Extreme::StackTable;
SwitchInfo/Driver/Extreme.pm: use Moo;
SwitchInfo/Driver/Extreme.pm: extends 'Foo::SwitchInfo::Driver';

SwitchInfo/Driver/Extreme/StackTable.pm: use Moo;
SwitchInfo/Driver/Extreme/StackTable.pm: extends 'Foo::SwitchInfo::StackTable';

SwitchInfo/Driver/Extreme/NameTable.pm: use Moo;
SwitchInfo/Driver/Extreme/NameTable.pm: extends 'Foo::SwitchInfo::NameTable';

При попытке использовать основной класс я получаю следующую ошибку:

$ cat sw.pl 
use strict;
use warnings;

use lib './lib';
use Foo::SwitchInfo;
$
$ perl sw.pl
Attempt to reload Foo/SwitchInfo/Role/L10N.pm aborted.
Compilation failed in require at /opt/perl5/lib/perl5/Module/Runtime.pm line 317.
Compilation failed in require at lib/Foo/SwitchInfo.pm line 3.
BEGIN failed--compilation aborted at lib/Foo/SwitchInfo.pm line 3.
Compilation failed in require at sw.pl line 5.
BEGIN failed--compilation aborted at sw.pl line 5.
$ 

Заголовок Foo/SwitchInfo.pm (с номерами строк):

 1 package Foo::SwitchInfo;
 2 
 3 use Foo::SwitchInfo::DeviceIdent;
 4 use Foo::SwitchInfo::Factory;
 5 use Foo::SwitchInfo::L10N;
 6 use Types::Standard qw/ ArrayRef InstanceOf Str /;
 7 use Type::Utils qw/ as coerce declare from via /;
 8 
 9 use Foo::SNMP;
10 
11 use Moo;
12 use namespace::clean;

И полная роль такова:

package Foo::SwitchInfo::Role::L10N;

use Types::Standard qw/ InstanceOf /;

use Moo::Role;

has l10n => (
  is        => 'ro',
  isa       => InstanceOf['Foo::SwitchInfo::L10N'],
  handles   => qw/ maketext /,
  required  => 1,
);

1;

Небольшой тестовый сценарий подтвердил, что можно без проблем использовать роль в нескольких классах, а затем использовать эти классы в другом классе.

Если кто-то еще читает этот длинный пост, вы обнаружите какие-либо проблемы? Или это использование роли предполагаемого использования для нее? Это моя первая (настоящая) попытка использования роли, поэтому я мог бы выйти за пределы здесь.

1 ответ

Нашел ошибку. Оказывается, у меня была опечатка в директиве "ручки" в роли.

было

handles => qw/ maketext /,

должно было

handles => [ qw/ maketext / ],

Понял это, запустив

perl -c lib/Foo/SwitchInfo/Role/L10N.pm

который жаловался громко

Can't locate maketext.pm in @INC
Другие вопросы по тегам