1 package Moose::Exporter;
6 use Carp qw( confess );
8 use List::MoreUtils qw( first_index uniq );
14 sub build_import_methods {
18 my $exporting_package = caller();
20 $EXPORT_SPEC{$exporting_package} = \%args;
22 my @exports_from = $class->_follow_also( $exporting_package );
25 = $class->_make_sub_exporter_params( $exporting_package, @exports_from );
27 my $exporter = Sub::Exporter::build_exporter(
30 groups => { default => [':all'] }
34 # $args{_export_to_main} exists for backwards compat, because
35 # Moose::Util::TypeConstraints did export to main (unlike Moose &
37 my $import = $class->_make_import_sub( $exporter, \@exports_from, $args{_export_to_main} );
39 my $unimport = $class->_make_unimport_sub( \@exports_from, [ keys %{$exports} ] );
42 *{ $exporting_package . '::import' } = $import;
43 *{ $exporting_package . '::unimport' } = $unimport;
51 my $exporting_package = shift;
53 %seen = ( $exporting_package => 1 );
55 return uniq( _follow_also_real($exporting_package) );
58 sub _follow_also_real {
59 my $exporting_package = shift;
61 die "Package in also ($exporting_package) does not seem to use MooseX::Exporter"
62 unless exists $EXPORT_SPEC{$exporting_package};
64 my $also = $EXPORT_SPEC{$exporting_package}{also};
66 return unless defined $also;
68 my @also = ref $also ? @{$also} : $also;
70 for my $package (@also)
72 die "Circular reference in also parameter to MooseX::Exporter between $exporting_package and $package"
78 return @also, map { _follow_also_real($_) } @also;
82 sub _make_sub_exporter_params {
88 for my $package (@packages) {
89 my $args = $EXPORT_SPEC{$package}
90 or die "The $package package does not use Moose::Exporter\n";
92 for my $name ( @{ $args->{with_caller} } ) {
95 \&{ $package . '::' . $name };
98 $exports{$name} = $class->_make_wrapped_sub(
105 for my $name ( @{ $args->{as_is} } ) {
110 $name = ( Class::MOP::get_code_info($name) )[1];
115 \&{ $package . '::' . $name };
119 $exports{$name} = sub {$sub};
127 # This variable gets closed over in each export _generator_. Then
128 # in the generator we grab the value and close over it _again_ in
129 # the real export, so it gets captured each time the generator
132 # In the meantime, we arrange for the import method we generate to
133 # set this variable to the caller each time it is called.
135 # This is all a bit confusing, but it works.
138 sub _make_wrapped_sub {
140 my $exporting_package = shift;
144 # We need to set the package at import time, so that when
145 # package Foo imports has(), we capture "Foo" as the
146 # package. This lets other packages call Foo::has() and get
147 # the right package. This is done for backwards compatibility
148 # with existing production code, not because this is a good
151 my $caller = $CALLER;
152 Class::MOP::subname( $exporting_package . '::'
153 . $name => sub { $sub->( $caller, @_ ) } );
157 sub _make_import_sub {
159 my $exporter = shift;
160 my $exports_from = shift;
161 my $export_to_main = shift;
164 # I think we could use Sub::Exporter's collector feature
165 # to do this, but that would be rather gross, since that
166 # feature isn't really designed to return a value to the
167 # caller of the exporter sub.
169 # Also, this makes sure we preserve backwards compat for
170 # _get_caller, so it always sees the arguments in the
173 ($traits, @_) = Moose::Exporter::_strip_traits(@_);
175 # It's important to leave @_ as-is for the benefit of
179 $CALLER = Moose::Exporter::_get_caller(@_);
181 # this works because both pragmas set $^H (see perldoc
182 # perlvar) which affects the current compilation -
183 # i.e. the file who use'd us - which is why we don't need
184 # to do anything special to make it affect that file
185 # rather than this one (which is already compiled)
190 # we should never export to main
191 if ( $CALLER eq 'main' && ! $export_to_main ) {
193 qq{$class does not export its sugar to the 'main' package.\n};
198 for my $c ( grep { $_->can('init_meta') } $class, @{$exports_from} ) {
200 $c->init_meta( for_class => $CALLER );
204 if ($did_init_meta) {
205 _apply_meta_traits( $CALLER, $traits );
207 elsif ( $traits && @{$traits} ) {
209 "Cannot provide traits when $class does not have an init_meta() method";
218 my $idx = first_index { $_ eq '-traits' } @_;
220 return ( undef, @_ ) unless $idx >= 0 && $#_ >= $idx + 1;
222 my $traits = $_[ $idx + 1 ];
226 $traits = [ $traits ] unless ref $traits;
228 return ( $traits, @_ );
231 sub _apply_meta_traits {
232 my ( $class, $traits ) = @_;
235 unless $traits && @$traits;
237 my $meta = $class->meta();
239 my $type = ( split /::/, ref $meta )[-1]
241 'Cannot determine metaclass type for trait application . Meta isa '
244 # We can only call does_role() on Moose::Meta::Class objects, and
245 # we can only do that on $meta->meta() if it has already had at
246 # least one trait applied to it. By default $meta->meta() returns
247 # a Class::MOP::Class object (not a Moose::Meta::Class).
249 $meta->meta()->can('does_role')
250 ? not $meta->meta()->does_role($_)
253 map { Moose::Util::resolve_metatrait_alias( $type => $_ ) } @$traits;
255 return unless @traits;
257 Moose::Util::apply_all_roles_with_method( $meta,
258 'apply_to_metaclass_instance', \@traits );
262 # 1 extra level because it's called by import so there's a layer
267 ( ref $_[1] && defined $_[1]->{into} ) ? $_[1]->{into}
268 : ( ref $_[1] && defined $_[1]->{into_level} )
269 ? caller( $offset + $_[1]->{into_level} )
273 sub _make_unimport_sub {
276 my $keywords = shift;
280 my $caller = scalar caller();
281 Moose::Exporter->_remove_keywords(
283 [ $class, @{$sources} ],
289 sub _remove_keywords {
293 my $keywords = shift;
295 my %sources = map { $_ => 1 } @{$sources};
299 # loop through the keywords ...
300 foreach my $name ( @{$keywords} ) {
303 if ( defined &{ $package . '::' . $name } ) {
304 my $keyword = \&{ $package . '::' . $name };
306 # make sure it is from us
307 my ($pkg_name) = Class::MOP::get_code_info($keyword);
308 next unless $sources{$pkg_name};
310 # and if it is from us, then undef the slot
311 delete ${ $package . '::' }{$name};
322 Moose::Exporter - make an import() and unimport() just like Moose.pm
326 package MyApp::Moose;
334 Moose::Exporter->build_export_methods(
335 export => [ 'sugar1', 'sugar2', \&Some::Random::thing ],
336 init_meta_args => { metaclass_class => 'MyApp::Meta::Class' ],
345 sugar1 'do your thing';
352 This module encapsulates the logic to export sugar functions like
353 C<Moose.pm>. It does this by building custom C<import> and C<unimport>
354 methods for your module, based on a spec your provide.
356 It also lets your "stack" Moose-alike modules so you can export
357 Moose's sugar as well as your own, along with sugar from any random
358 C<MooseX> module, as long as they all use C<Moose::Exporter>.
362 This module provides exactly one public method:
364 =head2 Moose::Exporter->build_import_methods(...)
366 When you call this method, C<Moose::Exporter> build custom C<import>
367 and C<unimport> methods for your module. The import method will export
368 the functions you specify, and you can also tell it to export
369 functions exported by some other module (like C<Moose.pm>).
371 The C<unimport> method cleans the callers namespace of all the
374 This method accepts the following parameters:
378 =item * with_caller => [ ... ]
380 This a list of function I<names only> to be exported wrapped and then
381 exported. The wrapper will pass the name of the calling package as the
382 first argument to the function. Many sugar functions need to know
383 their caller so they can get the calling package's metaclass object.
385 =item * as_is => [ ... ]
387 This a list of function names or sub references to be exported
388 as-is. You can identify a subroutine by reference, which is handy to
389 re-export some other module's functions directly by reference
390 (C<\&Some::Package::function>).
392 =item * also => $name or \@names
394 This is a list of modules which contain functions that the caller
395 wants to export. These modules must also use C<Moose::Exporter>. The
396 most common use case will be to export the functions from C<Moose.pm>.
398 C<Moose::Exporter> also makes sure all these functions get removed
399 when C<unimport> is called.
403 =head1 IMPORTING AND init_meta
405 If you want to set an alternative base object class or metaclass
406 class, simply define an C<init_meta> method in your class. The
407 C<import> method that C<Moose::Exporter> generates for you will call
408 this method (if it exists). It will always pass the caller to this
409 method via the C<for_class> parameter.
411 Most of the time, your C<init_meta> method will probably just call C<<
412 Moose->init_meta >> to do the real work:
415 shift; # our class name
416 return Moose->init_meta( @_, metaclass => 'My::Metaclass' );
419 =head1 METACLASS TRAITS
421 The C<import> method generated by C<Moose::Exporter> will allow the
422 user of your module to specify metaclass traits in a C<-traits>
423 parameter passed as part of the import:
425 use Moose -traits => 'My::Meta::Trait';
427 use Moose -traits => [ 'My::Meta::Trait', 'My::Other::Trait' ];
429 These traits will be applied to the caller's metaclass
430 instance. Providing traits for an exporting class that does not create
431 a metaclass for the caller is an error.
435 Dave Rolsky E<lt>autarch@urth.orgE<gt>
437 This is largely a reworking of code in Moose.pm originally written by
438 Stevan Little and others.
440 =head1 COPYRIGHT AND LICENSE
442 Copyright 2008 by Infinity Interactive, Inc.
444 L<http://www.iinteractive.com>
446 This library is free software; you can redistribute it and/or modify
447 it under the same terms as Perl itself.