开发者

Importing in hierarchical Perl modules into the local namespace

开发者 https://www.devze.com 2022-12-18 05:33 出处:网络
Situation: I have a module Foo::Quux::Bar, living in ./Bar.pm. I need to be able to unit test Bar. However, it is not advantageous due to circumstances beyond my control to set up a Foo/Quux director

Situation:

I have a module Foo::Quux::Bar, living in ./Bar.pm. I need to be able to unit test Bar. However, it is not advantageous due to circumstances beyond my control to set up a Foo/Quux directory structure.

So what I'd like to do is have some sort of unit_test_use routine that lets me grab Bar.pm and move/copy its functions into the local namespace(Note tha开发者_高级运维t Bar has a package Foo::Quux::Bar specifier) for my testing pleasure.

Grubbing around in the Perl documentation has not helped me.


Assuming your Bar.pm exports its functions in the standard way, you can load it with require and do the import manually:

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

But it's definitely worth looking into setting up the directory structure in the standard way, if you can.


The example below uses the following Bar.pm:

package Foo::Quux::Bar;

use warnings;
use strict;

sub one { 1 }

sub two { "zwei" }

sub three { 0x3333 }

1;

In your test-bar program, you can install a hook that will use the current directory's Bar.pm with

#! /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;
}

Hooks in @INC are documented in the perlfunc documentation for require.

Now to import all subs, ignoring any import in 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};
      }
    }
  }
}

Back out in the test code where the strict pragma is enabled, we can

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

and get the following output:

1
zwei
13107


Here's what I wrote:

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

   require $filename;

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

}

Invoke with this: import_module_into_main("Foo::Quux::Bar", "Bar.pm").

0

精彩评论

暂无评论...
验证码 换一张
取 消