File Coverage

blib/lib/Sub/Import.pm
Criterion Covered Total %
statement 78 88 88.6
branch 6 10 60.0
condition 1 3 33.3
subroutine 18 22 81.8
pod n/a
total 103 123 83.7


line stmt bran cond sub pod time code
1 2     2   59650 use strict;
  2         5  
  2         77  
2 2     2   10 use warnings;
  2         4  
  2         107  
3              
4             package Sub::Import;
5             {
6             $Sub::Import::VERSION = '1.001';
7             }
8             # ABSTRACT: import routines from most anything using Sub::Exporter
9              
10 2     2   9 use B qw(svref_2object);
  2         3  
  2         159  
11 2     2   11 use Carp ();
  2         4  
  2         37  
12 2     2   9 use Exporter ();
  2         4  
  2         46  
13 2     2   7685 use Params::Util qw(_CLASS _CLASSISA);
  2         12189  
  2         148  
14 2     2   1932 use Sub::Exporter ();
  2         16629  
  2         932  
15              
16              
17             sub import {
18 2     2   28 my ($self, $target, @args) = @_;
19              
20 2         8 my $import = $self->_get_import($target);
21              
22 2         9 @_ = ($target, @args);
23 2         15 goto &$import;
24             }
25              
26             sub unimport {
27 0     0   0 my ($self, $target, @args) = @_;
28              
29 0         0 my $unimport = $self->_get_unimport($target);
30              
31 0         0 @_ = ($target, @args);
32 0         0 goto &$unimport;
33             }
34              
35             sub _get_unimport {
36 0     0   0 my ($self, $target) = @_;
37              
38 0         0 $self->_get_methods($target)->{unimport};
39             }
40              
41             sub _get_import {
42 2     2   4 my ($self, $target) = @_;
43              
44 2         8 $self->_get_methods($target)->{import};
45             }
46              
47             my %GENERATED_METHODS;
48             sub _get_methods {
49 2     2   5 my ($self, $target) = @_;
50              
51 2   33     18 $GENERATED_METHODS{$target} ||= $self->_create_methods($target);
52             }
53              
54             sub _require_class {
55 2     2   4 my ($self, $class) = @_;
56              
57 2 50       140 Carp::croak("invalid package name: $class") unless _CLASS($class);
58              
59 2         30 local $@;
60 2 50       118 eval "require $class; 1" or die;
61              
62 2         8 return;
63             }
64              
65             sub _is_sexy {
66 2     2   6 my ($self, $class) = @_;
67              
68 2         3 local $@;
69 2         5 my $isa;
70 2         5 my $ok = eval {
71 2         44 my $obj = svref_2object( $class->can('import') );
72 2         48 my $importer_pkg = $obj->START->stashpv;
73 2         94 $isa = _CLASSISA($importer_pkg, 'Sub::Exporter');
74 2         43 1;
75             };
76              
77 2         12 return $isa;
78             }
79              
80             my $EXPORTER_IMPORT;
81 2     2   548 BEGIN { $EXPORTER_IMPORT = Exporter->can('import'); }
82             sub _is_exporterrific {
83 1     1   3 my ($self, $class) = @_;
84            
85 1         1 my $class_import = do {
86 1         2 local $@;
87 1         2 eval { $class->can('import') };
  1         6  
88             };
89              
90 1 50       4 return unless $class_import;
91 1         5 return $class_import == $EXPORTER_IMPORT;
92             }
93              
94             sub _create_methods {
95 2     2   5 my ($self, $target) = @_;
96              
97 2         5 $self->_require_class($target);
98              
99 2 100       9 if ($self->_is_sexy($target)) {
    50          
100             return {
101 1         17 import => $target->can("import"),
102             unimport => $target->can("unimport"),
103             };
104             } elsif ($self->_is_exporterrific($target)) {
105 1         4 return $self->_create_methods_exporter($target);
106             } else {
107 0         0 return $self->_create_methods_fallback($target);
108             }
109             }
110              
111             sub __filter_subs {
112 2     2   4 my ($self, $exports) = @_;
113              
114 2         6 @$exports = map { s/\A&//; $_ } grep { /\A[&_a-z]/ } @$exports;
  1         3  
  1         7  
  1         5  
115             }
116              
117             sub _create_methods_exporter {
118 1     1   2 my ($self, $target) = @_;
119              
120 2     2   151 no strict 'refs';
  2         5  
  2         482  
121              
122 1         2 my @ok = @{ $target . "::EXPORT_OK" };
  1         4  
123 1         2 my @default = @{ $target . "::EXPORT" };
  1         6  
124 1         1 my %groups = %{ $target . "::EXPORT_TAGS" };
  1         6  
125              
126 1         4 $self->__filter_subs($_) for (\@ok, \@default, values %groups);
127              
128 1         2 my @all = do {
129 1         2 my %seen;
130 1         2 grep { ! $seen{$_}++ } @ok, @default;
  1         5  
131             };
132              
133 1         8 my $import = Sub::Exporter::build_exporter({
134             exports => \@all,
135             groups => {
136             %groups,
137             default => \@default,
138             }
139             });
140              
141             return {
142             import => $import,
143 0     0     unimport => sub { die "unimport not handled for Exporter via Sub::Import" },
144 1         175 };
145             }
146              
147             sub _create_methods_fallback {
148 0     0     my ($self, @target) = @_;
149              
150 0           Carp::confess(
151             "Sub::Import only handles Sub::Exporter and Exporter-based import methods"
152             );
153             }
154              
155             1;
156              
157             __END__