perl: export symbols from module that has > 1 package - perl

module foo/bar.pm
package foo::bar;
stuff
stuff
package foo::wizzy;
require Exporter;
our #ISA=qw(Exporter);
our #EXPORT=qw(x);
use constant
{
x=>1
};
a consumer that does
use Foo::bar;
does not get the foo::wizzy::x export
I know I can make it two separate modules, but still I should be able to make this work, shouldn't I?

You can do it using Exporter's export_to_level method to have the "main package" re-export the "other" package's symbols like so:
sub import {
my $self = shift;
$self->export_to_level(1, #_);
Some::Other::Module->export_to_level(1);
}
though if Some::Other::Module does something more complicated than "export everything" you will probably need fancier handling for #_.
I really have to ask why, though—I can't imagine a use for this that's compatible with the words "good code" :)

When you call use foo::bar, what actually happens is essentially:
BEGIN {
require foo::bar;
foo::bar->import;
}
(see perldoc -f use)
So import is never getting called on foo::wizzy. If you want to import those symbols as well, you can call BEGIN { foo::wizzy->import } yourself (after use foo::bar). Or, as you said, just split these two packages into separate files, which would be much more human-readable.
(By the way, it's not advisable to use lower-cased package names, as those are generally reserved for perl pragmata.)

At the end of the module, put:
BEGIN { $INC{'foo/wizzy.pm'} = 1 }
Then code can just say:
use foo::bar;
use foo::wizzy;
to get foo::wizzy's exports.

First off, I find it helpful to use enclosing braces to control scope when cramming multiple packages into one file. Also, enclosing the package in a BEGIN block makes it work more like a proper use was used to load it, but this is mostly if I am cramming the package into the main script.
use Foo is the same as BEGIN { require Foo; Foo->import }.
So, you have two choices:
call BEGIN{ Foo::Whizzy->import; } in your main script.
make Foo::Bar::import trigger Foo::Whizzy::import on the calling module.
In Foo/Bar.pm:
{ package Foo::Bar;
use Exporter qw( export_to_level );
# Special custom import. Not needed if you call Foo::Whizzy->import
sub import {
shift;
export_to_level('Foo::Whizzy', 1, #_ );
}
# stuff
# stuff
}
{ package Foo::Whizzy;
require Exporter;
our #ISA=qw(Exporter);
our #EXPORT=qw(x);
use constant { x=>1 };
}
1; # return true
In your main code:
use Foo::Bar;
# If you don't do a custom import for Foo::Bar, add this line:
BEGIN { Foo::Whizzy->import };

Related

Perl Import Package in different Namespace

is it possible to import (use) a perl module within a different namespace?
Let's say I have a Module A (XS Module with no methods Exported #EXPORT is empty) and I have no way of changing the module.
This Module has a Method A::open
currently I can use that Module in my main program (package main) by calling A::open I would like to have that module inside my package main so that I can directly call open
I tried to manually push every key of %A:: into %main:: however that did not work as expected.
The only way that I know to achieve what I want is by using package A; inside my main program, effectively changing the package of my program from main to A.
Im not satisfied with this. I would really like to keep my program inside package main.
Is there any way to achieve this and still keep my program in package main?
Offtopic: Yes I know usually you would not want to import everything into your namespace but this module is used by us extensively and we don't want to type A:: (well the actual module name is way longer which isn't making the situation better)in front of hundreds or thousands of calls
This is one of those "impossible" situations, where the clear solution -- to rework that module -- is off limits.
But, you can alias that package's subs names, from its symbol table, to the same names in main. Worse than being rude, this comes with a glitch: it catches all names that that package itself imported in any way. However, since this package is a fixed quantity it stands to reason that you can establish that list (and even hard-code it). It is just this one time, right?
main
use warnings;
use strict;
use feature 'say';
use OffLimits;
GET_SUBS: {
# The list of names to be excluded
my $re_exclude = qr/^(?:BEGIN|import)$/; # ...
my #subs = grep { !/$re_exclude/ } sort keys %OffLimits::;
no strict 'refs';
for my $sub_name (#subs) {
*{ $sub_name } = \&{ 'OffLimits::' . $sub_name };
}
};
my $name = name('name() called from ' . __PACKAGE__);
my $id = id('id() called from ' . __PACKAGE__);
say "name() returned: $name";
say "id() returned: $id";
with OffLimits.pm
package OffLimits;
use warnings;
use strict;
sub name { return "In " . __PACKAGE__ . ": #_" }
sub id { return "In " . __PACKAGE__ . ": #_" }
1;
It prints
name() returned: In OffLimits: name() called from main
id() returned: In OffLimits: id() called from main
You may need that code in a BEGIN block, depending on other details.
Another option is of course to hard-code the subs to be "exported" (in #subs). Given that the module seems to be immutable in practice this option is reasonable and more reliable.
This can also be wrapped in a module, so that you have the normal, selective, importing.
WrapOffLimits.pm
package WrapOffLimits;
use warnings;
use strict;
use OffLimits;
use Exporter qw(import);
our #sub_names;
our #EXPORT_OK = #sub_names;
our %EXPORT_TAGS = (all => \#sub_names);
BEGIN {
# Or supply a hard-coded list of all module's subs in #sub_names
my $re_exclude = qr/^(?:BEGIN|import)$/; # ...
#sub_names = grep { !/$re_exclude/ } sort keys %OffLimits::;
no strict 'refs';
for my $sub_name (#sub_names) {
*{ $sub_name } = \&{ 'OffLimits::' . $sub_name };
}
};
1;
and now in the caller you can import either only some subs
use WrapOffLimits qw(name);
or all
use WrapOffLimits qw(:all);
with otherwise the same main as above for a test.
The module name is hard-coded, which should be OK as this is meant only for that module.
The following is added mostly for completeness.
One can pass the module name to the wrapper by writing one's own import sub, which is what gets used then. The import list can be passed as well, at the expense of an awkward interface of the use statement.
It goes along the lines of
package WrapModule;
use warnings;
use strict;
use OffLimits;
use Exporter qw(); # will need our own import
our ($mod_name, #sub_names);
our #EXPORT_OK = #sub_names;
our %EXPORT_TAGS = (all => \#sub_names);
sub import {
my $mod_name = splice #_, 1, 1; # remove mod name from #_ for goto
my $re_exclude = qr/^(?:BEGIN|import)$/; # etc
no strict 'refs';
#sub_names = grep { !/$re_exclude/ } sort keys %{ $mod_name . '::'};
for my $sub_name (#sub_names) {
*{ $sub_name } = \&{ $mod_name . '::' . $sub_name };
}
push #EXPORT_OK, #sub_names;
goto &Exporter::import;
}
1;
what can be used as
use WrapModule qw(OffLimits name id); # or (OffLimits :all)
or, with the list broken-up so to remind the user of the unusual interface
use WrapModule 'OffLimits', qw(name id);
When used with the main above this prints the same output.
The use statement ends up using the import sub defined in the module, which exports symbols by writing to the caller's symbol table. (If no import sub is written then the Exporter's import method is nicely used, which is how this is normally done.)
This way we are able to unpack the arguments and have the module name supplied at use invocation. With the import list supplied as well now we have to push manually to #EXPORT_OK since this can't be in the BEGIN phase. In the end the sub is replaced by Exporter::import via the (good form of) goto, to complete the job.
You can forcibly "import" a function into main using glob assignment to alias the subroutine (and you want to do it in BEGIN so it happens at compile time, before calls to that subroutine are parsed later in the file):
use strict;
use warnings;
use Other::Module;
BEGIN { *open = \&Other::Module::open }
However, another problem you might have here is that open is a builtin function, which may cause some problems. You can add use subs 'open'; to indicate that you want to override the built-in function in this case, since you aren't using an actual import function to do so.
Here is what I now came up with. Yes this is hacky and yes I also feel like I opened pandoras box with this. However at least a small dummy program ran perfectly fine.
I renamed the module in my code again. In my original post I used the example A::open actually this module does not contain any method/variable reserved by the perl core. This is why I blindly import everything here.
BEGIN {
# using the caller to determine the parent. Usually this is main but maybe we want it somewhere else in some cases
my ($parent_package) = caller;
package A;
foreach (keys(%A::)) {
if (defined $$_) {
eval '*'.$parent_package.'::'.$_.' = \$A::'.$_;
}
elsif (%$_) {
eval '*'.$parent_package.'::'.$_.' = \%A::'.$_;
}
elsif (#$_) {
eval '*'.$parent_package.'::'.$_.' = \#A::'.$_;
}
else {
eval '*'.$parent_package.'::'.$_.' = \&A::'.$_;
}
}
}

How to handle: Moo::Role's `before` modifier silently skipped due to circular imports?

Using Moo::Role, I'm finding that circular imports are silently preventing the execution of the before modifier of my method.
I have a Moo::Role in MyRole.pm :
package MyRole;
use Moo::Role;
use MyB;
requires 'the_method';
before the_method => sub { die 'This has been correctly executed'; };
1;
...a consumer in MyA.pm :
package MyA;
use Moo;
with ( 'MyRole' );
sub the_method { die; }
1;
..and another in MyB.pm :
package MyB;
use Moo;
with ( 'MyRole' );
sub the_method { die 'The code should have died before this point'; }
1;
When I run this script.pl:
#!/usr/bin/env perl
package main;
use MyA;
use MyB;
MyB->new()->the_method();
...I get The code should have died before this point at MyB.pm line 4. but would expect to see This has been correctly executed at MyRole.pm line 5.
I think this problem is caused by the circular imports. It goes away if I switch the order of the use statements in script.pl or if I change the use MyB; in MyRole.pm to be a require within the_method.
Is this behaviour expected? If so, what is the best way to handle it where circular imports can't be avoided?
I can workaround the problem but it feels worryingly easy to inadvertently trigger (particularly since it causes before functions, which often contain checking code, to be silently skipped).
(I'm using Moo version 2.003004. Obviously the use MyB; in MyRole.pm is superfluous here but only after I've simplified the code for this repro example.)
Circular imports can get rather tricky, but behave consistently. The crucial points are:
use Some::Module behaves like BEGIN { require Some::Module; Some::Module->import }
When a module is loaded, it is compiled and executed. BEGIN blocks are executed during parsing of the surrounding code.
Each module is only require'd once. When it is required again, that require is ignored.
Knowing that, we can combine your four files into a single file that includes the required files in a BEGIN block.
Let's start with your main file:
use MyA;
use MyB;
MyB->new()->the_method();
We can transform the use to BEGIN { require ... } and include the MyA contents. For clarity, I will ignore any ->import calls on MyA and MyB because they are not relevant in this case.
BEGIN { # use MyA;
package MyA;
use Moo;
with ( 'MyRole' );
sub the_method { die; }
}
BEGIN { # use MyB;
require MyB;
}
MyB->new()->the_method();
The with('MyRole') also does a require MyRole, which we can make explicit:
...
require MyRole;
with( 'MyRole ');
So let's expand that:
BEGIN { # use MyA;
package MyA;
use Moo;
{ # require MyRole;
package MyRole;
use Moo::Role;
use MyB;
requires 'the_method';
before the_method => sub { die 'This has been correctly executed'; };
}
with ( 'MyRole' );
sub the_method { die; }
}
BEGIN { # use MyB;
require MyB;
}
MyB->new()->the_method();
We can then expand the use MyB, also expanding MyB's with('MyRole') to a require:
BEGIN { # use MyA;
package MyA;
use Moo;
{ # require MyRole;
package MyRole;
use Moo::Role;
BEGIN { # use MyB;
package MyB;
use Moo;
require MyRole;
with ( 'MyRole' );
sub the_method { die 'The code should have died before this point'; }
}
requires 'the_method';
before the_method => sub { die 'This has been correctly executed'; };
}
with ( 'MyRole' );
sub the_method { die; }
}
BEGIN { # use MyB;
require MyB;
}
MyB->new()->the_method();
Within MyB we have a require MyRole, but that module has already been required. Therefore, this doesn't do anything. At that point during the execution, MyRole only consists of this:
package MyRole;
use Moo::Role;
So the role is empty. The requires 'the_method'; before the_method => sub { ... } has not yet been compiled at that point.
As a consequence MyB composes an empty role, which does not affect the the_method.
How can this be avoided? It is often helpful to avoid a use in these cases because that interrupts parsing, before the current module has been initialized. This leads to unintuitive behaviour.
When the modules you use are just classes and do not affect how your source code is parsed (e.g. by importing subroutines), then you can often defer the require to run time. Not just the run time of the module where top-level code is executed, but to the run time of the main application. This means sticking your require into the subroutine that needs to use the imported class. Since a require still has some overhead even when the required module is already imported, you can guard the require like state $require_once = require Some::Module. That way, the require has no run-time overhead.
In general: you can avoid many problems by doing as little initialization as possible in the top-level code of your modules. Prefer being lazy and deferring that initialization. On the other hand, this laziness can also make your system more dynamic and less predictable: it is difficult to tell what initialization has already happened.
More generally, think hard about your design. Why is this circular dependency needed? You should decide to either stick to a layered architecture where high-level code depends on low-level code, or use dependency inversion where low-level code depends on high-level interfaces. Mixing both will result in a horrible tangled mess (exhibit A: this question).
I do understand that some data models necessarily feature co-recursive classes. In that case it can be clearest to sort out the order manually by placing the interdependent classes in a single file.

How to declare an array variable to be global in module scope

I have some code I decided to pull into a module in perl. I admit that I am doing a bit of monkey-see monkey-do stuff following documentation I've found online.
There is only one pubicly visible subroutine, which sets 2 variables * would like to use in other subroutines in the module, without passing them explicitly as parameters -- $fname, and #lines. Looking online I came up with the "our" keyword, but when I try to declare them at global level (see code snippet below), I get the following error:
mig_tools.pm did not return a true value at
I have worked around the issue by declaring "our $fname" and "our #lines" in every subroutine they are used, but I would prefer to declare them once at global scope. Is that possible?
Here's what I take to be the relevant part of the code.
package mig_tools;
require Exporter;
use strict;
use warnings;
our #ISA = qw(Exporter);
our #EXPORT = qw( ensure_included);
our $fname;
our #lines;
// definitions of already_has_include find_include_insert_point and ensure_included.
All-lowercase variables are reserved for local identifiers and pragma names. Your module should be in MigTools.pm and you should use it with use MigTools
The did not return a true value error is just because your module file didn't return a true value when it was executed. It is usual to add a line containing just 1; to the end of all modules
Your MigTools.pm should look like this. It is best to use the import directly from Exporter instead of subclassing it, and our doesn't help you to create a global variable, but I am a little worried about why you are structuring your module this way
package MigTools;
use strict;
use warnings;
use Exporter qw/ import /;
our #EXPORT = qw/ ensure_included /;
my ($fname, #lines)
sub ensure_included {
}
sub already_has_include {
}
sub find_include_insert_point {
}
sub ensure_included {
}
1;

Passing arguments to a perl package while using it

How to pass some arguments while using a package, for example:
use Test::More tests => 21;
I wasn't able to find any valuable documentation about this featue. Are there any pros and cons of passing such arguments?
use My::Module LIST does two things: 1) It requires My::Module; and 2) Invokes My::Module->import(LIST).
Therefore, you can write your module's import routine to treat the list of arguments passed any which way you want. This becomes even easier if you are indeed writing an object oriented module that does not export anything to the caller's namespace.
Here's a rather pointless example:
package Ex;
use strict;
use warnings;
{
my $hello = 'Hello';
sub import {
my $self = shift;
my $lang = shift || 'English';
if ($lang eq 'Turkish') {
$hello = 'Merhaba';
}
else {
$hello = 'Hello';
}
return;
}
sub say_hello {
my $self = shift;
my $name = shift;
print "$hello $name!\n";
return;
}
}
__PACKAGE__;
__END__
And a script to use it:
#!/usr/bin/env perl
use strict;
use warnings;
use Ex 'Turkish';
Ex->say_hello('Perl');
Ex->import;
Ex->say_hello('Perl');
Output:
$ ./imp.pl
Merhaba Perl!
Hello Perl!
Some may say it is more readable in some scenarios, but in essence it is same as
use Test::More qw(tests 21);
(test is auto-quoted by fat comma =>, and number doesn't need quote).
The major disadvantage is that you can't use the default import subroutine from Exporter, which expects only a list of symbols (or tags denoting collections of symbols) to import into the calling package
Test::More inherits a custom import routine from the superclass Test::Builder::Module, which uses the arguments supplied in the use statement to configure the test plan. It also in turn uses Exporter to handle options specified like import => [qw/ symbols to import /]
Pretty much anything can be done by a custom import subroutine if you have a specific requirement, but it is probably unwise to stray too far from standard object-oriented semantics

inspect the parameters to "use", and pass on the rest?

I have a Perl module and I'd like to be able to pick out the parameters that my my module's user passed in the "use" call. Whichever ones I don't recognize I'd like to pass on. I tried to do this by overriding the "import" method but I'm not having much luck.
EDIT:
To clarify, as it is, I can use my module like this:
use MyModule qw/foo bar/;
which will import the foo and bar methods of MyModule. But I want to be able to say:
use MyModule qw/foo doSpecialStuff bar/;
and look for doSpecialStuff to check if I need to do some special stuff at the beginning of the program, then pass qw/foo bar/ to the Exporter's import
Normally, you would do this to gain Exporter's import() functionality (this isn't the only way, but it's a common method that works):
package MyClass;
use strict;
use warnings;
use Exporter 'import'; # gives you Exporter's import() method directly
our #EXPORT_OK = qw(stuff more_stuff even_more_stuff);
...and then you will get an import() method automatically created for you. However, if you want to do something extra in import() before the normal method gets a hold of the parameters, then don't import Exporter's import(), and define your own, which calls Exporter's import() after making any alterations to the argument list that you need:
package MyClass;
use strict;
use warnings;
use parent 'Exporter';
sub import
{
my ($class, #symbols) = #_;
# do something with #symbols, as appropriate for your application
# ...code here left as an exercise for the reader :)
# now call Exporter's import, and import to the right level
local $Exporter::ExportLevel = 1;
$class->SUPER::import(#symbols);
}
However, I'm wondering why you need to do this... the standard behaviour of dying when being passed an unrecognized symbol is normally a good thing. Why would you want to ignore unrecognized symbols? (Edit: I see now, you want to specify additional behaviour on top of importing symbols, which is not uncommon in Perl. So defining your own import() method is definitely the way to go here, to grab those values.)
PS. if you only want to import symbols which are defined by #EXPORT_OK, it could be implemented like this:
#symbols = grep {
my $sym = $_;
grep { $_ eq $sym } #EXPORT_OK
} #symbols;
The typical use of Exporter is to declare your module to inherit from Exporter, and to have Exporter's import method called implicitly when your module is used. But this keeps you from creating your own import method for your module.
The workaround is to use Exporter's export_to_level method, which performs Exporter's functions without explicitly going through the Exporter::import method. Here's a typical way to use it:
package My::Module;
use base 'Exporter'; # or use Exporter; our #ISA=qw(Exporter);
our #EXPORT = qw(...);
our #EXPORT_OK = qw(...);
our %EXPORT_TAGS = (...);
sub import {
my ($class,#import_args) = #_;
my #import_args_to_pass_on = ();
foreach my $arg (#import_args) {
if (... want to process this arg here ...) {
...
} else {
push #import_args_to_pass_on, $arg;
}
}
My::Module->export_to_level(1, "My::Module", #import_args_to_pass_on, #EXPORT);
#or: $class->export_to_level(1, $class, #import_args_to_pass_on, #EXPORT);
}
I have done it this way in my modules:
sub import {
return if not #_;
require Exporter;
my $pkg = shift;
# process #_ however you want
unshift #_, $pkg;
goto &Exporter::import;
}
you can also inherit from Exporter if you want unimport and the like.