update changes and delta
[gitmo/Moose.git] / lib / Moose / Exporter.pm
CommitLineData
e606ae5f 1package Moose::Exporter;
2
3use strict;
4use warnings;
5
75d2da34 6our $VERSION = '0.77';
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;
13use Sub::Exporter;
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
23 my ( $import, $unimport ) = $class->build_import_methods(%args);
24
25 no strict 'refs';
26 *{ $exporting_package . '::import' } = $import;
27 *{ $exporting_package . '::unimport' } = $unimport;
28}
29
30sub build_import_methods {
31 my ( $class, %args ) = @_;
32
33 my $exporting_package = $args{exporting_package} ||= caller();
34
35 $EXPORT_SPEC{$exporting_package} = \%args;
36
37 my @exports_from = $class->_follow_also( $exporting_package );
38
39 my $export_recorder = {};
40
e05fb8ae 41 my ( $exports, $is_removable )
42 = $class->_make_sub_exporter_params(
f44ec924 43 [ @exports_from, $exporting_package ], $export_recorder );
e606ae5f 44
45 my $exporter = Sub::Exporter::build_exporter(
46 {
47 exports => $exports,
48 groups => { default => [':all'] }
49 }
50 );
51
52 # $args{_export_to_main} exists for backwards compat, because
53 # Moose::Util::TypeConstraints did export to main (unlike Moose &
54 # Moose::Role).
55 my $import = $class->_make_import_sub( $exporting_package, $exporter,
56 \@exports_from, $args{_export_to_main} );
57
58 my $unimport = $class->_make_unimport_sub( $exporting_package, $exports,
e05fb8ae 59 $is_removable, $export_recorder );
e606ae5f 60
61 return ( $import, $unimport )
62}
63
64{
65 my $seen = {};
66
67 sub _follow_also {
68 my $class = shift;
69 my $exporting_package = shift;
70
71 local %$seen = ( $exporting_package => 1 );
72
73 return uniq( _follow_also_real($exporting_package) );
74 }
75
76 sub _follow_also_real {
77 my $exporting_package = shift;
78
f5d03831 79 die "Package in also ($exporting_package) does not seem to use Moose::Exporter"
e606ae5f 80 unless exists $EXPORT_SPEC{$exporting_package};
81
82 my $also = $EXPORT_SPEC{$exporting_package}{also};
83
84 return unless defined $also;
85
86 my @also = ref $also ? @{$also} : $also;
87
88 for my $package (@also)
89 {
f5d03831 90 die "Circular reference in also parameter to Moose::Exporter between $exporting_package and $package"
e606ae5f 91 if $seen->{$package};
92
93 $seen->{$package} = 1;
94 }
95
96 return @also, map { _follow_also_real($_) } @also;
97 }
98}
99
100sub _make_sub_exporter_params {
101 my $class = shift;
102 my $packages = shift;
103 my $export_recorder = shift;
104
105 my %exports;
e05fb8ae 106 my %is_removable;
e606ae5f 107
108 for my $package ( @{$packages} ) {
109 my $args = $EXPORT_SPEC{$package}
110 or die "The $package package does not use Moose::Exporter\n";
111
112 for my $name ( @{ $args->{with_caller} } ) {
113 my $sub = do {
114 no strict 'refs';
115 \&{ $package . '::' . $name };
116 };
117
118 my $fq_name = $package . '::' . $name;
119
120 $exports{$name} = $class->_make_wrapped_sub(
121 $fq_name,
122 $sub,
123 $export_recorder,
124 );
e05fb8ae 125
126 $is_removable{$name} = 1;
e606ae5f 127 }
128
129 for my $name ( @{ $args->{as_is} } ) {
130 my $sub;
131
132 if ( ref $name ) {
133 $sub = $name;
e05fb8ae 134
135 # Even though Moose re-exports things from Carp &
136 # Scalar::Util, we don't want to remove those at
137 # unimport time, because the importing package may
138 # have imported them explicitly ala
139 #
140 # use Carp qw( confess );
141 #
142 # This is a hack. Since we can't know whether they
143 # really want to keep these subs or not, we err on the
144 # safe side and leave them in.
145 my $coderef_pkg;
146 ( $coderef_pkg, $name ) = Class::MOP::get_code_info($name);
147
148 $is_removable{$name} = $coderef_pkg eq $package ? 1 : 0;
e606ae5f 149 }
150 else {
151 $sub = do {
152 no strict 'refs';
153 \&{ $package . '::' . $name };
154 };
e05fb8ae 155
156 $is_removable{$name} = 1;
e606ae5f 157 }
158
159 $export_recorder->{$sub} = 1;
160
161 $exports{$name} = sub {$sub};
162 }
163 }
164
e05fb8ae 165 return ( \%exports, \%is_removable );
e606ae5f 166}
167
96bb13ea 168our $CALLER;
169
170sub _make_wrapped_sub {
b4f00a34 171 my $self = shift;
96bb13ea 172 my $fq_name = shift;
173 my $sub = shift;
174 my $export_recorder = shift;
175
176 # We need to set the package at import time, so that when
177 # package Foo imports has(), we capture "Foo" as the
178 # package. This lets other packages call Foo::has() and get
179 # the right package. This is done for backwards compatibility
180 # with existing production code, not because this is a good
181 # idea ;)
182 return sub {
183 my $caller = $CALLER;
184
b4f00a34 185 my $wrapper = $self->_make_wrapper($caller, $sub, $fq_name);
186
9f2230e9 187 my $sub = subname($fq_name => $wrapper);
96bb13ea 188
189 $export_recorder->{$sub} = 1;
190
191 return $sub;
192 };
193}
e606ae5f 194
badbc528 195sub _make_wrapper {
196 my $class = shift;
b4f00a34 197 my $caller = shift;
198 my $sub = shift;
199 my $fq_name = shift;
200
2d7e979b 201 my $wrapper = sub { $sub->($caller, @_) };
badbc528 202 if (my $proto = prototype $sub) {
2d7e979b 203 # XXX - Perl's prototype sucks. Use & to make set_prototype
204 # ignore the fact that we're passing a "provate variable"
205 &Scalar::Util::set_prototype($wrapper, $proto);
badbc528 206 }
207 return $wrapper;
b4f00a34 208}
209
96bb13ea 210sub _make_import_sub {
211 shift;
212 my $exporting_package = shift;
213 my $exporter = shift;
214 my $exports_from = shift;
215 my $export_to_main = shift;
216
217 return sub {
218
219 # I think we could use Sub::Exporter's collector feature
220 # to do this, but that would be rather gross, since that
221 # feature isn't really designed to return a value to the
222 # caller of the exporter sub.
223 #
224 # Also, this makes sure we preserve backwards compat for
225 # _get_caller, so it always sees the arguments in the
226 # expected order.
227 my $traits;
228 ( $traits, @_ ) = _strip_traits(@_);
229
8f30b86e 230 my $metaclass;
231 ( $metaclass, @_ ) = _strip_metaclass(@_);
232
96bb13ea 233 # Normally we could look at $_[0], but in some weird cases
234 # (involving goto &Moose::import), $_[0] ends as something
235 # else (like Squirrel).
236 my $class = $exporting_package;
237
238 $CALLER = _get_caller(@_);
239
240 # this works because both pragmas set $^H (see perldoc
241 # perlvar) which affects the current compilation -
242 # i.e. the file who use'd us - which is why we don't need
243 # to do anything special to make it affect that file
244 # rather than this one (which is already compiled)
245
246 strict->import;
247 warnings->import;
248
249 # we should never export to main
250 if ( $CALLER eq 'main' && !$export_to_main ) {
251 warn
252 qq{$class does not export its sugar to the 'main' package.\n};
253 return;
254 }
e606ae5f 255
96bb13ea 256 my $did_init_meta;
257 for my $c ( grep { $_->can('init_meta') } $class, @{$exports_from} ) {
816208bc 258 # init_meta can apply a role, which when loaded uses
259 # Moose::Exporter, which in turn sets $CALLER, so we need
260 # to protect against that.
fdeb8354 261 local $CALLER = $CALLER;
89bcd625 262 $c->init_meta( for_class => $CALLER, metaclass => $metaclass );
96bb13ea 263 $did_init_meta = 1;
264 }
e606ae5f 265
96bb13ea 266 if ( $did_init_meta && @{$traits} ) {
267 # The traits will use Moose::Role, which in turn uses
268 # Moose::Exporter, which in turn sets $CALLER, so we need
269 # to protect against that.
270 local $CALLER = $CALLER;
271 _apply_meta_traits( $CALLER, $traits );
272 }
273 elsif ( @{$traits} ) {
70ea9161 274 require Moose;
96bb13ea 275 Moose->throw_error(
276 "Cannot provide traits when $class does not have an init_meta() method"
277 );
278 }
e606ae5f 279
96bb13ea 280 goto $exporter;
281 };
e606ae5f 282}
283
96bb13ea 284
e606ae5f 285sub _strip_traits {
286 my $idx = first_index { $_ eq '-traits' } @_;
287
288 return ( [], @_ ) unless $idx >= 0 && $#_ >= $idx + 1;
289
290 my $traits = $_[ $idx + 1 ];
291
292 splice @_, $idx, 2;
293
294 $traits = [ $traits ] unless ref $traits;
295
296 return ( $traits, @_ );
297}
298
8f30b86e 299sub _strip_metaclass {
300 my $idx = first_index { $_ eq '-metaclass' } @_;
301
302 return ( undef, @_ ) unless $idx >= 0 && $#_ >= $idx + 1;
303
304 my $metaclass = $_[ $idx + 1 ];
305
306 splice @_, $idx, 2;
307
308 return ( $metaclass, @_ );
309}
310
e606ae5f 311sub _apply_meta_traits {
312 my ( $class, $traits ) = @_;
313
314 return unless @{$traits};
315
2571a16d 316 my $meta = Class::MOP::class_of($class);
e606ae5f 317
318 my $type = ( split /::/, ref $meta )[-1]
c245d69b 319 or Moose->throw_error(
e606ae5f 320 'Cannot determine metaclass type for trait application . Meta isa '
4c0b3599 321 . ref $meta );
e606ae5f 322
323 my @resolved_traits
324 = map { Moose::Util::resolve_metatrait_alias( $type => $_ ) }
325 @$traits;
326
327 return unless @resolved_traits;
328
329 Moose::Util::MetaRole::apply_metaclass_roles(
330 for_class => $class,
331 metaclass_roles => \@resolved_traits,
332 );
333}
334
335sub _get_caller {
336 # 1 extra level because it's called by import so there's a layer
337 # of indirection
338 my $offset = 1;
339
340 return
341 ( ref $_[1] && defined $_[1]->{into} ) ? $_[1]->{into}
342 : ( ref $_[1] && defined $_[1]->{into_level} )
343 ? caller( $offset + $_[1]->{into_level} )
344 : caller($offset);
345}
346
347sub _make_unimport_sub {
348 shift;
349 my $exporting_package = shift;
350 my $exports = shift;
e05fb8ae 351 my $is_removable = shift;
e606ae5f 352 my $export_recorder = shift;
353
354 return sub {
355 my $caller = scalar caller();
356 Moose::Exporter->_remove_keywords(
357 $caller,
358 [ keys %{$exports} ],
e05fb8ae 359 $is_removable,
e606ae5f 360 $export_recorder,
361 );
362 };
363}
364
365sub _remove_keywords {
366 shift;
367 my $package = shift;
368 my $keywords = shift;
e05fb8ae 369 my $is_removable = shift;
e606ae5f 370 my $recorded_exports = shift;
371
372 no strict 'refs';
373
374 foreach my $name ( @{ $keywords } ) {
e05fb8ae 375 next unless $is_removable->{$name};
e606ae5f 376
377 if ( defined &{ $package . '::' . $name } ) {
378 my $sub = \&{ $package . '::' . $name };
379
380 # make sure it is from us
381 next unless $recorded_exports->{$sub};
382
383 # and if it is from us, then undef the slot
384 delete ${ $package . '::' }{$name};
385 }
386 }
387}
388
e2fa092d 389sub import {
390 strict->import;
391 warnings->import;
392}
393
e606ae5f 3941;
395
396__END__
397
398=head1 NAME
399
400Moose::Exporter - make an import() and unimport() just like Moose.pm
401
402=head1 SYNOPSIS
403
404 package MyApp::Moose;
405
e606ae5f 406 use Moose ();
407 use Moose::Exporter;
408
409 Moose::Exporter->setup_import_methods(
82ad7804 410 with_caller => [ 'has_rw', 'sugar2' ],
e606ae5f 411 as_is => [ 'sugar3', \&Some::Random::thing ],
412 also => 'Moose',
413 );
414
82ad7804 415 sub has_rw {
6daad0b9 416 my ($caller, $name, %options) = @_;
82ad7804 417 Class::MOP::Class->initialize($caller)->add_attribute($name,
418 is => 'rw',
419 %options,
420 );
421 }
422
e606ae5f 423 # then later ...
424 package MyApp::User;
425
426 use MyApp::Moose;
427
428 has 'name';
6daad0b9 429 has_rw 'size';
e606ae5f 430 thing;
431
432 no MyApp::Moose;
433
434=head1 DESCRIPTION
435
436This module encapsulates the logic to export sugar functions like
437C<Moose.pm>. It does this by building custom C<import> and C<unimport>
24aef5e1 438methods for your module, based on a spec you provide.
e606ae5f 439
24aef5e1 440It also lets you "stack" Moose-alike modules so you can export
e606ae5f 441Moose's sugar as well as your own, along with sugar from any random
442C<MooseX> module, as long as they all use C<Moose::Exporter>.
443
10e0127a 444To simplify writing exporter modules, C<Moose::Exporter> also imports
445C<strict> and C<warnings> into your exporter module, as well as into
446modules that use it.
447
e606ae5f 448=head1 METHODS
449
450This module provides two public methods:
451
4b68e0de 452=over 4
453
454=item B<< Moose::Exporter->setup_import_methods(...) >>
e606ae5f 455
456When you call this method, C<Moose::Exporter> build custom C<import>
457and C<unimport> methods for your module. The import method will export
458the functions you specify, and you can also tell it to export
459functions exported by some other module (like C<Moose.pm>).
460
461The C<unimport> method cleans the callers namespace of all the
462exported functions.
463
464This method accepts the following parameters:
465
4b68e0de 466=over 8
e606ae5f 467
468=item * with_caller => [ ... ]
469
470This a list of function I<names only> to be exported wrapped and then
471exported. The wrapper will pass the name of the calling package as the
472first argument to the function. Many sugar functions need to know
473their caller so they can get the calling package's metaclass object.
474
475=item * as_is => [ ... ]
476
477This a list of function names or sub references to be exported
478as-is. You can identify a subroutine by reference, which is handy to
479re-export some other module's functions directly by reference
480(C<\&Some::Package::function>).
481
e05fb8ae 482If you do export some other packages function, this function will
483never be removed by the C<unimport> method. The reason for this is we
484cannot know if the caller I<also> explicitly imported the sub
485themselves, and therefore wants to keep it.
486
e606ae5f 487=item * also => $name or \@names
488
489This is a list of modules which contain functions that the caller
490wants to export. These modules must also use C<Moose::Exporter>. The
491most common use case will be to export the functions from C<Moose.pm>.
ae8817b6 492Functions specified by C<with_caller> or C<as_is> take precedence over
493functions exported by modules specified by C<also>, so that a module
494can selectively override functions exported by another module.
e606ae5f 495
496C<Moose::Exporter> also makes sure all these functions get removed
497when C<unimport> is called.
498
499=back
500
4b68e0de 501=item B<< Moose::Exporter->build_import_methods(...) >>
e606ae5f 502
503Returns two code refs, one for import and one for unimport.
504
505Used by C<setup_import_methods>.
506
4b68e0de 507=back
508
e606ae5f 509=head1 IMPORTING AND init_meta
510
511If you want to set an alternative base object class or metaclass
512class, simply define an C<init_meta> method in your class. The
513C<import> method that C<Moose::Exporter> generates for you will call
514this method (if it exists). It will always pass the caller to this
515method via the C<for_class> parameter.
516
517Most of the time, your C<init_meta> method will probably just call C<<
518Moose->init_meta >> to do the real work:
519
520 sub init_meta {
521 shift; # our class name
522 return Moose->init_meta( @_, metaclass => 'My::Metaclass' );
523 }
524
525=head1 METACLASS TRAITS
526
527The C<import> method generated by C<Moose::Exporter> will allow the
528user of your module to specify metaclass traits in a C<-traits>
529parameter passed as part of the import:
530
531 use Moose -traits => 'My::Meta::Trait';
532
533 use Moose -traits => [ 'My::Meta::Trait', 'My::Other::Trait' ];
534
535These traits will be applied to the caller's metaclass
536instance. Providing traits for an exporting class that does not create
537a metaclass for the caller is an error.
538
539=head1 AUTHOR
540
541Dave Rolsky E<lt>autarch@urth.orgE<gt>
542
543This is largely a reworking of code in Moose.pm originally written by
544Stevan Little and others.
545
546=head1 COPYRIGHT AND LICENSE
547
2840a3b2 548Copyright 2009 by Infinity Interactive, Inc.
e606ae5f 549
550L<http://www.iinteractive.com>
551
552This library is free software; you can redistribute it and/or modify
553it under the same terms as Perl itself.
554
555=cut