Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

include/eval perl file into unique namespace defined at runtime

Tags:

perl

I'm writing a tool that must import a number of other perl config files. The files are not wrapped w/packages and may have similar or conflicting variables/functions. I don't have the ability to change the format of these files, so I must work around what they are. What I was thinking to do was import each into a unique name space, but I've not found a way to do that using do, require, or use. If I don't use dynamic names, just a hardcoded name, I can do it.

Want something like this:

sub sourceTheFile {
  my ($namespace, $file) = @_;
  package $namespace;
  do $file;
  1;
  return;
}

That doesn't work because the package command requires a constant for the name. So then I try something like this:

sub sourceTheFile {
  my ($namespace, $file) = @_;
  eval "package $namespace;do $file;1;"
  return;
}

But the contents of the file read by do are placed in the main:: scope not the one I want. The target scope is created, just not populated by the do. (I tried require, and just a straight cat $file inside the eval as well.)

I'm using Devel::Symdump to verify that the namespaces are built correctly or not.

example input file:

my $xyz = "some var";
%all_have_this = ( common=>"stuff" );

ADDITIONAL CHALLENGE

Using the answer that does the temp file build and do call, I can make this work dynamically as I require. BUT, big but, how do I now reference the data inside this new namespace? Perl doesn't seem to have the lose ability to build a variable name from a string and use that as the variable.

like image 589
Bruce Avatar asked Aug 24 '17 21:08

Bruce


1 Answers

I am not sure why the eval did not work. Maybe a bug? Here is a workaround using a temp file. This works for me:

use strict;
use warnings;

use Devel::Symdump;
use File::Temp;

my $file = './test.pl';
my $namespace = 'TEST';
{
    my $fh = File::Temp->new();
    print $fh "package $namespace;\n";
    print $fh "do '$file';\n";
    print $fh "1;\n";
    close $fh;
    do $fh->filename;
}
like image 144
Håkon Hægland Avatar answered Sep 27 '22 00:09

Håkon Hægland