File Coverage

blib/lib/Importer.pm
Criterion Covered Total %
statement 340 353 96.3
branch 154 176 87.5
condition 126 175 72.0
subroutine 41 41 100.0
pod 17 19 89.4
total 678 764 88.7


line stmt bran cond sub pod time code
1             package Importer;
2 7     7   208877 use strict; no strict 'refs';
  7     7   125  
  7         499  
  7         94  
  7         94  
  7         207  
3 7     7   94 use warnings; no warnings 'once';
  7     7   73  
  7         487  
  7         125  
  7         115  
  6         19624  
4              
5             our $VERSION = '0.026';
6              
7             my %SIG_TO_SLOT = (
8             '&' => 'CODE',
9             '$' => 'SCALAR',
10             '%' => 'HASH',
11             '@' => 'ARRAY',
12             '*' => 'GLOB',
13             );
14              
15             our %IMPORTED;
16              
17             # This will be used to check if an import arg is a version number
18             my %NUMERIC = map +($_ => 1), 0 .. 9;
19              
20             sub IMPORTER_MENU() {
21             return (
22             export_ok => [qw/optimal_import/],
23             export_anon => {
24             import => sub {
25 0     1   0 my $from = shift;
26 0         0 my @caller = caller(0);
27              
28 0 50 0     0 _version_check($from, \@caller, shift @_) if @_ && $NUMERIC{substr($_[0], 0, 1)};
29              
30 0         0 my $file = _mod_to_file($from);
31 0 50       0 _load_file(\@caller, $file) unless $INC{$file};
32              
33 0 50       0 return if optimal_import($from, $caller[0], \@caller, @_);
34              
35 0         0 my $self = __PACKAGE__->new(
36             from => $from,
37             caller => \@caller,
38             );
39              
40 0         0 $self->do_import($caller[0], @_);
41             },
42             },
43 1     2 0 9 );
44             }
45              
46             ###########################################################################
47             #
48             # These are class methods
49             # import and unimport are what you would expect.
50             # import_into and unimport_from are the indirect forms you can use in other
51             # package import() methods.
52             #
53             # These all attempt to do a fast optimal-import if possible, then fallback to
54             # the full-featured import that constructs an object when needed.
55             #
56              
57             sub import {
58 15     16   11098 my $class = shift;
59              
60 15         122 my @caller = caller(0);
61              
62 15 100 66     160 _version_check($class, \@caller, shift @_) if @_ && $NUMERIC{substr($_[0], 0, 1)};
63              
64 14 100       154 return unless @_;
65              
66 13         33 my ($from, @args) = @_;
67              
68 13         40 my $file = _mod_to_file($from);
69 13 100       52 _load_file(\@caller, $file) unless $INC{$file};
70              
71 13 100       224248 return if optimal_import($from, $caller[0], \@caller, @args);
72              
73 11         67 my $self = $class->new(
74             from => $from,
75             caller => \@caller,
76             );
77              
78 11         38 $self->do_import($caller[0], @args);
79             }
80              
81             sub unimport {
82 5     6   3470 my $class = shift;
83 5         39 my @caller = caller(0);
84              
85 5         20 my $self = $class->new(
86             from => $caller[0],
87             caller => \@caller,
88             );
89              
90 5         20 $self->do_unimport(@_);
91             }
92              
93             sub import_into {
94 2     2 1 3413 my $class = shift;
95 2         7 my ($from, $into, @args) = @_;
96              
97 2         3 my @caller;
98              
99 2 50       18 if (ref($into)) {
    100          
100 0         0 @caller = @$into;
101 0         0 $into = $caller[0];
102             }
103             elsif ($into =~ m/^\d+$/) {
104 1         10 @caller = caller($into + 1);
105 1         4 $into = $caller[0];
106             }
107             else {
108 1         7 @caller = caller(0);
109             }
110              
111 2         11 my $file = _mod_to_file($from);
112 2 50       8 _load_file(\@caller, $file) unless $INC{$file};
113              
114 2 50       6 return if optimal_import($from, $into, \@caller, @args);
115              
116 0         0 my $self = $class->new(
117             from => $from,
118             caller => \@caller,
119             );
120              
121 0         0 $self->do_import($into, @args);
122             }
123              
124             sub unimport_from {
125 4     4 1 3942 my $class = shift;
126 4         11 my ($from, @args) = @_;
127              
128 4         7 my @caller;
129 4 100       22 if ($from =~ m/^\d+$/) {
130 2         17 @caller = caller($from + 1);
131 2         5 $from = $caller[0];
132             }
133             else {
134 2         14 @caller = caller(0);
135             }
136              
137 4         16 my $self = $class->new(
138             from => $from,
139             caller => \@caller,
140             );
141              
142 4         12 $self->do_unimport(@args);
143             }
144              
145             ###########################################################################
146             #
147             # Constructors
148             #
149              
150             sub new {
151 50     50 1 37402 my $class = shift;
152 50         127 my %params = @_;
153              
154 50   100     204 my $caller = $params{caller} || [caller()];
155              
156             die "You must specify a package to import from at $caller->[1] line $caller->[2].\n"
157 50 100       118 unless $params{from};
158              
159             return bless {
160             from => $params{from},
161             caller => $params{caller}, # Do not use our caller.
162 49         230 }, $class;
163             }
164              
165             ###########################################################################
166             #
167             # Shortcuts for getting symbols without any namespace modifications
168             #
169              
170             sub get {
171 2     2 1 2279 my $proto = shift;
172 2         13 my @caller = caller(1);
173              
174 2 100       10 my $self = ref($proto) ? $proto : $proto->new(
175             from => shift(@_),
176             caller => \@caller,
177             );
178              
179 2         5 my %result;
180 2     4   41 $self->do_import($caller[0], @_, sub { $result{$_[0]} = $_[1] });
  4         10  
181 2         77 return \%result;
182             }
183              
184             sub get_list {
185 2     2 1 2750 my $proto = shift;
186 2         15 my @caller = caller(1);
187              
188 2 100       10 my $self = ref($proto) ? $proto : $proto->new(
189             from => shift(@_),
190             caller => \@caller,
191             );
192              
193 2         6 my @result;
194 2     4   12 $self->do_import($caller[0], @_, sub { push @result => $_[1] });
  4         11  
195 2         25 return @result;
196             }
197              
198             sub get_one {
199 3     3 1 2733 my $proto = shift;
200 3         19 my @caller = caller(1);
201              
202 3 100       14 my $self = ref($proto) ? $proto : $proto->new(
203             from => shift(@_),
204             caller => \@caller,
205             );
206              
207 3         6 my $result;
208 3     4   19 $self->do_import($caller[0], @_, sub { $result = $_[1] });
  4         6  
209 3         41 return $result;
210             }
211              
212             ###########################################################################
213             #
214             # Object methods
215             #
216              
217             sub do_import {
218 18     18 1 34 my $self = shift;
219              
220 18         45 my ($into, $versions, $exclude, $import, $set) = $self->parse_args(@_);
221              
222             # Exporter supported multiple version numbers being listed...
223 18 100       53 _version_check($self->from, $self->get_caller, @$versions) if @$versions;
224              
225 18 50       145 return unless @$import;
226              
227 18 100       49 $self->_handle_fail($into, $import) if $self->menu($into)->{fail};
228 18         71 $self->_set_symbols($into, $exclude, $import, $set);
229             }
230              
231             sub do_unimport {
232 11     11 1 3819 my $self = shift;
233              
234 11         24 my $from = $self->from;
235 11 100       38 my $imported = $IMPORTED{$from} or $self->croak("'$from' does not have any imports to remove");
236              
237 9         21 my %allowed = map { $_ => 1 } @$imported;
  25         58  
238              
239 9 100       36 my @args = @_ ? @_ : @$imported;
240              
241 9         13 my $stash = \%{"$from\::"};
  9         28  
242              
243 9         23 for my $name (@args) {
244 18         28 $name =~ s/^&//;
245              
246 18 100       49 $self->croak("Sub '$name' was not imported using " . ref($self)) unless $allowed{$name};
247              
248 16         49 my $glob = delete $stash->{$name};
249 16         46 local *GLOBCLONE = *$glob;
250              
251 16         33 for my $type (qw/SCALAR HASH ARRAY FORMAT IO/) {
252 80 100       102 next unless defined(*{$glob}{$type});
  80         1713  
253 18         28 *{"$from\::$name"} = *{$glob}{$type}
  18         76  
  18         33  
254             }
255             }
256             }
257              
258 161     161 1 735 sub from { $_[0]->{from} }
259              
260             sub from_file {
261 5     5 1 925 my $self = shift;
262              
263 5   66     29 $self->{from_file} ||= _mod_to_file($self->{from});
264              
265 5         14 return $self->{from_file};
266             }
267              
268             sub load_from {
269 3     3 1 47 my $self = shift;
270 3         7 my $from_file = $self->from_file;
271 3         5 my $this_file = __FILE__;
272              
273 3 100       10 return if $INC{$from_file};
274              
275 2         5 my $caller = $self->get_caller;
276              
277 2         7 _load_file($caller, $from_file);
278             }
279              
280             sub get_caller {
281 57     57 1 91 my $self = shift;
282 57 100       185 return $self->{caller} if $self->{caller};
283              
284 14         21 my $level = 1;
285 14         107 while(my @caller = caller($level++)) {
286 27 100 66     184 return \@caller if @caller && !$caller[0]->isa(__PACKAGE__);
287 13 50       85 last unless @caller;
288             }
289              
290             # Fallback
291 0         0 return [caller(0)];
292             }
293              
294             sub croak {
295 15     15 1 35 my $self = shift;
296 15         29 my ($msg) = @_;
297 15         30 my $caller = $self->get_caller;
298 15   50     38 my $file = $caller->[1] || 'unknown file';
299 15   50     30 my $line = $caller->[2] || 'unknown line';
300 15         110 die "$msg at $file line $line.\n";
301             }
302              
303             sub carp {
304 2     2 1 619 my $self = shift;
305 2         5 my ($msg) = @_;
306 2         6 my $caller = $self->get_caller;
307 2   50     6 my $file = $caller->[1] || 'unknown file';
308 2   50     6 my $line = $caller->[2] || 'unknown line';
309 2         27 warn "$msg at $file line $line.\n";
310             }
311              
312             sub menu {
313 136     136 1 1233 my $self = shift;
314 136         205 my ($into) = @_;
315              
316 136 100       245 $self->croak("menu() requires the name of the destination package")
317             unless $into;
318              
319 135         236 my $for = $self->{menu_for};
320 135 100 100     449 delete $self->{menu} if $for && $for ne $into;
321 135   66     407 return $self->{menu} || $self->reload_menu($into);
322             }
323              
324             sub reload_menu {
325 34     34 1 96 my $self = shift;
326 34         58 my ($into) = @_;
327              
328 34 100       98 $self->croak("reload_menu() requires the name of the destination package")
329             unless $into;
330              
331 33         69 my $from = $self->from;
332              
333 33 100       53 if (my $menu_sub = *{"$from\::IMPORTER_MENU"}{CODE}) {
  33         183  
334             # Hook, other exporter modules can define this method to be compatible with
335             # Importer.pm
336              
337 9         20 my %got = $from->$menu_sub($into, $self->get_caller);
338              
339 9   100     941 $got{export} ||= [];
340 9   100     26 $got{export_ok} ||= [];
341 9   100     27 $got{export_tags} ||= {};
342 9   100     28 $got{export_fail} ||= [];
343 9   100     31 $got{export_anon} ||= {};
344 9   50     44 $got{export_magic} ||= {};
345              
346             $self->croak("'$from' provides both 'generate' and 'export_gen' in its IMPORTER_MENU (They are exclusive, module must pick 1)")
347 9 100 100     36 if $got{export_gen} && $got{generate};
348              
349 8   100     25 $got{export_gen} ||= {};
350              
351 8         18 $self->{menu} = $self->_build_menu($into => \%got, 1);
352             }
353             else {
354 24         43 my %got;
355 24         48 $got{export} = \@{"$from\::EXPORT"};
  24         84  
356 24         34 $got{export_ok} = \@{"$from\::EXPORT_OK"};
  24         79  
357 24         32 $got{export_tags} = \%{"$from\::EXPORT_TAGS"};
  24         93  
358 24         38 $got{export_fail} = \@{"$from\::EXPORT_FAIL"};
  24         67  
359 24         35 $got{export_gen} = \%{"$from\::EXPORT_GEN"};
  24         62  
360 24         68 $got{export_anon} = \%{"$from\::EXPORT_ANON"};
  24         67  
361 24         35 $got{export_magic} = \%{"$from\::EXPORT_MAGIC"};
  24         65  
362              
363 24         66 $self->{menu} = $self->_build_menu($into => \%got, 0);
364             }
365              
366 31         104 $self->{menu_for} = $into;
367              
368 31         117 return $self->{menu};
369             }
370              
371             sub _build_menu {
372 32     32   53 my $self = shift;
373 32         68 my ($into, $got, $new_style) = @_;
374              
375 32         60 my $from = $self->from;
376              
377 32   50     95 my $export = $got->{export} || [];
378 32   50     75 my $export_ok = $got->{export_ok} || [];
379 32   50     64 my $export_tags = $got->{export_tags} || {};
380 32   50     69 my $export_fail = $got->{export_fail} || [];
381 32   50     60 my $export_anon = $got->{export_anon} || {};
382 32   50     63 my $export_gen = $got->{export_gen} || {};
383 32   50     79 my $export_magic = $got->{export_magic} || {};
384              
385 32         46 my $generate = $got->{generate};
386              
387             $generate ||= sub {
388 7     7   9891 my $symbol = shift;
389 7         40 my ($sig, $name) = ($symbol =~ m/^(\W?)(.*)$/);
390 7   100     29 $sig ||= '&';
391              
392 7         16 my $do = $export_gen->{"${sig}${name}"};
393 7 50 100     44 $do ||= $export_gen->{$name} if !$sig || $sig eq '&';
      33        
394              
395 7 100       12 return undef unless $do;
396              
397 6         19 $from->$do($into, $symbol);
398 32 100 50     207 } if $export_gen && keys %$export_gen;
      66        
399              
400 32         56 my $lookup = {};
401 32         48 my $exports = {};
402 32         91 for my $sym (@$export, @$export_ok, keys %$export_gen, keys %$export_anon) {
403 273         1080 my ($sig, $name) = ($sym =~ m/^(\W?)(.*)$/);
404 273   100     932 $sig ||= '&';
405              
406 273         575 $lookup->{"${sig}${name}"} = 1;
407 273 100       601 $lookup->{$name} = 1 if $sig eq '&';
408              
409 273 100       516 next if $export_gen->{"${sig}${name}"};
410 266 100 100     713 next if $sig eq '&' && $export_gen->{$name};
411 259 50 33     504 next if $got->{generate} && $generate->("${sig}${name}");
412              
413 259         403 my $fqn = "$from\::$name";
414             # We cannot use *{$fqn}{TYPE} here, it breaks for autoloaded subs, this
415             # does not:
416             $exports->{"${sig}${name}"} = $export_anon->{$sym} || (
417             $sig eq '&' ? \&{$fqn} :
418             $sig eq '$' ? \${$fqn} :
419             $sig eq '@' ? \@{$fqn} :
420             $sig eq '%' ? \%{$fqn} :
421 259   66     682 $sig eq '*' ? \*{$fqn} :
422             # Sometimes people (CGI::Carp) put invalid names (^name=) into
423             # @EXPORT. We simply go to 'next' in these cases. These modules
424             # have hooks to prevent anyone actually trying to import these.
425             next
426             );
427             }
428              
429 32   100     274 my $f_import = $new_style || $from->can('import');
430             $self->croak("'$from' does not provide any exports")
431             unless $new_style
432             || keys %$exports
433             || $from->isa('Exporter')
434 32 100 100     216 || ($INC{'Exporter.pm'} && $f_import && $f_import == \&Exporter::import);
      100        
      66        
      66        
      66        
435              
436             # Do not cleanup or normalize the list added to the DEFAULT tag, legacy....
437 31         133 my $tags = {
438             %$export_tags,
439             'DEFAULT' => [ @$export ],
440             };
441              
442             # Add 'ALL' tag unless already specified. We want to normalize it.
443 31   100     194 $tags->{ALL} ||= [ sort grep {m/^[\&\$\@\%\*]/} keys %$lookup ];
  509         1163  
444              
445             my $fail = @$export_fail ? {
446             map {
447 31 100       116 my ($sig, $name) = (m/^(\W?)(.*)$/);
  24         105  
448 24   100     93 $sig ||= '&';
449 24 100       118 ("${sig}${name}" => 1, $sig eq '&' ? ($name => 1) : ())
450             } @$export_fail
451             } : undef;
452              
453 31         125 my $menu = {
454             lookup => $lookup,
455             exports => $exports,
456             tags => $tags,
457             fail => $fail,
458             generate => $generate,
459             magic => $export_magic,
460             };
461              
462 31         113 return $menu;
463             }
464              
465             sub parse_args {
466 31     31 0 1441 my $self = shift;
467 31         88 my ($into, @args) = @_;
468              
469 31         80 my $menu = $self->menu($into);
470              
471 31         102 my @out = $self->_parse_args($into, $menu, \@args);
472 28         51 pop @out;
473 28         262 return @out;
474             }
475              
476             sub _parse_args {
477 47     47   84 my $self = shift;
478 47         138 my ($into, $menu, $args, $is_tag) = @_;
479              
480 47         109 my $from = $self->from;
481 47         96 my $main_menu = $self->menu($into);
482 47   33     113 $menu ||= $main_menu;
483              
484             # First we strip out versions numbers and setters, this simplifies the logic late.
485 47         104 my @sets;
486             my @versions;
487 47         0 my @leftover;
488 47         100 for my $arg (@$args) {
489 6     7   51 no warnings 'void';
  6         13  
  6         12011  
490              
491             # Code refs are custom setters
492             # If the first character is an ASCII numeric then it is a version number
493 188 100 50     328 push @sets => $arg and next if ref($arg) eq 'CODE';
494 178 100 0     346 push @versions => $arg xor next if $NUMERIC{substr($arg, 0, 1)};
495 175         306 push @leftover => $arg;
496             }
497              
498 47 50       131 $self->carp("Multiple setters specified, only 1 will be used") if @sets > 1;
499 47         75 my $set = pop @sets;
500              
501 47         75 $args = \@leftover;
502 47 100 100     159 @$args = (':DEFAULT') unless $is_tag || @$args || @versions;
      66        
503              
504 47         82 my %exclude;
505             my @import;
506              
507 47         109 while(my $full_arg = shift @$args) {
508 174         247 my $arg = $full_arg;
509 174         265 my $lead = substr($arg, 0, 1);
510              
511 174         210 my ($spec, $exc);
512 174 100       292 if ($lead eq '!') {
513 5         10 $exc = $lead;
514              
515 5 100       9 if ($arg eq '!') {
516             # If the current arg is just '!' then we are negating the next item.
517 1         2 $arg = shift @$args;
518             }
519             else {
520             # Strip off the '!'
521 4         13 substr($arg, 0, 1, '');
522             }
523              
524             # Exporter.pm legacy behavior
525             # negated first item implies starting with default set:
526 5 50 66     24 unshift @$args => ':DEFAULT' unless @import || keys %exclude || @versions;
      66        
527              
528             # Now we have a new lead character
529 5         9 $lead = substr($arg, 0, 1);
530             }
531             else {
532             # If the item is followed by a reference then they are asking us to
533             # do something special...
534 169 100       364 $spec = ref($args->[0]) eq 'HASH' ? shift @$args : {};
535             }
536              
537 174 100       314 if($lead eq ':') {
538 17         47 substr($arg, 0, 1, '');
539 17 100       52 my $tag = $menu->{tags}->{$arg} or $self->croak("$from does not export the :$arg tag");
540              
541 16         133 my (undef, $cvers, $cexc, $cimp, $cset, $newmenu) = $self->_parse_args($into, $menu, $tag, $arg);
542              
543 16 50       44 $self->croak("Exporter specified version numbers (" . join(', ', @$cvers) . ") in the :$arg tag!")
544             if @$cvers;
545              
546 16 50       32 $self->croak("Exporter specified a custom symbol setter in the :$arg tag!")
547             if $cset;
548              
549             # Merge excludes
550 16         45 %exclude = (%exclude, %$cexc);
551              
552 16 100 66     85 if ($exc) {
    100          
553 1 50       15 $exclude{$_} = 1 for grep {!ref($_) && substr($_, 0, 1) ne '+'} map {$_->[0]} @$cimp;
  2         14  
  2         5  
554             }
555             elsif ($spec && keys %$spec) {
556             $self->croak("Cannot use '-as' to rename multiple symbols included by: $full_arg")
557 3 100 66     18 if $spec->{'-as'} && @$cimp > 1;
558              
559 2         4 for my $set (@$cimp) {
560 5         11 my ($sym, $cspec) = @$set;
561              
562             # Start with a blind squash, spec from tag overrides the ones inside.
563 5         15 my $nspec = {%$cspec, %$spec};
564              
565 5 100 66     20 $nspec->{'-prefix'} = "$spec->{'-prefix'}$cspec->{'-prefix'}" if $spec->{'-prefix'} && $cspec->{'-prefix'};
566 5 100 100     18 $nspec->{'-postfix'} = "$cspec->{'-postfix'}$spec->{'-postfix'}" if $spec->{'-postfix'} && $cspec->{'-postfix'};
567              
568 5         11 push @import => [$sym, $nspec];
569             }
570             }
571             else {
572 12         62 push @import => @$cimp;
573             }
574              
575             # New menu
576 15         33 $menu = $newmenu;
577              
578 15         83 next;
579             }
580              
581             # Process the item to figure out what symbols are being touched, if it
582             # is a tag or regex than it can be multiple.
583 157         189 my @list;
584 157 100 66     366 if(ref($arg) eq 'Regexp') {
    100          
585 1         11 @list = sort grep /$arg/, keys %{$menu->{lookup}};
  1         26  
586             }
587             elsif($lead eq '/' && $arg =~ m{^/(.*)/$}) {
588 2         8 my $pattern = $1;
589 2         5 @list = sort grep /$1/, keys %{$menu->{lookup}};
  2         45  
590             }
591             else {
592 154         255 @list = ($arg);
593             }
594              
595             # Normalize list, always have a sigil
596 157 100       225 @list = map {m/^\W/ ? $_ : "\&$_" } @list;
  163         572  
597              
598 157 100       282 if ($exc) {
599 4         21 $exclude{$_} = 1 for @list;
600             }
601             else {
602             $self->croak("Cannot use '-as' to rename multiple symbols included by: $full_arg")
603 153 100 100     334 if $spec->{'-as'} && @list > 1;
604              
605 152         648 push @import => [$_, $spec] for @list;
606             }
607             }
608              
609 44         189 return ($into, \@versions, \%exclude, \@import, $set, $menu);
610             }
611              
612             sub _handle_fail {
613 12     12   35 my $self = shift;
614 12         23 my ($into, $import) = @_;
615              
616 12         22 my $from = $self->from;
617 12         27 my $menu = $self->menu($into);
618              
619             # Historically Exporter would strip the '&' off of sub names passed into export_fail.
620 12 100       67 my @fail = map {my $x = $_->[0]; $x =~ s/^&//; $x} grep $menu->{fail}->{$_->[0]}, @$import or return;
  4         19  
  4         11  
  4         16  
621              
622 3 50       34 my @real_fail = $from->can('export_fail') ? $from->export_fail(@fail) : @fail;
623              
624 3 100       26 if (@real_fail) {
625             $self->carp(qq["$_" is not implemented by the $from module on this architecture])
626 1         8 for @real_fail;
627              
628 1         9 $self->croak("Can't continue after import errors");
629             }
630              
631 2         8 $self->reload_menu($menu);
632 2         5 return;
633             }
634              
635             sub _set_symbols {
636 24     24   6511 my $self = shift;
637 24         48 my ($into, $exclude, $import, $custom_set) = @_;
638              
639 24         62 my $from = $self->from;
640 24         56 my $menu = $self->menu($into);
641 24         67 my $caller = $self->get_caller();
642              
643 6 50 50 7   348 my $set_symbol = $custom_set || eval <<" EOT" || die $@;
  4 50   5   248  
  24         1680  
644             # Inherit the callers warning settings. If they have warnings and we
645             # redefine their subs they will hear about it. If they do not have warnings
646             # on they will not.
647             BEGIN { \${^WARNING_BITS} = \$caller->[9] if defined \$caller->[9] }
648             #line $caller->[2] "$caller->[1]"
649             sub { *{"$into\\::\$_[0]"} = \$_[1] }
650             EOT
651              
652 24         333 for my $set (@$import) {
653 128         240 my ($symbol, $spec) = @$set;
654              
655 128 50       603 my ($sig, $name) = ($symbol =~ m/^(\W)(.*)$/) or die "Invalid symbol: $symbol";
656              
657             # Find the thing we are actually shoving in a new namespace
658 128         259 my $ref = $menu->{exports}->{$symbol};
659 128 100 100     232 $ref ||= $menu->{generate}->($symbol) if $menu->{generate};
660              
661             # Exporter.pm supported listing items in @EXPORT that are not actually
662             # available for export. So if it is listed (lookup) but nothing is
663             # there (!$ref) we simply skip it.
664 128 100 66     280 $self->croak("$from does not export $symbol") unless $ref || $menu->{lookup}->{"${sig}${name}"};
665 127 50       188 next unless $ref;
666              
667 127         197 my $type = ref($ref);
668 127 100       209 $type = 'SCALAR' if $type eq 'REF';
669             $self->croak("Symbol '$sig$name' requested, but reference (" . ref($ref) . ") does not match sigil ($sig)")
670 127 100 66     398 if $ref && $type ne $SIG_TO_SLOT{$sig};
671              
672             # If they directly renamed it then we assume they want it under the new
673             # name, otherwise excludes get kicked. It is useful to be able to
674             # exclude an item in a tag/match where the group has a prefix/postfix.
675 126 100 100     306 next if $exclude->{"${sig}${name}"} && !$spec->{'-as'};
676              
677 123   100     683 my $new_name = join '' => ($spec->{'-prefix'} || '', $spec->{'-as'} || $name, $spec->{'-postfix'} || '');
      66        
      100        
678              
679             # Set the symbol (finally!)
680 123         309 $set_symbol->($new_name, $ref, sig => $sig, symbol => $symbol, into => $into, from => $from, spec => $spec);
681              
682             # The remaining things get skipped with a custom setter
683 123 100       1129 next if $custom_set;
684              
685             # Record the import so that we can 'unimport'
686 109 100       219 push @{$IMPORTED{$into}} => $new_name if $sig eq '&';
  102         247  
687              
688             # Apply magic
689 109         172 my $magic = $menu->{magic}->{$symbol};
690 109 100 66     422 $magic ||= $menu->{magic}->{$name} if $sig eq '&';
691 109 100       5505 $from->$magic(into => $into, orig_name => $name, new_name => $new_name, ref => $ref)
692             if $magic;
693             }
694             }
695              
696             ###########################################################################
697             #
698             # The rest of these are utility functions, not methods!
699             #
700              
701             sub _version_check {
702 9     9   5971 my ($mod, $caller, @versions) = @_;
703              
704 9 100       535 eval <<" EOT" or die $@;
705             #line $caller->[2] "$caller->[1]"
706             \$mod->VERSION(\$_) for \@versions;
707             1;
708             EOT
709             }
710              
711             sub _mod_to_file {
712 19     19   2632 my $file = shift;
713 19         96 $file =~ s{::}{/}g;
714 19         44 $file .= '.pm';
715 19         49 return $file;
716             }
717              
718             sub _load_file {
719 9     9   3429 my ($caller, $file) = @_;
720              
721 9 100       517 eval <<" EOT" || die $@;
722             #line $caller->[2] "$caller->[1]"
723             require \$file;
724             EOT
725             }
726              
727              
728             my %HEAVY_VARS = (
729             IMPORTER_MENU => 'CODE', # Origin package has a custom menu
730             EXPORT_FAIL => 'ARRAY', # Origin package has a failure handler
731             EXPORT_GEN => 'HASH', # Origin package has generators
732             EXPORT_ANON => 'HASH', # Origin package has anonymous exports
733             EXPORT_MAGIC => 'HASH', # Origin package has magic to apply post-export
734             );
735              
736             sub optimal_import {
737 20     20 1 2975 my ($from, $into, $caller, @args) = @_;
738              
739 20   100     82 defined(*{"$from\::$_"}{$HEAVY_VARS{$_}}) and return 0 for keys %HEAVY_VARS;
  86         397  
740              
741             # Default to @EXPORT
742 15 100       43 @args = @{"$from\::EXPORT"} unless @args;
  6         37  
743              
744             # Subs will be listed without sigil in %allowed, all others keep sigil
745             my %allowed = map +(substr($_, 0, 1) eq '&' ? substr($_, 1) : $_ => 1),
746 15 100       30 @{"$from\::EXPORT"}, @{"$from\::EXPORT_OK"};
  15         42  
  15         221  
747              
748             # First check if it is allowed, stripping '&' if necessary, which will also
749             # let scalars in, we will deal with those shortly.
750             # If not allowed return 0 (need to do a heavy import)
751             # if it is allowed then see if it has a CODE slot, if so use it, otherwise
752             # we have a symbol that needs heavy due to non-sub, autoload, etc.
753             # This will not allow $foo to import foo() since '$from' still contains the
754             # sigil making it an invalid symbol name in our globref below.
755             my %final = map +(
756             (!ref($_) && ($allowed{$_} || (substr($_, 0, 1, "") eq '&' && $allowed{$_})))
757 15 100 66     143 ? ($_ => *{"$from\::$_"}{CODE} || return 0)
      100        
758             : return 0
759             ), @args;
760              
761 7 50   2   615 eval <<" EOT" || die $@;
  2 50       127  
762             # If the caller has redefine warnings enabled then we want to warn them if
763             # their import redefines things.
764             BEGIN { \${^WARNING_BITS} = \$caller->[9] if defined \$caller->[9] };
765             #line $caller->[2] "$caller->[1]"
766             (*{"$into\\::\$_"} = \$final{\$_}, push \@{\$Importer::IMPORTED{\$into}} => \$_) for keys %final;
767             1;
768             EOT
769             }
770              
771             1;
772              
773             __END__