1 package Moose::Exporter;
6 our $VERSION = '0.89_01';
7 $VERSION = eval $VERSION;
8 our $AUTHORITY = 'cpan:STEVAN';
11 use List::MoreUtils qw( first_index uniq );
12 use Moose::Util::MetaRole;
13 use Sub::Exporter 0.980;
14 use Sub::Name qw(subname);
18 sub setup_import_methods {
19 my ( $class, %args ) = @_;
21 my $exporting_package = $args{exporting_package} ||= caller();
23 $class->build_import_methods(
25 install => [qw(import unimport init_meta)]
29 sub build_import_methods {
30 my ( $class, %args ) = @_;
32 my $exporting_package = $args{exporting_package} ||= caller();
34 $EXPORT_SPEC{$exporting_package} = \%args;
36 my @exports_from = $class->_follow_also( $exporting_package );
38 my $export_recorder = {};
40 my ( $exports, $is_removable, $groups )
41 = $class->_make_sub_exporter_params(
42 [ @exports_from, $exporting_package ], $export_recorder );
44 my $exporter = Sub::Exporter::build_exporter(
47 groups => { default => [':all'], %$groups }
52 # $args{_export_to_main} exists for backwards compat, because
53 # Moose::Util::TypeConstraints did export to main (unlike Moose &
55 $methods{import} = $class->_make_import_sub( $exporting_package,
56 $exporter, \@exports_from, $args{_export_to_main} );
58 $methods{unimport} = $class->_make_unimport_sub( $exporting_package,
59 $exports, $is_removable, $export_recorder );
61 $methods{init_meta} = $class->_make_init_meta( $exporting_package,
64 my $package = Class::MOP::Package->initialize($exporting_package);
65 for my $to_install (@{ $args{install} || [] }) {
66 my $symbol = '&' . $to_install;
67 next unless $methods{$to_install}
68 && !$package->has_package_symbol($symbol);
69 $package->add_package_symbol($symbol, $methods{$to_install});
72 return ( $methods{import}, $methods{unimport}, $methods{init_meta} )
80 my $exporting_package = shift;
82 local %$seen = ( $exporting_package => 1 );
84 return uniq( _follow_also_real($exporting_package) );
87 sub _follow_also_real {
88 my $exporting_package = shift;
90 if (!exists $EXPORT_SPEC{$exporting_package}) {
91 my $loaded = Class::MOP::is_class_loaded($exporting_package);
93 die "Package in also ($exporting_package) does not seem to "
94 . "use Moose::Exporter"
95 . ($loaded ? "" : " (is it loaded?)");
98 my $also = $EXPORT_SPEC{$exporting_package}{also};
100 return unless defined $also;
102 my @also = ref $also ? @{$also} : $also;
104 for my $package (@also)
106 die "Circular reference in also parameter to Moose::Exporter between $exporting_package and $package"
107 if $seen->{$package};
109 $seen->{$package} = 1;
112 return @also, map { _follow_also_real($_) } @also;
116 sub _make_sub_exporter_params {
118 my $packages = shift;
119 my $export_recorder = shift;
125 for my $package ( @{$packages} ) {
126 my $args = $EXPORT_SPEC{$package}
127 or die "The $package package does not use Moose::Exporter\n";
129 # one group for each 'also' package
130 $groups{$package} = [
131 @{ $args->{with_caller} || [] },
132 @{ $args->{with_meta} || [] },
133 @{ $args->{as_is} || [] },
135 keys %{ $args->{groups} || {} }
138 for my $name ( @{ $args->{with_caller} } ) {
141 \&{ $package . '::' . $name };
144 my $fq_name = $package . '::' . $name;
146 $exports{$name} = $class->_make_wrapped_sub(
152 $is_removable{$name} = 1;
155 for my $name ( @{ $args->{with_meta} } ) {
158 \&{ $package . '::' . $name };
161 my $fq_name = $package . '::' . $name;
163 $exports{$name} = $class->_make_wrapped_sub_with_meta(
169 $is_removable{$name} = 1;
172 for my $name ( @{ $args->{as_is} } ) {
178 # Even though Moose re-exports things from Carp &
179 # Scalar::Util, we don't want to remove those at
180 # unimport time, because the importing package may
181 # have imported them explicitly ala
183 # use Carp qw( confess );
185 # This is a hack. Since we can't know whether they
186 # really want to keep these subs or not, we err on the
187 # safe side and leave them in.
189 ( $coderef_pkg, $name ) = Class::MOP::get_code_info($name);
191 $is_removable{$name} = $coderef_pkg eq $package ? 1 : 0;
196 \&{ $package . '::' . $name };
199 $is_removable{$name} = 1;
202 $export_recorder->{$sub} = 1;
204 $exports{$name} = sub {$sub};
207 for my $name ( keys %{ $args->{groups} } ) {
208 my $group = $args->{groups}{$name};
210 if (ref $group eq 'CODE') {
211 $groups{$name} = $class->_make_wrapped_group(
219 elsif (ref $group eq 'ARRAY') {
220 $groups{$name} = $group;
225 return ( \%exports, \%is_removable, \%groups );
230 sub _make_wrapped_sub {
234 my $export_recorder = shift;
236 # We need to set the package at import time, so that when
237 # package Foo imports has(), we capture "Foo" as the
238 # package. This lets other packages call Foo::has() and get
239 # the right package. This is done for backwards compatibility
240 # with existing production code, not because this is a good
243 my $caller = $CALLER;
245 my $wrapper = $self->_curry_wrapper($sub, $fq_name, $caller);
247 my $sub = subname($fq_name => $wrapper);
249 $export_recorder->{$sub} = 1;
255 sub _make_wrapped_sub_with_meta {
259 my $export_recorder = shift;
262 my $caller = $CALLER;
264 my $wrapper = $self->_late_curry_wrapper($sub, $fq_name,
265 sub { Class::MOP::class_of(shift) } => $caller);
267 my $sub = subname($fq_name => $wrapper);
269 $export_recorder->{$sub} = 1;
275 sub _make_wrapped_group {
277 my $package = shift; # package calling use Moose::Exporter
279 my $export_recorder = shift;
280 my $keywords = shift;
281 my $is_removable = shift;
284 my $caller = $CALLER; # package calling use PackageUsingMooseExporter -group => {args}
286 # there are plenty of ways to deal with telling the code which
287 # package it lives in. the last arg (collector hashref) is
288 # otherwise unused, so we'll stick the original package in
289 # there and act like 'with_caller' by putting the calling
290 # package name as the first arg
292 $_[3]{from} = $package;
294 my $named_code = $sub->(@_);
297 # send invalid return value error up to Sub::Exporter
298 unless (ref $named_code eq 'HASH') {
302 for my $name (keys %$named_code) {
303 my $code = $named_code->{$name};
305 my $fq_name = $package . '::' . $name;
306 my $wrapper = $class->_curry_wrapper(
312 my $sub = subname( $fq_name => $wrapper );
313 $named_code->{$name} = $sub;
315 # mark each coderef as ours
316 $keywords->{$name} = 1;
317 $is_removable->{$name} = 1;
318 $export_recorder->{$sub} = 1;
331 my $wrapper = sub { $sub->(@extra, @_) };
332 if (my $proto = prototype $sub) {
333 # XXX - Perl's prototype sucks. Use & to make set_prototype
334 # ignore the fact that we're passing "private variables"
335 &Scalar::Util::set_prototype($wrapper, $proto);
340 sub _late_curry_wrapper {
348 # resolve curried arguments at runtime via this closure
349 my @curry = ( $extra->( @ex_args ) );
350 return $sub->(@curry, @_);
353 if (my $proto = prototype $sub) {
354 # XXX - Perl's prototype sucks. Use & to make set_prototype
355 # ignore the fact that we're passing "private variables"
356 &Scalar::Util::set_prototype($wrapper, $proto);
361 sub _make_import_sub {
363 my $exporting_package = shift;
364 my $exporter = shift;
365 my $exports_from = shift;
366 my $export_to_main = shift;
370 # I think we could use Sub::Exporter's collector feature
371 # to do this, but that would be rather gross, since that
372 # feature isn't really designed to return a value to the
373 # caller of the exporter sub.
375 # Also, this makes sure we preserve backwards compat for
376 # _get_caller, so it always sees the arguments in the
379 ( $traits, @_ ) = _strip_traits(@_);
382 ( $metaclass, @_ ) = _strip_metaclass(@_);
383 $metaclass = Moose::Util::resolve_metaclass_alias(
384 'Class' => $metaclass
385 ) if defined $metaclass && length $metaclass;
387 # Normally we could look at $_[0], but in some weird cases
388 # (involving goto &Moose::import), $_[0] ends as something
389 # else (like Squirrel).
390 my $class = $exporting_package;
392 $CALLER = _get_caller(@_);
394 # this works because both pragmas set $^H (see perldoc
395 # perlvar) which affects the current compilation -
396 # i.e. the file who use'd us - which is why we don't need
397 # to do anything special to make it affect that file
398 # rather than this one (which is already compiled)
403 # we should never export to main
404 if ( $CALLER eq 'main' && !$export_to_main ) {
406 qq{$class does not export its sugar to the 'main' package.\n};
411 for my $c ( grep { $_->can('init_meta') } $class, @{$exports_from} ) {
412 # init_meta can apply a role, which when loaded uses
413 # Moose::Exporter, which in turn sets $CALLER, so we need
414 # to protect against that.
415 local $CALLER = $CALLER;
416 $c->init_meta( for_class => $CALLER, metaclass => $metaclass );
420 if ( $did_init_meta && @{$traits} ) {
421 # The traits will use Moose::Role, which in turn uses
422 # Moose::Exporter, which in turn sets $CALLER, so we need
423 # to protect against that.
424 local $CALLER = $CALLER;
425 _apply_meta_traits( $CALLER, $traits );
427 elsif ( @{$traits} ) {
430 "Cannot provide traits when $class does not have an init_meta() method"
440 my $idx = first_index { $_ eq '-traits' } @_;
442 return ( [], @_ ) unless $idx >= 0 && $#_ >= $idx + 1;
444 my $traits = $_[ $idx + 1 ];
448 $traits = [ $traits ] unless ref $traits;
450 return ( $traits, @_ );
453 sub _strip_metaclass {
454 my $idx = first_index { $_ eq '-metaclass' } @_;
456 return ( undef, @_ ) unless $idx >= 0 && $#_ >= $idx + 1;
458 my $metaclass = $_[ $idx + 1 ];
462 return ( $metaclass, @_ );
465 sub _apply_meta_traits {
466 my ( $class, $traits ) = @_;
468 return unless @{$traits};
470 my $meta = Class::MOP::class_of($class);
472 my $type = ( split /::/, ref $meta )[-1]
473 or Moose->throw_error(
474 'Cannot determine metaclass type for trait application . Meta isa '
479 ref $_ ? $_ : Moose::Util::resolve_metatrait_alias( $type => $_ )
483 return unless @resolved_traits;
485 Moose::Util::MetaRole::apply_metaclass_roles(
487 metaclass_roles => \@resolved_traits,
492 # 1 extra level because it's called by import so there's a layer
497 ( ref $_[1] && defined $_[1]->{into} ) ? $_[1]->{into}
498 : ( ref $_[1] && defined $_[1]->{into_level} )
499 ? caller( $offset + $_[1]->{into_level} )
503 sub _make_unimport_sub {
505 my $exporting_package = shift;
507 my $is_removable = shift;
508 my $export_recorder = shift;
511 my $caller = scalar caller();
512 Moose::Exporter->_remove_keywords(
514 [ keys %{$exports} ],
521 sub _remove_keywords {
524 my $keywords = shift;
525 my $is_removable = shift;
526 my $recorded_exports = shift;
530 foreach my $name ( @{ $keywords } ) {
531 next unless $is_removable->{$name};
533 if ( defined &{ $package . '::' . $name } ) {
534 my $sub = \&{ $package . '::' . $name };
536 # make sure it is from us
537 next unless $recorded_exports->{$sub};
539 # and if it is from us, then undef the slot
540 delete ${ $package . '::' }{$name};
545 sub _make_init_meta {
551 for my $role (map { "${_}_roles" }
555 wrapped_method_metaclass
560 application_to_class_class
561 application_to_role_class
562 application_to_instance_class)) {
563 $metaclass_roles{$role} = $args->{$role} if exists $args->{$role};
566 my %base_class_roles;
567 %base_class_roles = (roles => $args->{base_class_roles})
568 if exists $args->{base_class_roles};
570 return unless %metaclass_roles || %base_class_roles;
575 return unless Class::MOP::class_of($options{for_class});
576 Moose::Util::MetaRole::apply_metaclass_roles(
577 for_class => $options{for_class},
580 Moose::Util::MetaRole::apply_base_class_roles(
581 for_class => $options{for_class},
583 ) if Class::MOP::class_of($options{for_class})->isa('Moose::Meta::Class');
584 return Class::MOP::class_of($options{for_class});
599 Moose::Exporter - make an import() and unimport() just like Moose.pm
603 package MyApp::Moose;
608 Moose::Exporter->setup_import_methods(
609 with_caller => [ 'has_rw', 'sugar2' ],
610 as_is => [ 'sugar3', \&Some::Random::thing ],
615 my ($caller, $name, %options) = @_;
616 Class::MOP::class_of($caller)->add_attribute($name,
635 This module encapsulates the exporting of sugar functions in a
636 C<Moose.pm>-like manner. It does this by building custom C<import>,
637 C<unimport>, and optionally C<init_meta> methods for your module,
638 based on a spec you provide.
640 It also lets you "stack" Moose-alike modules so you can export
641 Moose's sugar as well as your own, along with sugar from any random
642 C<MooseX> module, as long as they all use C<Moose::Exporter>.
644 To simplify writing exporter modules, C<Moose::Exporter> also imports
645 C<strict> and C<warnings> into your exporter module, as well as into
650 This module provides two public methods:
654 =item B<< Moose::Exporter->setup_import_methods(...) >>
656 When you call this method, C<Moose::Exporter> builds custom C<import>,
657 C<unimport>, and C<init_meta> methods for your module. The C<import>
658 method will export the functions you specify, and you can also tell it
659 to export functions exported by some other module (like C<Moose.pm>).
661 The C<unimport> method cleans the callers namespace of all the
664 The C<init_meta> method will be generated if any parameters for
665 L<Moose::Util::MetaRole> are passed to C<setup_import_methods> (see
666 below). It will handle passing along the required traits to
667 C<apply_metaclass_roles> and C<apply_base_class_roles> as needed.
669 Note that if any of these methods already exist, they will not be
670 overridden, you will have to use C<build_import_methods> to get the
671 coderef that would be installed.
673 This method accepts the following parameters:
677 =item * with_caller => [ ... ]
679 This a list of function I<names only> to be exported wrapped and then
680 exported. The wrapper will pass the name of the calling package as the
681 first argument to the function. Many sugar functions need to know
682 their caller so they can get the calling package's metaclass object.
684 =item * as_is => [ ... ]
686 This a list of function names or sub references to be exported
687 as-is. You can identify a subroutine by reference, which is handy to
688 re-export some other module's functions directly by reference
689 (C<\&Some::Package::function>).
691 If you do export some other packages function, this function will
692 never be removed by the C<unimport> method. The reason for this is we
693 cannot know if the caller I<also> explicitly imported the sub
694 themselves, and therefore wants to keep it.
696 =item * also => $name or \@names
698 This is a list of modules which contain functions that the caller
699 wants to export. These modules must also use C<Moose::Exporter>. The
700 most common use case will be to export the functions from C<Moose.pm>.
701 Functions specified by C<with_caller> or C<as_is> take precedence over
702 functions exported by modules specified by C<also>, so that a module
703 can selectively override functions exported by another module.
705 C<Moose::Exporter> also makes sure all these functions get removed
706 when C<unimport> is called.
710 Any of the C<*_roles> options for
711 C<Moose::Util::MetaRole::apply_metaclass_roles> are also valid here,
712 and C<base_class_roles> will be passed along to the C<roles> parameter
713 of C<Moose::Util::MetaRole::apply_base_class_roles>.
715 =item B<< Moose::Exporter->build_import_methods(...) >>
717 Returns two or three code refs, one for C<import>, one for
718 C<unimport>, and optionally one for C<init_meta>, if the appropriate
719 options are passed in.
721 Accepts the additional C<install> option, which accepts an arrayref of
722 method names to install into your exporter (C<import>, C<unimport>,
723 and C<init_meta>). Calling C<setup_import_methods> is equivalent to
724 calling C<build_import_methods> with
725 C<< install => [qw(import unimport init_meta)] >> (except that it
726 doesn't also return the methods).
728 Used by C<setup_import_methods>.
732 =head1 IMPORTING AND init_meta
734 If you want to set an alternative base object class or metaclass
735 class, see above for how to pass options to L<Moose::Util::MetaRole>
736 through the options to C<setup_import_methods>. If you want to do
737 something not supported by this, simply define an C<init_meta> method
738 in your class. The C<import> method that C<Moose::Exporter> generates
739 for you will call this method (if it exists). It will always pass the
740 caller to this method via the C<for_class> parameter.
742 Most of the time, your C<init_meta> method will probably just call C<<
743 Moose->init_meta >> to do the real work:
746 shift; # our class name
747 return Moose->init_meta( @_, metaclass => 'My::Metaclass' );
750 Keep in mind that C<build_import_methods> will return an C<init_meta>
751 method for you, which you can also call from within your custom
754 =head1 METACLASS TRAITS
756 The C<import> method generated by C<Moose::Exporter> will allow the
757 user of your module to specify metaclass traits in a C<-traits>
758 parameter passed as part of the import:
760 use Moose -traits => 'My::Meta::Trait';
762 use Moose -traits => [ 'My::Meta::Trait', 'My::Other::Trait' ];
764 These traits will be applied to the caller's metaclass
765 instance. Providing traits for an exporting class that does not create
766 a metaclass for the caller is an error.
770 Dave Rolsky E<lt>autarch@urth.orgE<gt>
772 This is largely a reworking of code in Moose.pm originally written by
773 Stevan Little and others.
775 =head1 COPYRIGHT AND LICENSE
777 Copyright 2009 by Infinity Interactive, Inc.
779 L<http://www.iinteractive.com>
781 This library is free software; you can redistribute it and/or modify
782 it under the same terms as Perl itself.