1 package Moose::Exporter;
11 $Moose::Exporter::{VERSION} ? ${ $Moose::Exporter::{VERSION} } : ()
16 use List::MoreUtils qw( first_index uniq );
17 use Moose::Util::MetaRole;
18 use Scalar::Util qw(reftype);
19 use Sub::Exporter 0.980;
20 use Sub::Name qw(subname);
24 sub setup_import_methods {
25 my ( $class, %args ) = @_;
27 my $exporting_package = $args{exporting_package} ||= caller();
29 $class->build_import_methods(
31 install => [qw(import unimport init_meta)]
35 sub build_import_methods {
36 my ( $class, %args ) = @_;
38 my $exporting_package = $args{exporting_package} ||= caller();
40 $EXPORT_SPEC{$exporting_package} = \%args;
42 my @exports_from = $class->_follow_also($exporting_package);
44 my $export_recorder = {};
47 my $exports = $class->_make_sub_exporter_params(
48 [ @exports_from, $exporting_package ],
53 my $exporter = $class->_make_exporter($exports, $is_reexport);
56 $methods{import} = $class->_make_import_sub(
63 $methods{unimport} = $class->_make_unimport_sub(
70 $methods{init_meta} = $class->_make_init_meta(
75 my $package = Class::MOP::Package->initialize($exporting_package);
76 for my $to_install ( @{ $args{install} || [] } ) {
77 my $symbol = '&' . $to_install;
79 unless $methods{$to_install}
80 && !$package->has_package_symbol($symbol);
81 $package->add_package_symbol( $symbol, $methods{$to_install} );
84 return ( $methods{import}, $methods{unimport}, $methods{init_meta} );
88 my ($class, $exports, $is_reexport) = @_;
90 return Sub::Exporter::build_exporter(
93 groups => { default => [':all'] },
95 my ($arg, $to_export) = @_;
96 my $meta = Class::MOP::class_of($arg->{into});
98 goto &Sub::Exporter::default_installer unless $meta;
100 # don't overwrite existing symbols with our magically flagged
101 # version of it if we would install the same sub that's already
104 my @filtered_to_export;
106 for (my $i = 0; $i < @{ $to_export }; $i += 2) {
107 my ($as, $cv) = @{ $to_export }[$i, $i + 1];
110 && $meta->has_package_symbol('&' . $as)
111 && $meta->get_package_symbol('&' . $as) == $cv;
113 push @filtered_to_export, $as, $cv;
114 $installed{$as} = 1 unless ref $as;
117 Sub::Exporter::default_installer($arg, \@filtered_to_export);
119 for my $name ( keys %{$is_reexport} ) {
122 next unless exists $installed{$name};
123 _flag_as_reexport( \*{ join q{::}, $arg->{into}, $name } );
135 my $exporting_package = shift;
137 local %$seen = ( $exporting_package => 1 );
139 return uniq( _follow_also_real($exporting_package) );
142 sub _follow_also_real {
143 my $exporting_package = shift;
145 if ( !exists $EXPORT_SPEC{$exporting_package} ) {
146 my $loaded = Class::MOP::is_class_loaded($exporting_package);
148 die "Package in also ($exporting_package) does not seem to "
149 . "use Moose::Exporter"
150 . ( $loaded ? "" : " (is it loaded?)" );
153 my $also = $EXPORT_SPEC{$exporting_package}{also};
155 return unless defined $also;
157 my @also = ref $also ? @{$also} : $also;
159 for my $package (@also) {
161 "Circular reference in 'also' parameter to Moose::Exporter between $exporting_package and $package"
162 if $seen->{$package};
164 $seen->{$package} = 1;
167 return @also, map { _follow_also_real($_) } @also;
171 sub _parse_trait_aliases {
173 my ($package, $aliases) = @_;
176 for my $alias (@$aliases) {
179 reftype($alias) eq 'ARRAY'
180 or Moose->throw_error(reftype($alias) . " references are not "
181 . "valid arguments to the 'trait_aliases' "
184 ($alias, $name) = @$alias;
187 ($name = $alias) =~ s/.*:://;
189 push @ret, subname "${package}::${name}" => sub () { $alias };
195 sub _make_sub_exporter_params {
197 my $packages = shift;
198 my $export_recorder = shift;
199 my $is_reexport = shift;
203 for my $package ( @{$packages} ) {
204 my $args = $EXPORT_SPEC{$package}
205 or die "The $package package does not use Moose::Exporter\n";
207 for my $name ( @{ $args->{with_meta} } ) {
208 my $sub = $class->_sub_from_package( $package, $name )
211 my $fq_name = $package . '::' . $name;
213 $exports{$name} = $class->_make_wrapped_sub_with_meta(
220 for my $name ( @{ $args->{with_caller} } ) {
221 my $sub = $class->_sub_from_package( $package, $name )
224 my $fq_name = $package . '::' . $name;
226 $exports{$name} = $class->_make_wrapped_sub(
233 my @extra_exports = $class->_parse_trait_aliases(
234 $package, $args->{trait_aliases},
236 for my $name ( @{ $args->{as_is} }, @extra_exports ) {
237 my ( $sub, $coderef_name );
243 ( $coderef_pkg, $coderef_name )
244 = Class::MOP::get_code_info($name);
246 if ( $coderef_pkg ne $package ) {
247 $is_reexport->{$coderef_name} = 1;
251 $sub = $class->_sub_from_package( $package, $name )
254 $coderef_name = $name;
257 $export_recorder->{$sub} = 1;
259 $exports{$coderef_name} = sub {$sub};
266 sub _sub_from_package {
273 \&{ $package . '::' . $name };
276 return $sub if defined &$sub;
278 Carp::cluck "Trying to export undefined sub ${package}::${name}";
285 sub _make_wrapped_sub {
289 my $export_recorder = shift;
291 # We need to set the package at import time, so that when
292 # package Foo imports has(), we capture "Foo" as the
293 # package. This lets other packages call Foo::has() and get
294 # the right package. This is done for backwards compatibility
295 # with existing production code, not because this is a good
298 my $caller = $CALLER;
300 my $wrapper = $self->_curry_wrapper( $sub, $fq_name, $caller );
302 my $sub = subname( $fq_name => $wrapper );
304 $export_recorder->{$sub} = 1;
310 sub _make_wrapped_sub_with_meta {
314 my $export_recorder = shift;
317 my $caller = $CALLER;
319 my $wrapper = $self->_late_curry_wrapper(
321 sub { Class::MOP::class_of(shift) } => $caller
324 my $sub = subname( $fq_name => $wrapper );
326 $export_recorder->{$sub} = 1;
338 my $wrapper = sub { $sub->( @extra, @_ ) };
339 if ( my $proto = prototype $sub ) {
341 # XXX - Perl's prototype sucks. Use & to make set_prototype
342 # ignore the fact that we're passing "private variables"
343 &Scalar::Util::set_prototype( $wrapper, $proto );
348 sub _late_curry_wrapper {
357 # resolve curried arguments at runtime via this closure
358 my @curry = ( $extra->(@ex_args) );
359 return $sub->( @curry, @_ );
362 if ( my $proto = prototype $sub ) {
364 # XXX - Perl's prototype sucks. Use & to make set_prototype
365 # ignore the fact that we're passing "private variables"
366 &Scalar::Util::set_prototype( $wrapper, $proto );
371 sub _make_import_sub {
373 my $exporting_package = shift;
374 my $exporter = shift;
375 my $exports_from = shift;
376 my $is_reexport = shift;
380 # I think we could use Sub::Exporter's collector feature
381 # to do this, but that would be rather gross, since that
382 # feature isn't really designed to return a value to the
383 # caller of the exporter sub.
385 # Also, this makes sure we preserve backwards compat for
386 # _get_caller, so it always sees the arguments in the
389 ( $traits, @_ ) = _strip_traits(@_);
392 ( $metaclass, @_ ) = _strip_metaclass(@_);
394 = Moose::Util::resolve_metaclass_alias( 'Class' => $metaclass )
395 if defined $metaclass && length $metaclass;
398 ( $meta_name, @_ ) = _strip_meta_name(@_);
400 # Normally we could look at $_[0], but in some weird cases
401 # (involving goto &Moose::import), $_[0] ends as something
402 # else (like Squirrel).
403 my $class = $exporting_package;
405 $CALLER = _get_caller(@_);
407 # this works because both pragmas set $^H (see perldoc
408 # perlvar) which affects the current compilation -
409 # i.e. the file who use'd us - which is why we don't need
410 # to do anything special to make it affect that file
411 # rather than this one (which is already compiled)
417 for my $c ( grep { $_->can('init_meta') } $class, @{$exports_from} ) {
419 # init_meta can apply a role, which when loaded uses
420 # Moose::Exporter, which in turn sets $CALLER, so we need
421 # to protect against that.
422 local $CALLER = $CALLER;
424 for_class => $CALLER,
425 metaclass => $metaclass,
426 meta_name => $meta_name,
431 if ( $did_init_meta && @{$traits} ) {
433 # The traits will use Moose::Role, which in turn uses
434 # Moose::Exporter, which in turn sets $CALLER, so we need
435 # to protect against that.
436 local $CALLER = $CALLER;
437 _apply_meta_traits( $CALLER, $traits );
439 elsif ( @{$traits} ) {
442 "Cannot provide traits when $class does not have an init_meta() method"
446 my ( undef, @args ) = @_;
447 my $extra = shift @args if ref $args[0] eq 'HASH';
450 if ( !$extra->{into} ) {
451 $extra->{into_level} ||= 0;
452 $extra->{into_level}++;
455 $class->$exporter( $extra, @args );
460 my $idx = first_index { ( $_ || '' ) eq '-traits' } @_;
462 return ( [], @_ ) unless $idx >= 0 && $#_ >= $idx + 1;
464 my $traits = $_[ $idx + 1 ];
468 $traits = [$traits] unless ref $traits;
470 return ( $traits, @_ );
473 sub _strip_metaclass {
474 my $idx = first_index { ( $_ || '' ) eq '-metaclass' } @_;
476 return ( undef, @_ ) unless $idx >= 0 && $#_ >= $idx + 1;
478 my $metaclass = $_[ $idx + 1 ];
482 return ( $metaclass, @_ );
485 sub _strip_meta_name {
486 my $idx = first_index { ( $_ || '' ) eq '-meta_name' } @_;
488 return ( 'meta', @_ ) unless $idx >= 0 && $#_ >= $idx + 1;
490 my $meta_name = $_[ $idx + 1 ];
494 return ( $meta_name, @_ );
497 sub _apply_meta_traits {
498 my ( $class, $traits ) = @_;
500 return unless @{$traits};
502 my $meta = Class::MOP::class_of($class);
504 my $type = ( split /::/, ref $meta )[-1]
505 or Moose->throw_error(
506 'Cannot determine metaclass type for trait application . Meta isa '
509 my @resolved_traits = map {
512 : Moose::Util::resolve_metatrait_alias( $type => $_ )
515 return unless @resolved_traits;
517 my %args = ( for => $class );
519 if ( $meta->isa('Moose::Meta::Role') ) {
520 $args{role_metaroles} = { role => \@resolved_traits };
523 $args{class_metaroles} = { class => \@resolved_traits };
526 Moose::Util::MetaRole::apply_metaroles(%args);
531 # 1 extra level because it's called by import so there's a layer
536 ( ref $_[1] && defined $_[1]->{into} ) ? $_[1]->{into}
537 : ( ref $_[1] && defined $_[1]->{into_level} )
538 ? caller( $offset + $_[1]->{into_level} )
542 sub _make_unimport_sub {
544 my $exporting_package = shift;
546 my $export_recorder = shift;
547 my $is_reexport = shift;
550 my $caller = scalar caller();
551 Moose::Exporter->_remove_keywords(
553 [ keys %{$exports} ],
560 sub _remove_keywords {
563 my $keywords = shift;
564 my $recorded_exports = shift;
565 my $is_reexport = shift;
569 foreach my $name ( @{$keywords} ) {
570 if ( defined &{ $package . '::' . $name } ) {
571 my $sub = \&{ $package . '::' . $name };
573 # make sure it is from us
574 next unless $recorded_exports->{$sub};
576 if ( $is_reexport->{$name} ) {
579 unless _export_is_flagged(
580 \*{ join q{::} => $package, $name } );
583 # and if it is from us, then undef the slot
584 delete ${ $package . '::' }{$name};
589 sub _make_init_meta {
601 wrapped_method_metaclass
608 $old_style_roles{$role} = $args->{$role}
609 if exists $args->{$role};
612 my %base_class_roles;
613 %base_class_roles = ( roles => $args->{base_class_roles} )
614 if exists $args->{base_class_roles};
616 my %new_style_roles = map { $_ => $args->{$_} }
617 grep { exists $args->{$_} } qw( class_metaroles role_metaroles );
619 return unless %new_style_roles || %old_style_roles || %base_class_roles;
625 return unless Class::MOP::class_of( $options{for_class} );
627 if ( %new_style_roles || %old_style_roles ) {
628 Moose::Util::MetaRole::apply_metaroles(
629 for => $options{for_class},
635 Moose::Util::MetaRole::apply_base_class_roles(
636 for_class => $options{for_class},
639 if Class::MOP::class_of( $options{for_class} )
640 ->isa('Moose::Meta::Class');
642 return Class::MOP::class_of( $options{for_class} );
653 # ABSTRACT: make an import() and unimport() just like Moose.pm
659 package MyApp::Moose;
664 Moose::Exporter->setup_import_methods(
665 with_meta => [ 'has_rw', 'sugar2' ],
666 as_is => [ 'sugar3', \&Some::Random::thing ],
671 my ( $meta, $name, %options ) = @_;
672 $meta->add_attribute(
692 This module encapsulates the exporting of sugar functions in a
693 C<Moose.pm>-like manner. It does this by building custom C<import>,
694 C<unimport>, and C<init_meta> methods for your module, based on a spec you
697 It also lets you "stack" Moose-alike modules so you can export Moose's sugar
698 as well as your own, along with sugar from any random C<MooseX> module, as
699 long as they all use C<Moose::Exporter>. This feature exists to let you bundle
700 a set of MooseX modules into a policy module that developers can use directly
701 instead of using Moose itself.
703 To simplify writing exporter modules, C<Moose::Exporter> also imports
704 C<strict> and C<warnings> into your exporter module, as well as into
709 This module provides two public methods:
713 =item B<< Moose::Exporter->setup_import_methods(...) >>
715 When you call this method, C<Moose::Exporter> builds custom C<import>,
716 C<unimport>, and C<init_meta> methods for your module. The C<import> method
717 will export the functions you specify, and can also re-export functions
718 exported by some other module (like C<Moose.pm>).
720 The C<unimport> method cleans the caller's namespace of all the exported
721 functions. This includes any functions you re-export from other
722 packages. However, if the consumer of your package also imports those
723 functions from the original package, they will I<not> be cleaned.
725 If you pass any parameters for L<Moose::Util::MetaRole>, this method will
726 generate an C<init_meta> for you as well (see below for details). This
727 C<init_meta> will call C<Moose::Util::MetaRole::apply_metaroles> and
728 C<Moose::Util::MetaRole::apply_base_class_roles> as needed.
730 Note that if any of these methods already exist, they will not be
731 overridden, you will have to use C<build_import_methods> to get the
732 coderef that would be installed.
734 This method accepts the following parameters:
738 =item * with_meta => [ ... ]
740 This list of function I<names only> will be wrapped and then exported. The
741 wrapper will pass the metaclass object for the caller as its first argument.
743 Many sugar functions will need to use this metaclass object to do something to
746 =item * as_is => [ ... ]
748 This list of function names or sub references will be exported as-is. You can
749 identify a subroutine by reference, which is handy to re-export some other
750 module's functions directly by reference (C<\&Some::Package::function>).
752 If you do export some other package's function, this function will never be
753 removed by the C<unimport> method. The reason for this is we cannot know if
754 the caller I<also> explicitly imported the sub themselves, and therefore wants
757 =item * trait_aliases => [ ... ]
759 This is a list of package names which should have shortened aliases exported,
760 similar to the functionality of L<aliased>. Each element in the list can be
761 either a package name, in which case the export will be named as the last
762 namespace component of the package, or an arrayref, whose first element is the
763 package to alias to, and second element is the alias to export.
765 =item * also => $name or \@names
767 This is a list of modules which contain functions that the caller
768 wants to export. These modules must also use C<Moose::Exporter>. The
769 most common use case will be to export the functions from C<Moose.pm>.
770 Functions specified by C<with_meta> or C<as_is> take precedence over
771 functions exported by modules specified by C<also>, so that a module
772 can selectively override functions exported by another module.
774 C<Moose::Exporter> also makes sure all these functions get removed
775 when C<unimport> is called.
779 You can also provide parameters for C<Moose::Util::MetaRole::apply_metaroles>
780 and C<Moose::Util::MetaRole::base_class_roles>. Specifically, valid parameters
781 are "class_metaroles", "role_metaroles", and "base_class_roles".
783 =item B<< Moose::Exporter->build_import_methods(...) >>
785 Returns two or three code refs, one for C<import>, one for
786 C<unimport>, and optionally one for C<init_meta>, if the appropriate
787 options are passed in.
789 Accepts the additional C<install> option, which accepts an arrayref of method
790 names to install into your exporting package. The valid options are C<import>,
791 C<unimport>, and C<init_meta>. Calling C<setup_import_methods> is equivalent
792 to calling C<build_import_methods> with C<< install => [qw(import unimport
793 init_meta)] >> except that it doesn't also return the methods.
795 Used by C<setup_import_methods>.
799 =head1 IMPORTING AND init_meta
801 If you want to set an alternative base object class or metaclass class, see
802 above for details on how this module can call L<Moose::Util::MetaRole> for
805 If you want to do something that is not supported by this module, simply
806 define an C<init_meta> method in your class. The C<import> method that
807 C<Moose::Exporter> generates for you will call this method (if it exists). It
808 will always pass the caller to this method via the C<for_class> parameter.
810 Most of the time, your C<init_meta> method will probably just call C<<
811 Moose->init_meta >> to do the real work:
814 shift; # our class name
815 return Moose->init_meta( @_, metaclass => 'My::Metaclass' );
818 Keep in mind that C<build_import_methods> will return an C<init_meta>
819 method for you, which you can also call from within your custom
822 my ( $import, $unimport, $init_meta ) =
823 Moose::Exporter->build_import_methods( ... );
830 $class->$import(...);
835 sub unimport { goto &$unimport }
842 $class->$init_meta(...);
847 =head1 METACLASS TRAITS
849 The C<import> method generated by C<Moose::Exporter> will allow the
850 user of your module to specify metaclass traits in a C<-traits>
851 parameter passed as part of the import:
853 use Moose -traits => 'My::Meta::Trait';
855 use Moose -traits => [ 'My::Meta::Trait', 'My::Other::Trait' ];
857 These traits will be applied to the caller's metaclass
858 instance. Providing traits for an exporting class that does not create
859 a metaclass for the caller is an error.
863 See L<Moose/BUGS> for details on reporting bugs.