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