1 package Moose::Exporter;
7 our $XS_VERSION = $VERSION;
8 $VERSION = eval $VERSION;
9 our $AUTHORITY = 'cpan:STEVAN';
12 use List::MoreUtils qw( first_index uniq );
13 use Moose::Deprecated;
14 use Moose::Util::MetaRole;
15 use Scalar::Util qw(reftype);
16 use Sub::Exporter 0.980;
17 use Sub::Name qw(subname);
21 XSLoader::load( 'Moose', $XS_VERSION );
25 sub setup_import_methods {
26 my ( $class, %args ) = @_;
28 my $exporting_package = $args{exporting_package} ||= caller();
30 $class->build_import_methods(
32 install => [qw(import unimport init_meta)]
36 sub build_import_methods {
37 my ( $class, %args ) = @_;
39 my $exporting_package = $args{exporting_package} ||= caller();
41 $EXPORT_SPEC{$exporting_package} = \%args;
43 my @exports_from = $class->_follow_also($exporting_package);
45 my $export_recorder = {};
48 my $exports = $class->_make_sub_exporter_params(
49 [ @exports_from, $exporting_package ],
54 my $exporter = Sub::Exporter::build_exporter(
57 groups => { default => [':all'] }
62 $methods{import} = $class->_make_import_sub(
69 $methods{unimport} = $class->_make_unimport_sub(
76 $methods{init_meta} = $class->_make_init_meta(
81 my $package = Class::MOP::Package->initialize($exporting_package);
82 for my $to_install ( @{ $args{install} || [] } ) {
83 my $symbol = '&' . $to_install;
85 unless $methods{$to_install}
86 && !$package->has_package_symbol($symbol);
87 $package->add_package_symbol( $symbol, $methods{$to_install} );
90 return ( $methods{import}, $methods{unimport}, $methods{init_meta} );
98 my $exporting_package = shift;
100 local %$seen = ( $exporting_package => 1 );
102 return uniq( _follow_also_real($exporting_package) );
105 sub _follow_also_real {
106 my $exporting_package = shift;
108 if ( !exists $EXPORT_SPEC{$exporting_package} ) {
109 my $loaded = Class::MOP::is_class_loaded($exporting_package);
111 die "Package in also ($exporting_package) does not seem to "
112 . "use Moose::Exporter"
113 . ( $loaded ? "" : " (is it loaded?)" );
116 my $also = $EXPORT_SPEC{$exporting_package}{also};
118 return unless defined $also;
120 my @also = ref $also ? @{$also} : $also;
122 for my $package (@also) {
124 "Circular reference in 'also' parameter to Moose::Exporter between $exporting_package and $package"
125 if $seen->{$package};
127 $seen->{$package} = 1;
130 return @also, map { _follow_also_real($_) } @also;
134 sub _parse_trait_aliases {
136 my ($package, $aliases) = @_;
139 for my $alias (@$aliases) {
142 reftype($alias) eq 'ARRAY'
143 or Moose->throw_error(reftype($alias) . " references are not "
144 . "valid arguments to the 'trait_aliases' "
147 ($alias, $name) = @$alias;
150 ($name = $alias) =~ s/.*:://;
152 push @ret, subname "${package}::${name}" => sub () { $alias };
158 sub _make_sub_exporter_params {
160 my $packages = shift;
161 my $export_recorder = shift;
162 my $is_reexport = shift;
166 for my $package ( @{$packages} ) {
167 my $args = $EXPORT_SPEC{$package}
168 or die "The $package package does not use Moose::Exporter\n";
170 for my $name ( @{ $args->{with_meta} } ) {
171 my $sub = $class->_sub_from_package( $package, $name )
174 my $fq_name = $package . '::' . $name;
176 $exports{$name} = $class->_make_wrapped_sub_with_meta(
183 for my $name ( @{ $args->{with_caller} } ) {
184 my $sub = $class->_sub_from_package( $package, $name )
187 my $fq_name = $package . '::' . $name;
189 $exports{$name} = $class->_make_wrapped_sub(
196 my @extra_exports = $class->_parse_trait_aliases(
197 $package, $args->{trait_aliases},
199 for my $name ( @{ $args->{as_is} }, @extra_exports ) {
200 my ( $sub, $coderef_name );
206 ( $coderef_pkg, $coderef_name )
207 = Class::MOP::get_code_info($name);
209 if ( $coderef_pkg ne $package ) {
210 $is_reexport->{$coderef_name} = 1;
214 $sub = $class->_sub_from_package( $package, $name )
217 $coderef_name = $name;
220 $export_recorder->{$sub} = 1;
222 $exports{$coderef_name} = sub {$sub};
229 sub _sub_from_package {
236 \&{ $package . '::' . $name };
239 return $sub if defined &$sub;
241 Carp::cluck "Trying to export undefined sub ${package}::${name}";
248 sub _make_wrapped_sub {
252 my $export_recorder = shift;
254 # We need to set the package at import time, so that when
255 # package Foo imports has(), we capture "Foo" as the
256 # package. This lets other packages call Foo::has() and get
257 # the right package. This is done for backwards compatibility
258 # with existing production code, not because this is a good
261 my $caller = $CALLER;
263 my $wrapper = $self->_curry_wrapper( $sub, $fq_name, $caller );
265 my $sub = subname( $fq_name => $wrapper );
267 $export_recorder->{$sub} = 1;
273 sub _make_wrapped_sub_with_meta {
277 my $export_recorder = shift;
280 my $caller = $CALLER;
282 my $wrapper = $self->_late_curry_wrapper(
284 sub { Class::MOP::class_of(shift) } => $caller
287 my $sub = subname( $fq_name => $wrapper );
289 $export_recorder->{$sub} = 1;
301 my $wrapper = sub { $sub->( @extra, @_ ) };
302 if ( my $proto = prototype $sub ) {
304 # XXX - Perl's prototype sucks. Use & to make set_prototype
305 # ignore the fact that we're passing "private variables"
306 &Scalar::Util::set_prototype( $wrapper, $proto );
311 sub _late_curry_wrapper {
320 # resolve curried arguments at runtime via this closure
321 my @curry = ( $extra->(@ex_args) );
322 return $sub->( @curry, @_ );
325 if ( my $proto = prototype $sub ) {
327 # XXX - Perl's prototype sucks. Use & to make set_prototype
328 # ignore the fact that we're passing "private variables"
329 &Scalar::Util::set_prototype( $wrapper, $proto );
334 sub _make_import_sub {
336 my $exporting_package = shift;
337 my $exporter = shift;
338 my $exports_from = shift;
339 my $is_reexport = shift;
343 # I think we could use Sub::Exporter's collector feature
344 # to do this, but that would be rather gross, since that
345 # feature isn't really designed to return a value to the
346 # caller of the exporter sub.
348 # Also, this makes sure we preserve backwards compat for
349 # _get_caller, so it always sees the arguments in the
352 ( $traits, @_ ) = _strip_traits(@_);
355 ( $metaclass, @_ ) = _strip_metaclass(@_);
357 = Moose::Util::resolve_metaclass_alias( 'Class' => $metaclass )
358 if defined $metaclass && length $metaclass;
361 ( $no_meta, @_ ) = _strip_no_meta(@_);
363 # Normally we could look at $_[0], but in some weird cases
364 # (involving goto &Moose::import), $_[0] ends as something
365 # else (like Squirrel).
366 my $class = $exporting_package;
368 $CALLER = _get_caller(@_);
370 # this works because both pragmas set $^H (see perldoc
371 # perlvar) which affects the current compilation -
372 # i.e. the file who use'd us - which is why we don't need
373 # to do anything special to make it affect that file
374 # rather than this one (which is already compiled)
380 for my $c ( grep { $_->can('init_meta') } $class, @{$exports_from} ) {
382 # init_meta can apply a role, which when loaded uses
383 # Moose::Exporter, which in turn sets $CALLER, so we need
384 # to protect against that.
385 local $CALLER = $CALLER;
387 for_class => $CALLER,
388 metaclass => $metaclass,
394 if ( $did_init_meta && @{$traits} ) {
396 # The traits will use Moose::Role, which in turn uses
397 # Moose::Exporter, which in turn sets $CALLER, so we need
398 # to protect against that.
399 local $CALLER = $CALLER;
400 _apply_meta_traits( $CALLER, $traits );
402 elsif ( @{$traits} ) {
405 "Cannot provide traits when $class does not have an init_meta() method"
409 my ( undef, @args ) = @_;
410 my $extra = shift @args if ref $args[0] eq 'HASH';
413 if ( !$extra->{into} ) {
414 $extra->{into_level} ||= 0;
415 $extra->{into_level}++;
418 $class->$exporter( $extra, @args );
420 for my $name ( keys %{$is_reexport} ) {
423 _flag_as_reexport( \*{ join q{::}, $CALLER, $name } );
429 my $idx = first_index { $_ eq '-traits' } @_;
431 return ( [], @_ ) unless $idx >= 0 && $#_ >= $idx + 1;
433 my $traits = $_[ $idx + 1 ];
437 $traits = [$traits] unless ref $traits;
439 return ( $traits, @_ );
442 sub _strip_metaclass {
443 my $idx = first_index { $_ eq '-metaclass' } @_;
445 return ( undef, @_ ) unless $idx >= 0 && $#_ >= $idx + 1;
447 my $metaclass = $_[ $idx + 1 ];
451 return ( $metaclass, @_ );
455 my $idx = first_index { $_ eq '-no_meta' } @_;
457 return ( undef, @_ ) unless $idx >= 0 && $#_ >= $idx + 1;
459 my $no_meta = $_[ $idx + 1 ];
463 return ( $no_meta, @_ );
466 sub _apply_meta_traits {
467 my ( $class, $traits ) = @_;
469 return unless @{$traits};
471 my $meta = Class::MOP::class_of($class);
473 my $type = ( split /::/, ref $meta )[-1]
474 or Moose->throw_error(
475 'Cannot determine metaclass type for trait application . Meta isa '
478 my @resolved_traits = map {
481 : Moose::Util::resolve_metatrait_alias( $type => $_ )
484 return unless @resolved_traits;
486 my %args = ( for => $class );
488 if ( $meta->isa('Moose::Meta::Role') ) {
489 $args{role_metaroles} = { role => \@resolved_traits };
492 $args{class_metaroles} = { class => \@resolved_traits };
495 Moose::Util::MetaRole::apply_metaroles(%args);
500 # 1 extra level because it's called by import so there's a layer
505 ( ref $_[1] && defined $_[1]->{into} ) ? $_[1]->{into}
506 : ( ref $_[1] && defined $_[1]->{into_level} )
507 ? caller( $offset + $_[1]->{into_level} )
511 sub _make_unimport_sub {
513 my $exporting_package = shift;
515 my $export_recorder = shift;
516 my $is_reexport = shift;
519 my $caller = scalar caller();
520 Moose::Exporter->_remove_keywords(
522 [ keys %{$exports} ],
529 sub _remove_keywords {
532 my $keywords = shift;
533 my $recorded_exports = shift;
534 my $is_reexport = shift;
538 foreach my $name ( @{$keywords} ) {
539 if ( defined &{ $package . '::' . $name } ) {
540 my $sub = \&{ $package . '::' . $name };
542 # make sure it is from us
543 next unless $recorded_exports->{$sub};
545 if ( $is_reexport->{$name} ) {
548 unless _export_is_flagged(
549 \*{ join q{::} => $package, $name } );
552 # and if it is from us, then undef the slot
553 delete ${ $package . '::' }{$name};
558 sub _make_init_meta {
570 wrapped_method_metaclass
577 $old_style_roles{$role} = $args->{$role}
578 if exists $args->{$role};
581 my %base_class_roles;
582 %base_class_roles = ( roles => $args->{base_class_roles} )
583 if exists $args->{base_class_roles};
585 my %new_style_roles = map { $_ => $args->{$_} }
586 grep { exists $args->{$_} } qw( class_metaroles role_metaroles );
588 return unless %new_style_roles || %old_style_roles || %base_class_roles;
594 return unless Class::MOP::class_of( $options{for_class} );
596 if ( %new_style_roles || %old_style_roles ) {
597 Moose::Util::MetaRole::apply_metaroles(
598 for => $options{for_class},
604 Moose::Util::MetaRole::apply_base_class_roles(
605 for_class => $options{for_class},
608 if Class::MOP::class_of( $options{for_class} )
609 ->isa('Moose::Meta::Class');
611 return Class::MOP::class_of( $options{for_class} );
626 Moose::Exporter - make an import() and unimport() just like Moose.pm
630 package MyApp::Moose;
635 Moose::Exporter->setup_import_methods(
636 with_meta => [ 'has_rw', 'sugar2' ],
637 as_is => [ 'sugar3', \&Some::Random::thing ],
642 my ( $meta, $name, %options ) = @_;
643 $meta->add_attribute(
663 This module encapsulates the exporting of sugar functions in a
664 C<Moose.pm>-like manner. It does this by building custom C<import>,
665 C<unimport>, and C<init_meta> methods for your module, based on a spec you
668 It also lets you "stack" Moose-alike modules so you can export Moose's sugar
669 as well as your own, along with sugar from any random C<MooseX> module, as
670 long as they all use C<Moose::Exporter>. This feature exists to let you bundle
671 a set of MooseX modules into a policy module that developers can use directly
672 instead of using Moose itself.
674 To simplify writing exporter modules, C<Moose::Exporter> also imports
675 C<strict> and C<warnings> into your exporter module, as well as into
680 This module provides two public methods:
684 =item B<< Moose::Exporter->setup_import_methods(...) >>
686 When you call this method, C<Moose::Exporter> builds custom C<import>,
687 C<unimport>, and C<init_meta> methods for your module. The C<import> method
688 will export the functions you specify, and can also re-export functions
689 exported by some other module (like C<Moose.pm>).
691 The C<unimport> method cleans the caller's namespace of all the exported
692 functions. This includes any functions you re-export from other
693 packages. However, if the consumer of your package also imports those
694 functions from the original package, they will I<not> be cleaned.
696 If you pass any parameters for L<Moose::Util::MetaRole>, this method will
697 generate an C<init_meta> for you as well (see below for details). This
698 C<init_meta> will call C<Moose::Util::MetaRole::apply_metaroles> and
699 C<Moose::Util::MetaRole::apply_base_class_roles> as needed.
701 Note that if any of these methods already exist, they will not be
702 overridden, you will have to use C<build_import_methods> to get the
703 coderef that would be installed.
705 This method accepts the following parameters:
709 =item * with_meta => [ ... ]
711 This list of function I<names only> will be wrapped and then exported. The
712 wrapper will pass the metaclass object for the caller as its first argument.
714 Many sugar functions will need to use this metaclass object to do something to
717 =item * as_is => [ ... ]
719 This list of function names or sub references will be exported as-is. You can
720 identify a subroutine by reference, which is handy to re-export some other
721 module's functions directly by reference (C<\&Some::Package::function>).
723 If you do export some other package's function, this function will never be
724 removed by the C<unimport> method. The reason for this is we cannot know if
725 the caller I<also> explicitly imported the sub themselves, and therefore wants
728 =item * trait_aliases => [ ... ]
730 This is a list of package names which should have shortened alias exported,
731 similar to the functionality of L<aliased>. Each element in the list can be
732 either a package name, in which case the export will be named as the last
733 namespace component of the package, or an arrayref, whose first element is the
734 package to alias to, and second element is the alias to export.
736 =item * also => $name or \@names
738 This is a list of modules which contain functions that the caller
739 wants to export. These modules must also use C<Moose::Exporter>. The
740 most common use case will be to export the functions from C<Moose.pm>.
741 Functions specified by C<with_meta> or C<as_is> take precedence over
742 functions exported by modules specified by C<also>, so that a module
743 can selectively override functions exported by another module.
745 C<Moose::Exporter> also makes sure all these functions get removed
746 when C<unimport> is called.
750 You can also provide parameters for C<Moose::Util::MetaRole::apply_metaroles>
751 and C<Moose::Util::MetaRole::base_class_roles>. Specifically, valid parameters
752 are "class_metaroles", "role_metaroles", and "base_class_roles".
754 =item B<< Moose::Exporter->build_import_methods(...) >>
756 Returns two or three code refs, one for C<import>, one for
757 C<unimport>, and optionally one for C<init_meta>, if the appropriate
758 options are passed in.
760 Accepts the additional C<install> option, which accepts an arrayref of method
761 names to install into your exporting package. The valid options are C<import>,
762 C<unimport>, and C<init_meta>. Calling C<setup_import_methods> is equivalent
763 to calling C<build_import_methods> with C<< install => [qw(import unimport
764 init_meta)] >> except that it doesn't also return the methods.
766 Used by C<setup_import_methods>.
770 =head1 IMPORTING AND init_meta
772 If you want to set an alternative base object class or metaclass class, see
773 above for details on how this module can call L<Moose::Util::MetaRole> for
776 If you want to do something that is not supported by this module, simply
777 define an C<init_meta> method in your class. The C<import> method that
778 C<Moose::Exporter> generates for you will call this method (if it exists). It
779 will always pass the caller to this method via the C<for_class> parameter.
781 Most of the time, your C<init_meta> method will probably just call C<<
782 Moose->init_meta >> to do the real work:
785 shift; # our class name
786 return Moose->init_meta( @_, metaclass => 'My::Metaclass' );
789 Keep in mind that C<build_import_methods> will return an C<init_meta>
790 method for you, which you can also call from within your custom
793 my ( $import, $unimport, $init_meta ) =
794 Moose::Exporter->build_import_methods( ... );
801 $class->$import(...);
806 sub unimport { goto &$unimport }
813 $class->$init_meta(...);
818 =head1 METACLASS TRAITS
820 The C<import> method generated by C<Moose::Exporter> will allow the
821 user of your module to specify metaclass traits in a C<-traits>
822 parameter passed as part of the import:
824 use Moose -traits => 'My::Meta::Trait';
826 use Moose -traits => [ 'My::Meta::Trait', 'My::Other::Trait' ];
828 These traits will be applied to the caller's metaclass
829 instance. Providing traits for an exporting class that does not create
830 a metaclass for the caller is an error.
834 See L<Moose/BUGS> for details on reporting bugs.
838 Dave Rolsky E<lt>autarch@urth.orgE<gt>
840 This is largely a reworking of code in Moose.pm originally written by
841 Stevan Little and others.
843 =head1 COPYRIGHT AND LICENSE
845 Copyright 2009 by Infinity Interactive, Inc.
847 L<http://www.iinteractive.com>
849 This library is free software; you can redistribute it and/or modify
850 it under the same terms as Perl itself.