Импорт в иерархических модулях Perl в локальное пространство имен - PullRequest
1 голос
/ 29 января 2010

Положение:

У меня есть модуль Foo::Quux::Bar, проживающий в ./Bar.pm. Я должен быть в состоянии провести юнит-тест Бар. Однако не выгодно из-за не зависящих от меня обстоятельств настраивать структуру каталогов Foo / Quux.

Итак, что я хотел бы сделать, это иметь некоторую подпрограмму unit_test_use, которая позволяет мне захватывать Bar.pm и перемещать / копировать его функции в локальное пространство имен (обратите внимание, что Bar имеет спецификатор package Foo::Quux::Bar) для моего удовольствия при тестировании .

Перебираться в документации по Perl мне не помогло.

Ответы [ 3 ]

5 голосов
/ 29 января 2010

Если ваш Bar.pm экспортирует свои функции стандартным способом, вы можете загрузить его с помощью require и выполнить импорт вручную:

BEGIN { 
    require 'Bar.pm';        # now the package Foo::Quux::Bar is set up
    Foo::Quux::Bar->import;
};

Но, безусловно, стоит посмотреть, как настроить структуру каталогов стандартным способом.

4 голосов
/ 29 января 2010

В приведенном ниже примере используется следующее Bar.pm:

package Foo::Quux::Bar;

use warnings;
use strict;

sub one { 1 }

sub two { "zwei" }

sub three { 0x3333 }

1;

В вашей test-bar программе вы можете установить хук, который будет использовать текущий каталог Bar.pm с

#! /usr/bin/perl

use warnings;
use strict;

use File::Basename;

BEGIN {
  sub find_bar {
    my(undef,$name) = @_;

    if (basename($name) eq "Bar.pm") {
      open my $fh, "<", "./Bar.pm" or die "$0: open ./Bar.pm: $!";
      $fh;
    }
  }

  unshift @INC => \&find_bar;
}

Крючки в @INC описаны в документации perlfunc для require.

Теперь можно импортировать все сабвуферы, игнорируя любые import в Foo::Quux::Bar,

# fake use Foo::Quux::Bar
BEGIN {
  require Foo::Quux::Bar;
  {
    no strict 'refs';
    while (my($name,$glob) = each %Foo::Quux::Bar::) {
      if (*{ $glob }{CODE}) {
        *{ __PACKAGE__ . "::" . $name } = *{ $glob }{CODE};
      }
    }
  }
}

Вернитесь в тестовый код, где включена прагма strict, мы можем

print map "$_\n", one, two, three;

и получите следующий вывод:

1
zwei
13107
0 голосов
/ 29 января 2010

Вот что я написал:

sub import_module_into_main
{
   my ($mod_name, $filename) = @_;

   require $filename;

   no strict;
   foreach my $var ( keys( %{$mod_name . "::"}))
   {
      $main::{$var} = ${$mod_name. "::"}{$var};
   }

}

Вызвать с этим: import_module_into_main("Foo::Quux::Bar", "Bar.pm").

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...