1 package Moose::Exporter;
6 use Carp qw( confess );
8 use List::MoreUtils qw( first_index uniq );
9 use Moose::Util::MetaRole;
15 sub setup_import_methods {
16 my ( $class, %args ) = @_;
18 my $exporting_package = $args{exporting_package} ||= caller();
20 my ( $import, $unimport ) = $class->build_import_methods(%args);
23 *{ $exporting_package . '::import' } = $import;
24 *{ $exporting_package . '::unimport' } = $unimport;
27 sub build_import_methods {
28 my ( $class, %args ) = @_;
30 my $exporting_package = $args{exporting_package} ||= caller();
32 $EXPORT_SPEC{$exporting_package} = \%args;
34 my @exports_from = $class->_follow_also( $exporting_package );
37 = $class->_make_sub_exporter_params( $exporting_package, @exports_from );
39 my $exporter = Sub::Exporter::build_exporter(
42 groups => { default => [':all'] }
46 # $args{_export_to_main} exists for backwards compat, because
47 # Moose::Util::TypeConstraints did export to main (unlike Moose &
49 my $import = $class->_make_import_sub( $exporting_package, $exporter,
50 \@exports_from, $args{_export_to_main} );
53 = $class->_make_unimport_sub( $exporting_package, \@exports_from,
54 [ keys %{$exports} ] );
56 return ( $import, $unimport )
64 my $exporting_package = shift;
66 local %$seen = ( $exporting_package => 1 );
68 return uniq( _follow_also_real($exporting_package) );
71 sub _follow_also_real {
72 my $exporting_package = shift;
74 die "Package in also ($exporting_package) does not seem to use MooseX::Exporter"
75 unless exists $EXPORT_SPEC{$exporting_package};
77 my $also = $EXPORT_SPEC{$exporting_package}{also};
79 return unless defined $also;
81 my @also = ref $also ? @{$also} : $also;
83 for my $package (@also)
85 die "Circular reference in also parameter to MooseX::Exporter between $exporting_package and $package"
88 $seen->{$package} = 1;
91 return @also, map { _follow_also_real($_) } @also;
95 sub _make_sub_exporter_params {
101 for my $package (@packages) {
102 my $args = $EXPORT_SPEC{$package}
103 or die "The $package package does not use Moose::Exporter\n";
105 for my $name ( @{ $args->{with_caller} } ) {
108 \&{ $package . '::' . $name };
111 $exports{$name} = $class->_make_wrapped_sub(
118 for my $name ( @{ $args->{as_is} } ) {
123 $name = ( Class::MOP::get_code_info($name) )[1];
128 \&{ $package . '::' . $name };
132 $exports{$name} = sub {$sub};
140 # This variable gets closed over in each export _generator_. Then
141 # in the generator we grab the value and close over it _again_ in
142 # the real export, so it gets captured each time the generator
145 # In the meantime, we arrange for the import method we generate to
146 # set this variable to the caller each time it is called.
148 # This is all a bit confusing, but it works.
151 sub _make_wrapped_sub {
153 my $exporting_package = shift;
157 # We need to set the package at import time, so that when
158 # package Foo imports has(), we capture "Foo" as the
159 # package. This lets other packages call Foo::has() and get
160 # the right package. This is done for backwards compatibility
161 # with existing production code, not because this is a good
164 my $caller = $CALLER;
165 Class::MOP::subname( $exporting_package . '::'
166 . $name => sub { $sub->( $caller, @_ ) } );
170 sub _make_import_sub {
172 my $exporting_package = shift;
173 my $exporter = shift;
174 my $exports_from = shift;
175 my $export_to_main = shift;
178 # I think we could use Sub::Exporter's collector feature
179 # to do this, but that would be rather gross, since that
180 # feature isn't really designed to return a value to the
181 # caller of the exporter sub.
183 # Also, this makes sure we preserve backwards compat for
184 # _get_caller, so it always sees the arguments in the
187 ($traits, @_) = Moose::Exporter::_strip_traits(@_);
189 # Normally we could look at $_[0], but in some weird cases
190 # (involving goto &Moose::import), $_[0] ends as something
191 # else (like Squirrel).
192 my $class = $exporting_package;
194 $CALLER = Moose::Exporter::_get_caller(@_);
196 # this works because both pragmas set $^H (see perldoc
197 # perlvar) which affects the current compilation -
198 # i.e. the file who use'd us - which is why we don't need
199 # to do anything special to make it affect that file
200 # rather than this one (which is already compiled)
205 # we should never export to main
206 if ( $CALLER eq 'main' && ! $export_to_main ) {
208 qq{$class does not export its sugar to the 'main' package.\n};
213 for my $c ( grep { $_->can('init_meta') } $class, @{$exports_from} ) {
215 $c->init_meta( for_class => $CALLER );
219 if ( $did_init_meta && @{$traits} ) {
220 _apply_meta_traits( $CALLER, $traits );
222 elsif ( @{$traits} ) {
224 "Cannot provide traits when $class does not have an init_meta() method";
233 my $idx = first_index { $_ eq '-traits' } @_;
235 return ( [], @_ ) unless $idx >= 0 && $#_ >= $idx + 1;
237 my $traits = $_[ $idx + 1 ];
241 $traits = [ $traits ] unless ref $traits;
243 return ( $traits, @_ );
246 sub _apply_meta_traits {
247 my ( $class, $traits ) = @_;
249 return unless @{$traits};
251 my $meta = $class->meta();
253 my $type = ( split /::/, ref $meta )[-1]
255 'Cannot determine metaclass type for trait application . Meta isa '
259 = map { Moose::Util::resolve_metatrait_alias( $type => $_ ) }
262 return unless @resolved_traits;
264 Moose::Util::MetaRole::apply_metaclass_roles(
266 metaclass_roles => \@resolved_traits,
271 # 1 extra level because it's called by import so there's a layer
276 ( ref $_[1] && defined $_[1]->{into} ) ? $_[1]->{into}
277 : ( ref $_[1] && defined $_[1]->{into_level} )
278 ? caller( $offset + $_[1]->{into_level} )
282 sub _make_unimport_sub {
284 my $exporting_package = shift;
286 my $keywords = shift;
289 my $caller = scalar caller();
290 Moose::Exporter->_remove_keywords(
292 [ $exporting_package, @{$sources} ],
298 sub _remove_keywords {
302 my $keywords = shift;
304 my %sources = map { $_ => 1 } @{$sources};
308 # loop through the keywords ...
309 foreach my $name ( @{$keywords} ) {
312 if ( defined &{ $package . '::' . $name } ) {
313 my $keyword = \&{ $package . '::' . $name };
315 # make sure it is from us
316 my ($pkg_name) = Class::MOP::get_code_info($keyword);
317 next unless $sources{$pkg_name};
319 # and if it is from us, then undef the slot
320 delete ${ $package . '::' }{$name};
331 Moose::Exporter - make an import() and unimport() just like Moose.pm
335 package MyApp::Moose;
343 Moose::Exporter->setup_import_methods(
344 with_caller => [ 'sugar1', 'sugar2' ],
345 as_is => [ 'sugar3', \&Some::Random::thing ],
355 sugar1 'do your thing';
362 This module encapsulates the logic to export sugar functions like
363 C<Moose.pm>. It does this by building custom C<import> and C<unimport>
364 methods for your module, based on a spec your provide.
366 It also lets your "stack" Moose-alike modules so you can export
367 Moose's sugar as well as your own, along with sugar from any random
368 C<MooseX> module, as long as they all use C<Moose::Exporter>.
372 This module provides two public methods:
374 =head2 Moose::Exporter->setup_import_methods(...)
376 When you call this method, C<Moose::Exporter> build custom C<import>
377 and C<unimport> methods for your module. The import method will export
378 the functions you specify, and you can also tell it to export
379 functions exported by some other module (like C<Moose.pm>).
381 The C<unimport> method cleans the callers namespace of all the
384 This method accepts the following parameters:
388 =item * with_caller => [ ... ]
390 This a list of function I<names only> to be exported wrapped and then
391 exported. The wrapper will pass the name of the calling package as the
392 first argument to the function. Many sugar functions need to know
393 their caller so they can get the calling package's metaclass object.
395 =item * as_is => [ ... ]
397 This a list of function names or sub references to be exported
398 as-is. You can identify a subroutine by reference, which is handy to
399 re-export some other module's functions directly by reference
400 (C<\&Some::Package::function>).
402 =item * also => $name or \@names
404 This is a list of modules which contain functions that the caller
405 wants to export. These modules must also use C<Moose::Exporter>. The
406 most common use case will be to export the functions from C<Moose.pm>.
408 C<Moose::Exporter> also makes sure all these functions get removed
409 when C<unimport> is called.
413 =head2 Moose::Exporter->build_import_methods(...)
415 Returns two code refs, one for import and one for unimport.
417 Used by C<setup_import_methods>.
419 =head1 IMPORTING AND init_meta
421 If you want to set an alternative base object class or metaclass
422 class, simply define an C<init_meta> method in your class. The
423 C<import> method that C<Moose::Exporter> generates for you will call
424 this method (if it exists). It will always pass the caller to this
425 method via the C<for_class> parameter.
427 Most of the time, your C<init_meta> method will probably just call C<<
428 Moose->init_meta >> to do the real work:
431 shift; # our class name
432 return Moose->init_meta( @_, metaclass => 'My::Metaclass' );
435 =head1 METACLASS TRAITS
437 The C<import> method generated by C<Moose::Exporter> will allow the
438 user of your module to specify metaclass traits in a C<-traits>
439 parameter passed as part of the import:
441 use Moose -traits => 'My::Meta::Trait';
443 use Moose -traits => [ 'My::Meta::Trait', 'My::Other::Trait' ];
445 These traits will be applied to the caller's metaclass
446 instance. Providing traits for an exporting class that does not create
447 a metaclass for the caller is an error.
451 Dave Rolsky E<lt>autarch@urth.orgE<gt>
453 This is largely a reworking of code in Moose.pm originally written by
454 Stevan Little and others.
456 =head1 COPYRIGHT AND LICENSE
458 Copyright 2008 by Infinity Interactive, Inc.
460 L<http://www.iinteractive.com>
462 This library is free software; you can redistribute it and/or modify
463 it under the same terms as Perl itself.