Don't start a sentence with lower case
[gitmo/Moose.git] / lib / Moose / Exporter.pm
CommitLineData
e606ae5f 1package Moose::Exporter;
2
3use strict;
4use warnings;
5
6d0815b5 6our $VERSION = '0.93';
ae18d5ec 7$VERSION = eval $VERSION;
8our $AUTHORITY = 'cpan:STEVAN';
9
e606ae5f 10use Class::MOP;
11use List::MoreUtils qw( first_index uniq );
12use Moose::Util::MetaRole;
091ac4b7 13use Sub::Exporter 0.980;
9f2230e9 14use Sub::Name qw(subname);
e606ae5f 15
16my %EXPORT_SPEC;
17
18sub setup_import_methods {
19 my ( $class, %args ) = @_;
20
21 my $exporting_package = $args{exporting_package} ||= caller();
22
95056a1e 23 $class->build_import_methods(
24 %args,
25 install => [qw(import unimport init_meta)]
26 );
e606ae5f 27}
28
29sub build_import_methods {
30 my ( $class, %args ) = @_;
31
32 my $exporting_package = $args{exporting_package} ||= caller();
33
34 $EXPORT_SPEC{$exporting_package} = \%args;
35
36 my @exports_from = $class->_follow_also( $exporting_package );
37
38 my $export_recorder = {};
39
0661fc1a 40 my ( $exports, $is_removable )
e05fb8ae 41 = $class->_make_sub_exporter_params(
f44ec924 42 [ @exports_from, $exporting_package ], $export_recorder );
e606ae5f 43
44 my $exporter = Sub::Exporter::build_exporter(
45 {
46 exports => $exports,
0661fc1a 47 groups => { default => [':all'] }
e606ae5f 48 }
49 );
50
95056a1e 51 my %methods;
95056a1e 52 $methods{import} = $class->_make_import_sub( $exporting_package,
05cde4e8 53 $exporter, \@exports_from );
e606ae5f 54
95056a1e 55 $methods{unimport} = $class->_make_unimport_sub( $exporting_package,
56 $exports, $is_removable, $export_recorder );
57
58 $methods{init_meta} = $class->_make_init_meta( $exporting_package,
59 \%args );
60
61 my $package = Class::MOP::Package->initialize($exporting_package);
906eabcd 62 for my $to_install ( @{ $args{install} || [] } ) {
95056a1e 63 my $symbol = '&' . $to_install;
906eabcd 64 next
65 unless $methods{$to_install}
66 && !$package->has_package_symbol($symbol);
67 $package->add_package_symbol( $symbol, $methods{$to_install} );
95056a1e 68 }
e606ae5f 69
95056a1e 70 return ( $methods{import}, $methods{unimport}, $methods{init_meta} )
e606ae5f 71}
72
73{
74 my $seen = {};
75
76 sub _follow_also {
77 my $class = shift;
78 my $exporting_package = shift;
79
80 local %$seen = ( $exporting_package => 1 );
81
82 return uniq( _follow_also_real($exporting_package) );
83 }
84
85 sub _follow_also_real {
86 my $exporting_package = shift;
87
ba1a3c2f 88 if (!exists $EXPORT_SPEC{$exporting_package}) {
89 my $loaded = Class::MOP::is_class_loaded($exporting_package);
90
91 die "Package in also ($exporting_package) does not seem to "
92 . "use Moose::Exporter"
93 . ($loaded ? "" : " (is it loaded?)");
94 }
e606ae5f 95
96 my $also = $EXPORT_SPEC{$exporting_package}{also};
97
98 return unless defined $also;
99
100 my @also = ref $also ? @{$also} : $also;
101
102 for my $package (@also)
103 {
b822369d 104 die "Circular reference in 'also' parameter to Moose::Exporter between $exporting_package and $package"
e606ae5f 105 if $seen->{$package};
106
107 $seen->{$package} = 1;
108 }
109
110 return @also, map { _follow_also_real($_) } @also;
111 }
112}
113
114sub _make_sub_exporter_params {
115 my $class = shift;
116 my $packages = shift;
117 my $export_recorder = shift;
118
119 my %exports;
e05fb8ae 120 my %is_removable;
e606ae5f 121
122 for my $package ( @{$packages} ) {
123 my $args = $EXPORT_SPEC{$package}
124 or die "The $package package does not use Moose::Exporter\n";
125
5ac14e89 126 for my $name ( @{ $args->{with_meta} } ) {
0dd4228e 127 my $sub = $class->_sub_from_package( $package, $name )
128 or next;
e6a5040f 129
e606ae5f 130 my $fq_name = $package . '::' . $name;
131
5ac14e89 132 $exports{$name} = $class->_make_wrapped_sub_with_meta(
e606ae5f 133 $fq_name,
134 $sub,
135 $export_recorder,
136 );
e05fb8ae 137
138 $is_removable{$name} = 1;
e606ae5f 139 }
140
5ac14e89 141 for my $name ( @{ $args->{with_caller} } ) {
0dd4228e 142 my $sub = $class->_sub_from_package( $package, $name )
143 or next;
e6a5040f 144
45975bce 145 my $fq_name = $package . '::' . $name;
146
5ac14e89 147 $exports{$name} = $class->_make_wrapped_sub(
45975bce 148 $fq_name,
149 $sub,
150 $export_recorder,
151 );
152
153 $is_removable{$name} = 1;
154 }
155
e606ae5f 156 for my $name ( @{ $args->{as_is} } ) {
e6a5040f 157 my ($sub, $coderef_name);
e606ae5f 158
159 if ( ref $name ) {
160 $sub = $name;
e05fb8ae 161
162 # Even though Moose re-exports things from Carp &
163 # Scalar::Util, we don't want to remove those at
164 # unimport time, because the importing package may
165 # have imported them explicitly ala
166 #
167 # use Carp qw( confess );
168 #
169 # This is a hack. Since we can't know whether they
170 # really want to keep these subs or not, we err on the
171 # safe side and leave them in.
172 my $coderef_pkg;
e6a5040f 173 ( $coderef_pkg, $coderef_name )
174 = Class::MOP::get_code_info($name);
e05fb8ae 175
e6a5040f 176 $is_removable{$coderef_name} = $coderef_pkg eq $package ? 1 : 0;
e606ae5f 177 }
178 else {
0dd4228e 179 $sub = $class->_sub_from_package( $package, $name )
180 or next;
e6a5040f 181
e05fb8ae 182 $is_removable{$name} = 1;
e6a5040f 183 $coderef_name = $name;
e606ae5f 184 }
185
186 $export_recorder->{$sub} = 1;
187
e6a5040f 188 $exports{$coderef_name} = sub {$sub};
e606ae5f 189 }
190 }
191
0661fc1a 192 return ( \%exports, \%is_removable );
e606ae5f 193}
194
0dd4228e 195sub _sub_from_package {
196 my $sclass = shift;
197 my $package = shift;
198 my $name = shift;
199
200 my $sub = do {
201 no strict 'refs';
202 \&{ $package . '::' . $name };
203 };
204
205 return $sub if defined &$sub;
206
207 Carp::cluck
208 "Trying to export undefined sub ${package}::${name}";
209
210 return;
211}
212
96bb13ea 213our $CALLER;
214
215sub _make_wrapped_sub {
b4f00a34 216 my $self = shift;
96bb13ea 217 my $fq_name = shift;
218 my $sub = shift;
219 my $export_recorder = shift;
220
221 # We need to set the package at import time, so that when
222 # package Foo imports has(), we capture "Foo" as the
223 # package. This lets other packages call Foo::has() and get
224 # the right package. This is done for backwards compatibility
225 # with existing production code, not because this is a good
226 # idea ;)
227 return sub {
228 my $caller = $CALLER;
229
6de00734 230 my $wrapper = $self->_curry_wrapper($sub, $fq_name, $caller);
b4f00a34 231
9f2230e9 232 my $sub = subname($fq_name => $wrapper);
96bb13ea 233
234 $export_recorder->{$sub} = 1;
235
236 return $sub;
237 };
238}
e606ae5f 239
45975bce 240sub _make_wrapped_sub_with_meta {
241 my $self = shift;
242 my $fq_name = shift;
243 my $sub = shift;
244 my $export_recorder = shift;
245
246 return sub {
247 my $caller = $CALLER;
248
249 my $wrapper = $self->_late_curry_wrapper($sub, $fq_name,
250 sub { Class::MOP::class_of(shift) } => $caller);
251
252 my $sub = subname($fq_name => $wrapper);
253
254 $export_recorder->{$sub} = 1;
255
256 return $sub;
257 };
258}
259
6de00734 260sub _curry_wrapper {
badbc528 261 my $class = shift;
b4f00a34 262 my $sub = shift;
263 my $fq_name = shift;
6de00734 264 my @extra = @_;
b4f00a34 265
6de00734 266 my $wrapper = sub { $sub->(@extra, @_) };
badbc528 267 if (my $proto = prototype $sub) {
2d7e979b 268 # XXX - Perl's prototype sucks. Use & to make set_prototype
6de00734 269 # ignore the fact that we're passing "private variables"
2d7e979b 270 &Scalar::Util::set_prototype($wrapper, $proto);
badbc528 271 }
272 return $wrapper;
b4f00a34 273}
274
45975bce 275sub _late_curry_wrapper {
276 my $class = shift;
277 my $sub = shift;
278 my $fq_name = shift;
279 my $extra = shift;
280 my @ex_args = @_;
281
282 my $wrapper = sub {
283 # resolve curried arguments at runtime via this closure
284 my @curry = ( $extra->( @ex_args ) );
285 return $sub->(@curry, @_);
286 };
287
288 if (my $proto = prototype $sub) {
289 # XXX - Perl's prototype sucks. Use & to make set_prototype
290 # ignore the fact that we're passing "private variables"
291 &Scalar::Util::set_prototype($wrapper, $proto);
292 }
293 return $wrapper;
294}
295
96bb13ea 296sub _make_import_sub {
297 shift;
298 my $exporting_package = shift;
299 my $exporter = shift;
300 my $exports_from = shift;
96bb13ea 301
302 return sub {
303
304 # I think we could use Sub::Exporter's collector feature
305 # to do this, but that would be rather gross, since that
306 # feature isn't really designed to return a value to the
307 # caller of the exporter sub.
308 #
309 # Also, this makes sure we preserve backwards compat for
310 # _get_caller, so it always sees the arguments in the
311 # expected order.
312 my $traits;
313 ( $traits, @_ ) = _strip_traits(@_);
314
8f30b86e 315 my $metaclass;
316 ( $metaclass, @_ ) = _strip_metaclass(@_);
8a8856de 317 $metaclass = Moose::Util::resolve_metaclass_alias(
318 'Class' => $metaclass
319 ) if defined $metaclass && length $metaclass;
8f30b86e 320
96bb13ea 321 # Normally we could look at $_[0], but in some weird cases
322 # (involving goto &Moose::import), $_[0] ends as something
323 # else (like Squirrel).
324 my $class = $exporting_package;
325
326 $CALLER = _get_caller(@_);
327
328 # this works because both pragmas set $^H (see perldoc
329 # perlvar) which affects the current compilation -
330 # i.e. the file who use'd us - which is why we don't need
331 # to do anything special to make it affect that file
332 # rather than this one (which is already compiled)
333
334 strict->import;
335 warnings->import;
336
96bb13ea 337 my $did_init_meta;
338 for my $c ( grep { $_->can('init_meta') } $class, @{$exports_from} ) {
816208bc 339 # init_meta can apply a role, which when loaded uses
340 # Moose::Exporter, which in turn sets $CALLER, so we need
341 # to protect against that.
fdeb8354 342 local $CALLER = $CALLER;
89bcd625 343 $c->init_meta( for_class => $CALLER, metaclass => $metaclass );
96bb13ea 344 $did_init_meta = 1;
345 }
e606ae5f 346
96bb13ea 347 if ( $did_init_meta && @{$traits} ) {
348 # The traits will use Moose::Role, which in turn uses
349 # Moose::Exporter, which in turn sets $CALLER, so we need
350 # to protect against that.
351 local $CALLER = $CALLER;
352 _apply_meta_traits( $CALLER, $traits );
353 }
354 elsif ( @{$traits} ) {
70ea9161 355 require Moose;
96bb13ea 356 Moose->throw_error(
357 "Cannot provide traits when $class does not have an init_meta() method"
358 );
359 }
e606ae5f 360
96bb13ea 361 goto $exporter;
362 };
e606ae5f 363}
364
96bb13ea 365
e606ae5f 366sub _strip_traits {
367 my $idx = first_index { $_ eq '-traits' } @_;
368
369 return ( [], @_ ) unless $idx >= 0 && $#_ >= $idx + 1;
370
371 my $traits = $_[ $idx + 1 ];
372
373 splice @_, $idx, 2;
374
375 $traits = [ $traits ] unless ref $traits;
376
377 return ( $traits, @_ );
378}
379
8f30b86e 380sub _strip_metaclass {
381 my $idx = first_index { $_ eq '-metaclass' } @_;
382
383 return ( undef, @_ ) unless $idx >= 0 && $#_ >= $idx + 1;
384
385 my $metaclass = $_[ $idx + 1 ];
386
387 splice @_, $idx, 2;
388
389 return ( $metaclass, @_ );
390}
391
e606ae5f 392sub _apply_meta_traits {
393 my ( $class, $traits ) = @_;
394
395 return unless @{$traits};
396
2571a16d 397 my $meta = Class::MOP::class_of($class);
e606ae5f 398
399 my $type = ( split /::/, ref $meta )[-1]
c245d69b 400 or Moose->throw_error(
e606ae5f 401 'Cannot determine metaclass type for trait application . Meta isa '
4c0b3599 402 . ref $meta );
e606ae5f 403
404 my @resolved_traits
386c056b 405 = map {
406 ref $_ ? $_ : Moose::Util::resolve_metatrait_alias( $type => $_ )
407 }
e606ae5f 408 @$traits;
409
410 return unless @resolved_traits;
411
412 Moose::Util::MetaRole::apply_metaclass_roles(
413 for_class => $class,
414 metaclass_roles => \@resolved_traits,
415 );
416}
417
418sub _get_caller {
419 # 1 extra level because it's called by import so there's a layer
420 # of indirection
421 my $offset = 1;
422
423 return
424 ( ref $_[1] && defined $_[1]->{into} ) ? $_[1]->{into}
425 : ( ref $_[1] && defined $_[1]->{into_level} )
426 ? caller( $offset + $_[1]->{into_level} )
427 : caller($offset);
428}
429
430sub _make_unimport_sub {
431 shift;
432 my $exporting_package = shift;
433 my $exports = shift;
e05fb8ae 434 my $is_removable = shift;
e606ae5f 435 my $export_recorder = shift;
436
437 return sub {
438 my $caller = scalar caller();
439 Moose::Exporter->_remove_keywords(
440 $caller,
441 [ keys %{$exports} ],
e05fb8ae 442 $is_removable,
e606ae5f 443 $export_recorder,
444 );
445 };
446}
447
448sub _remove_keywords {
449 shift;
450 my $package = shift;
451 my $keywords = shift;
e05fb8ae 452 my $is_removable = shift;
e606ae5f 453 my $recorded_exports = shift;
454
455 no strict 'refs';
456
457 foreach my $name ( @{ $keywords } ) {
e05fb8ae 458 next unless $is_removable->{$name};
e606ae5f 459
460 if ( defined &{ $package . '::' . $name } ) {
461 my $sub = \&{ $package . '::' . $name };
462
463 # make sure it is from us
464 next unless $recorded_exports->{$sub};
465
466 # and if it is from us, then undef the slot
467 delete ${ $package . '::' }{$name};
468 }
469 }
470}
471
95056a1e 472sub _make_init_meta {
473 shift;
906eabcd 474 my $class = shift;
475 my $args = shift;
95056a1e 476
477 my %metaclass_roles;
906eabcd 478 for my $role (
479 map {"${_}_roles"}
480 qw(metaclass
481 attribute_metaclass
482 method_metaclass
483 wrapped_method_metaclass
484 instance_metaclass
485 constructor_class
486 destructor_class
487 error_class
488 application_to_class_class
489 application_to_role_class
490 application_to_instance_class)
491 ) {
95056a1e 492 $metaclass_roles{$role} = $args->{$role} if exists $args->{$role};
493 }
494
495 my %base_class_roles;
906eabcd 496 %base_class_roles = ( roles => $args->{base_class_roles} )
95056a1e 497 if exists $args->{base_class_roles};
498
499 return unless %metaclass_roles || %base_class_roles;
500
501 return sub {
502 shift;
503 my %options = @_;
906eabcd 504
505 return unless Class::MOP::class_of( $options{for_class} );
506
95056a1e 507 Moose::Util::MetaRole::apply_metaclass_roles(
508 for_class => $options{for_class},
509 %metaclass_roles,
510 );
906eabcd 511
95056a1e 512 Moose::Util::MetaRole::apply_base_class_roles(
513 for_class => $options{for_class},
514 %base_class_roles,
906eabcd 515 )
516 if Class::MOP::class_of( $options{for_class} )
517 ->isa('Moose::Meta::Class');
518
519 return Class::MOP::class_of( $options{for_class} );
95056a1e 520 };
521}
522
e2fa092d 523sub import {
524 strict->import;
525 warnings->import;
526}
527
e606ae5f 5281;
529
530__END__
531
532=head1 NAME
533
534Moose::Exporter - make an import() and unimport() just like Moose.pm
535
536=head1 SYNOPSIS
537
538 package MyApp::Moose;
539
e606ae5f 540 use Moose ();
541 use Moose::Exporter;
542
543 Moose::Exporter->setup_import_methods(
5ac14e89 544 with_meta => [ 'has_rw', 'sugar2' ],
545 as_is => [ 'sugar3', \&Some::Random::thing ],
546 also => 'Moose',
e606ae5f 547 );
548
82ad7804 549 sub has_rw {
5ac14e89 550 my ( $meta, $name, %options ) = @_;
551 $meta->add_attribute(
552 $name,
82ad7804 553 is => 'rw',
554 %options,
555 );
556 }
557
e606ae5f 558 # then later ...
559 package MyApp::User;
560
561 use MyApp::Moose;
562
563 has 'name';
6daad0b9 564 has_rw 'size';
e606ae5f 565 thing;
566
567 no MyApp::Moose;
568
569=head1 DESCRIPTION
570
fd7ab111 571This module encapsulates the exporting of sugar functions in a
95056a1e 572C<Moose.pm>-like manner. It does this by building custom C<import>,
37e4fe95 573C<unimport>, and C<init_meta> methods for your module, based on a spec you
574provide.
e606ae5f 575
37e4fe95 576It also lets you "stack" Moose-alike modules so you can export Moose's sugar
577as well as your own, along with sugar from any random C<MooseX> module, as
578long as they all use C<Moose::Exporter>. This feature exists to let you bundle
579a set of MooseX modules into a policy module that developers can use directly
580instead of using Moose itself.
e606ae5f 581
10e0127a 582To simplify writing exporter modules, C<Moose::Exporter> also imports
583C<strict> and C<warnings> into your exporter module, as well as into
584modules that use it.
585
e606ae5f 586=head1 METHODS
587
588This module provides two public methods:
589
4b68e0de 590=over 4
591
592=item B<< Moose::Exporter->setup_import_methods(...) >>
e606ae5f 593
95056a1e 594When you call this method, C<Moose::Exporter> builds custom C<import>,
37e4fe95 595C<unimport>, and C<init_meta> methods for your module. The C<import> method
596will export the functions you specify, and can also re-export functions
597exported by some other module (like C<Moose.pm>).
e606ae5f 598
37e4fe95 599The C<unimport> method cleans the caller's namespace of all the exported
600functions.
e606ae5f 601
37e4fe95 602If you pass any parameters for L<Moose::Util::MetaRole>, this method will
603generate an C<init_meta> for you as well (see below for details). This
604C<init_meta> will call C<Moose::Util::MetaRole::apply_metaclass_roles> and
605C<Moose::Util::MetaRole::apply_base_class_roles> as needed.
95056a1e 606
607Note that if any of these methods already exist, they will not be
608overridden, you will have to use C<build_import_methods> to get the
609coderef that would be installed.
e606ae5f 610
611This method accepts the following parameters:
612
4b68e0de 613=over 8
e606ae5f 614
5ac14e89 615=item * with_meta => [ ... ]
e606ae5f 616
37e4fe95 617This list of function I<names only> will be wrapped and then exported. The
5ac14e89 618wrapper will pass the metaclass object for the caller as its first argument.
619
620Many sugar functions will need to use this metaclass object to do something to
621the calling package.
e606ae5f 622
623=item * as_is => [ ... ]
624
37e4fe95 625This list of function names or sub references will be exported as-is. You can
626identify a subroutine by reference, which is handy to re-export some other
627module's functions directly by reference (C<\&Some::Package::function>).
e606ae5f 628
37e4fe95 629If you do export some other package's function, this function will never be
630removed by the C<unimport> method. The reason for this is we cannot know if
631the caller I<also> explicitly imported the sub themselves, and therefore wants
632to keep it.
e05fb8ae 633
e606ae5f 634=item * also => $name or \@names
635
636This is a list of modules which contain functions that the caller
637wants to export. These modules must also use C<Moose::Exporter>. The
638most common use case will be to export the functions from C<Moose.pm>.
5ac14e89 639Functions specified by C<with_meta> or C<as_is> take precedence over
ae8817b6 640functions exported by modules specified by C<also>, so that a module
641can selectively override functions exported by another module.
e606ae5f 642
643C<Moose::Exporter> also makes sure all these functions get removed
644when C<unimport> is called.
645
646=back
647
95056a1e 648Any of the C<*_roles> options for
37e4fe95 649C<Moose::Util::MetaRole::apply_metaclass_roles> and
650C<Moose::Util::MetaRole::base_class_roles> are also acceptable.
95056a1e 651
4b68e0de 652=item B<< Moose::Exporter->build_import_methods(...) >>
e606ae5f 653
95056a1e 654Returns two or three code refs, one for C<import>, one for
655C<unimport>, and optionally one for C<init_meta>, if the appropriate
656options are passed in.
657
37e4fe95 658Accepts the additional C<install> option, which accepts an arrayref of method
659names to install into your exporting package. The valid options are C<import>,
660C<unimport>, and C<init_meta>. Calling C<setup_import_methods> is equivalent
661to calling C<build_import_methods> with C<< install => [qw(import unimport
662init_meta)] >> except that it doesn't also return the methods.
e606ae5f 663
664Used by C<setup_import_methods>.
665
4b68e0de 666=back
667
e606ae5f 668=head1 IMPORTING AND init_meta
669
37e4fe95 670If you want to set an alternative base object class or metaclass class, see
671above for details on how this module can call L<Moose::Util::MetaRole> for
672you.
673
674If you want to do something that is not supported by this module, simply
675define an C<init_meta> method in your class. The C<import> method that
676C<Moose::Exporter> generates for you will call this method (if it exists). It
677will always pass the caller to this method via the C<for_class> parameter.
e606ae5f 678
679Most of the time, your C<init_meta> method will probably just call C<<
680Moose->init_meta >> to do the real work:
681
682 sub init_meta {
683 shift; # our class name
684 return Moose->init_meta( @_, metaclass => 'My::Metaclass' );
685 }
686
95056a1e 687Keep in mind that C<build_import_methods> will return an C<init_meta>
688method for you, which you can also call from within your custom
37e4fe95 689C<init_meta>:
690
691 my ( $import, $unimport, $init_meta ) =
692 Moose::Exporter->build_import_methods( ... );
693
694 sub import {
695 my $class = shift;
696
697 ...
698
699 $class->$import(...);
700
701 ...
702 }
703
704 sub unimport { goto &$unimport }
705
706 sub init_meta {
707 my $class = shift;
708
709 ...
710
711 $class->$init_meta(...);
712
713 ...
714 }
95056a1e 715
e606ae5f 716=head1 METACLASS TRAITS
717
718The C<import> method generated by C<Moose::Exporter> will allow the
719user of your module to specify metaclass traits in a C<-traits>
720parameter passed as part of the import:
721
722 use Moose -traits => 'My::Meta::Trait';
723
724 use Moose -traits => [ 'My::Meta::Trait', 'My::Other::Trait' ];
725
726These traits will be applied to the caller's metaclass
727instance. Providing traits for an exporting class that does not create
728a metaclass for the caller is an error.
729
730=head1 AUTHOR
731
732Dave Rolsky E<lt>autarch@urth.orgE<gt>
733
734This is largely a reworking of code in Moose.pm originally written by
735Stevan Little and others.
736
737=head1 COPYRIGHT AND LICENSE
738
2840a3b2 739Copyright 2009 by Infinity Interactive, Inc.
e606ae5f 740
741L<http://www.iinteractive.com>
742
743This library is free software; you can redistribute it and/or modify
744it under the same terms as Perl itself.
745
746=cut