use strict;
use warnings FATAL => 'all';
+use Module::Runtime;
-our $VERSION = '1.001001'; # 1.1.1
+our $VERSION = '1.002003';
sub _prelude {
my $target = shift;
- my ($package, $file, $line)
- = $target =~ /[^0-9]/ ? ($target) : caller($target + 2);
+ my ($package, $file, $line, $level)
+ = ref $target ? @{$target}{qw(package filename line)}
+ : $target =~ /[^0-9]/ ? ($target)
+ : (undef, undef, undef, $target);
+ if (defined $level) {
+ my ($p, $fn, $ln) = caller($level + 2);
+ $package ||= $p;
+ $file ||= $fn;
+ $line ||= $ln;
+ }
qq{package $package;\n}
. ($file ? "#line $line \"$file\"\n" : '')
}
sub _make_action {
my ($action, $target) = @_;
- eval _prelude($target).qq{sub { shift->$action(\@_) }}
+ my $version = ref $target && $target->{version};
+ my $ver_check = $version ? ', $version' : '';
+ eval _prelude($target)
+ . qq{sub { Module::Runtime::use_module( shift$ver_check )->$action(\@_) }}
or die "Failed to build action sub to ${action} for ${target}: $@";
}
}
1;
-
+
+__END__
+
=head1 NAME
-Import::Into - import packages into other packages
+Import::Into - Import packages into other packages
=head1 SYNOPSIS
use Import::Into;
- use Thing1 ();
- use Thing2 ();
- use Thing3 ();
+ # simple
+ sub import {
+ Thing1->import::into(scalar caller);
+ }
+ # multiple
sub import {
my $target = caller;
Thing1->import::into($target);
Thing2->import::into($target, qw(import arguments));
- Thing3->import::into(1); # import to level
}
-Note: you don't need to do anything more clever than this provided you
-document that people wanting to re-export your module should also be using
-L<Import::Into>. In fact, for a single module you can simply do:
-
+ # by level
sub import {
- ...
- Thing1->import::into(scalar caller);
+ Thing1->import::into(1);
}
-Notably, this works:
-
+ # with exporter
use base qw(Exporter);
-
sub import {
shift->export_to_level(1);
- Thing1->import::into(scalar caller);
+ Thing1->import::into(1);
}
-Note 2: You do B<not> need to do anything to Thing1 to be able to call
-C<import::into> on it. This is a global method, and is callable on any
-package (and in fact on any object as well, although it's rarer that you'd
-want to do that).
-
-If you provide C<import::into> with an integer instead of a package name, it
-will be used as the number of stack frames to skip to find where to export to.
-This has the advantage of preserving the apparent filename and line number
-being exported to, which some modules (L<autodie>, L<strictures>) check.
-
-Finally, we also provide an C<unimport::out_of> to allow the exporting of the
-effect of C<no>:
-
- # unimport::out_of was added in 1.1.0 (1.001000)
+ # no My::MultiExporter == no Thing1
sub unimport {
- Moose->unimport::out_of(scalar caller); # no MyThing == no Moose
+ Thing1->unimport::out_of(scalar caller);
}
-If how and why this all works is of interest to you, please read on to the
-description immediately below.
+People wanting to re-export your module should also be using L<Import::Into>.
+Any exporter or pragma will work seamlessly.
+
+Note: You do B<not> need to make any changes to Thing1 to be able to call
+C<import::into> on it. This is a global method, and is callable on any
+package (and in fact on any object as well, although it's rarer that you'd
+want to do that).
=head1 DESCRIPTION
some use L<Moose::Exporter>, some use L<Exporter::Declare> ... and some things
are pragmas.
-If you want to re-export other things, you have to know which is which.
-L<Exporter> subclasses provide export_to_level, but if they overrode their
-import method all bets are off. L<Sub::Exporter> provides an into parameter
-but figuring out something used it isn't trivial. Pragmas need to have
-their C<import> method called directly since they affect the current unit of
-compilation.
+Exporting on someone else's behalf is harder. The exporters don't provide a
+consistent API for this, and pragmas need to have their import method called
+directly, since they effect the current unit of compilation.
+
+C<Import::Into> provides global methods to make this painless.
+
+=head1 METHODS
+
+=head2 $package->import::into( $target, @arguments );
+
+A global method, callable on any package. Loads and imports the given package
+into C<$target>. C<@arguments> are passed along to the package's import method.
+
+C<$target> can be an package name to export to, an integer for the
+caller level to export to, or a hashref with the following options:
+
+=over 4
+
+=item package
+
+The target package to export to.
+
+=item filename
+
+The apparent filename to export to. Some exporting modules, such as
+L<autodie> or L<strictures>, care about the filename they are being imported
+to.
+
+=item line
+
+The apparent line number to export to. To be combined with the C<filename>
+option.
+
+=item level
+
+The caller level to export to. This will automatically populate the
+C<package>, C<filename>, and C<line> options, making it the easiest most
+constent option.
+
+=item version
+
+A version number to check for the module. The equivalent of specifying the
+version number on a C<use> line.
+
+=back
+
+=head2 $package->unimport::out_of( $target, @arguments );
+
+Equivalent to C<import::into>, but dispatches to C<$package>'s C<unimport>
+method instead of C<import>.
+
+=head1 WHY USE THIS MODULE
+
+The APIs for exporting modules aren't consistent. L<Exporter> subclasses
+provide export_to_level, but if they overrode their import method all bets
+are off. L<Sub::Exporter> provides an into parameter but figuring out
+something used it isn't trivial. Pragmas need to have their C<import> method
+called directly since they affect the current unit of compilation.
It's ... annoying.
So, a solution for that is:
- my $sub = eval "package $target; sub { shift->import(\@_) }";
+ use Module::Runtime;
+ my $sub = eval "package $target; sub { use_module(shift)->import(\@_) }";
$sub->($thing, @import_args);
which means that import is called from the right place for pragmas to take
the filename when called in the importer. The filename and line number to use
in the directive then need to be fetched using C<caller>:
- my ($terget, $file, $line) = caller(1);
+ my ($target, $file, $line) = caller(1);
my $sub = eval qq{
package $target;
#line $line "$file"
- sub { shift->import(\@_) }
+ sub { use_module(shift)->import(\@_) }
};
$sub->($thing, @import_args);
+And you need to switch between these implementations depending on if you are
+targeting a specific package, or something in your call stack.
+
Remembering all this, however, is excessively irritating. So I wrote a module
so I didn't have to anymore. Loading L<Import::Into> creates a global method
C<import::into> which you can call on any package to import it into another
L<http://shadow.cat/blog/matt-s-trout/madness-with-methods> which covers
coderef abuse and the C<${\...}> syntax.
-Final note: You do still need to ensure that you already loaded C<$thing> - if
-you're receiving this from a parameter, I recommend using L<Module::Runtime>:
-
- use Import::Into;
- use Module::Runtime qw(use_module);
+And that's it.
- use_module($thing)->import::into($target, @import_args);
+=head1 SEE ALSO
-And that's it.
+I gave a lightning talk on this module (and L<curry> and L<Safe::Isa>) at
+L<YAPC::NA 2013|https://www.youtube.com/watch?v=wFXWV2yY7gE&t=46m05s>.
=head1 ACKNOWLEDGEMENTS
haarg - Graham Knop (cpan:HAARG) <haarg@haarg.org>
+Mithaldu - Christian Walde (cpan:MITHALDU) <walde.christian@gmail.com>
+
=head1 COPYRIGHT
Copyright (c) 2012 the Import::Into L</AUTHOR> and L</CONTRIBUTORS>
This library is free software and may be distributed under the same terms
as perl itself.
+
+=cut