File Coverage

blib/lib/Xporter.pm
Criterion Covered Total %
statement 78 112 69.6
branch 21 50 42.0
condition 17 61 27.8
subroutine 14 17 82.3
pod 0 4 0.0
total 130 244 53.2


line stmt bran cond sub pod time code
1             #!/usr/bin/perl
2 7   50 7   60190 BEGIN { require $_.".pm" && $_->import for qw(strict warnings) }
3             # vim=:SetNumberAndWidth
4             =encoding utf-8
5              
6             =head1 NAME
7              
8             Xporter - Alternative Exporter with persistant defaults & auto-ISA
9              
10             =head1 VERSION
11              
12             Version "0.1.1"
13              
14             =cut
15              
16             { package Xporter;
17 7   50 7   445 BEGIN { require $_.".pm" && $_->import for qw(strict warnings) }
18             our $VERSION='0.1.2';
19             our @CARP_NOT;
20 7     7   1470 use mem(@CARP_NOT=(__PACKAGE__));
  7         525  
  7         52  
21             # 0.1.2 - Bad version check found in self-testing;
22             # Added test against 4 version formats
23             # 0.1.1 - Bad use of modern proptype (_) for old perls
24             # 0.1.0 - Bugfix: only match user input after stripping sigels or "nots" (!^-)
25             # - Feature addition, in addition to a global, (solo) 'not'
26             # at the beginning of a list to zero the default exports,
27             # individual items in EXPORTS can be excluded by prefixing them
28             # with a negating prefix (!^-);
29             # - Added new test case for specific exclusion
30             # - NOTE: blocking an export will ignore type as will asking for a non-dflt
31             # 0.0.14 - Documentation update
32             # 0.0.13 - Bug fix in string version compare -- didn't add leading
33             # zeros for numeric compares;
34             # 0.0.12 - Add version tests to test 3 forms of version: v-string,
35             # numeric version, and string-based version.
36             # If universal method $VERSION doesn't exist, call our own
37             # method.
38             # 0.0.11 - Add a Configure_depends to see if that satisfies the one
39             # test client that is broken (sigh)
40             # 0.0.10 - Remove P from another test (missed one); Having to use
41             # replacement lang features is torture on my RSI
42             # 0.0.9 - add alternate version format for ExtMM(this system sucks)
43             # - remove diagnostic messages from tests (required P)
44             # 0.0.8 - add current dep for BUILD_REQ of ExtMM
45             # 0.0.7 - 'require' version# bugfix
46             # 0.0.6 - comment cleanup; Change CONFIGURE_REQUIRES to TEST_REQUIRES
47             # 0.0.5 - export inheritance test written to highlight a problem area
48             # - problem area addessed; converted to use efficient jump table
49             # 0.0.4 - documentation additions;
50             # - added tests & corrected any found problems
51             # 0.0.3 - added auto-ISA-adding (via push) when this mod is used.
52             # - added check for importing 'import' to disable auto-ISA-add
53             # 0.0.2 - Allow for "!" as first arg to import to turn off default export
54             # NOTE: defaults are defaults when using EXPORT_OK as well;
55             # One must specifically disable defaults to turn them off.
56             # 0.0.1 - Initial split of code from iomon
57             #
58             #require 5.8.0;
59            
60             # Alternate export-import method that doesn't undefine defaults by
61             # default
62              
63             sub add_to_caller_ISA($$) {
64 7     7 0 12 my ($pkg, $caller) = @_;
65            
66 7 50   7   544 if ($pkg eq __PACKAGE__) { no strict 'refs';
  7         10  
  7         2735  
  7         26  
67 7 50       13 unshift @{$caller."::ISA"}, $pkg unless grep /$pkg/, @{$caller."::ISA"};
  7         82  
  7         55  
68             }
69             }
70              
71             # adapted from Core::Types to avoid circular include
72 46     46   69 sub _EhV($*) { my ($arg, $field) = @_;
73 46 100 66     887 (ref $arg && 'HASH' eq ref $arg) &&
74             defined $field && exists $arg->{$field} ? $arg->{$field} : undef
75             }
76              
77             sub cmp_ver($$) {
78 0     0 0 0 my ($v1, $v2) = @_;
79 0   0     0 for (my $i=0; $i<@$v2 && $i<@$v1; ++$i) {
80 0         0 my ($v1p, $v1_num, $v1s) = ($v1->[$i] =~ /^([^\d]*)(\d+)([^\d]*)$/);
81 0         0 my ($v2p, $v2_num, $v2s) = ($v2->[$i] =~ /^([^\d]*)(\d+)([^\d]*)$/);
82 0 0       0 my $maxlen = $v1_num > $v2_num ? $v1_num : $v2_num;
83 0   0     0 my $r = sprintf("%s%0*d%s", $v1p||"", $maxlen, $v1_num, $v1s||"") cmp
      0        
      0        
      0        
84             sprintf("%s%0*d%s", $v2p||"", $maxlen, $v2_num, $v2s||"");
85 0 0       0 return -1 if $r<0;
86 0 0       0 return 0 if $r>0;
87             }
88 0         0 return 0;
89             }
90              
91              
92             sub _version_specified($$;$) {
93 0     0   0 my ($pkg, $requires) = @_;
94 0         0 my $pkg_ver;
95 7     7   42 { no strict 'refs';
  7         10  
  7         3283  
  0         0  
96 0   0     0 $pkg_ver = ${$pkg."::VERSION"} || '(undef)';
97             }
98 0         0 my @v1=split /_|\./, $pkg_ver;
99 0         0 my @v2=split /_|\./, $requires;
100 0 0 0     0 if (@v1>2 || @v2>2) {
101 0 0       0 return if cmp_ver(\@v1, \@v2) >= 0;
102             } else {
103 0 0 0     0 return if $pkg_ver && ($pkg_ver cmp $requires)>=0;
104 0 0 0     0 return if $pkg_ver ne '(undef)' && $pkg_ver >= $requires;
105             }
106 0         0 require Carp;
107 0         0 Carp::croak(sprintf "module %s %s required. This is only %s",
108             $pkg, $requires, $pkg_ver);
109             }
110              
111              
112             our %exporters;
113              
114              
115             our $tc2proto = {'&' => '&', '$' => '$', '@' => '@', '%' => '%',
116             '*' => '*', '!' => '!', '-' => '!', '^' => '!'};
117              
118 0     0 0 0 sub list(;*) { return @_ }
119              
120             sub op_prefix;
121             sub op_prefix {
122 46 50   46 0 97 return ($_, undef) unless $_;
123 46         88 my $type = substr $_, 0, 1;
124 46         87 my $mapped_op = _EhV $tc2proto, $type;
125 46 100       163 if ($mapped_op) {
    50          
126 15         29 $_ = substr($_,1);
127 15 50       40 if ($mapped_op eq '!') {
128 0         0 ($_, $type, undef ) = op_prefix() }
129 31         57 } elsif ($type =~ /\w/) { $mapped_op=$type='&' }
130 46         162 ($_, $type, $mapped_op);
131            
132             }
133             sub import {
134 16     16   171123 my $pkg = shift;
135 16         58 my ($caller, $fl, $ln) = (caller);
136 7     7   34 no strict 'refs';
  7         16  
  7         957  
137              
138              
139             #*{$caller."::import"}=
140             #\&{__PACKAGE__."::import"} if !exists ${$caller."::import"}->{CODE};
141              
142 16 50 66     209 if (@_ && $_[0] && $_[0] =~ /^(v?[\d\._]+)$/) {
      33        
143 0         0 my @t=split /\./, $_[0];
144 7     7   40 no warnings;
  7         16  
  7         1031  
145 0 0 0     0 if ($pkg->can("VERSION") && @t<3 && $1 ) {
      0        
146 0         0 $pkg->VERSION($1) }
147             else {
148 0         0 _version_specified($pkg, $1); }
149 0         0 shift;
150             }
151              
152 16 100       61 if ($pkg eq __PACKAGE__) { # we are exporting
153 8 100 100     57 if (@_ && $_[0] eq q(import)) {
154 7     7   30 no strict q(refs);
  7         14  
  7         744  
155 1         2 *{$caller."::import"} = \*{$pkg."::import"};
  1         5  
  1         3  
156             } else {
157 7         22 add_to_caller_ISA($pkg, $caller);
158             }
159 8         20 $exporters{$caller} = 1;
160 8         3650 return 1;
161             }
162              
163 8         18 my ($export, $exportok, $exporttags);
164              
165 7     7   36 { no strict q(refs);
  7         17  
  7         9088  
  8         12  
166 8   50     20 $export = \@{$pkg."::"."EXPORT"} || [];
167 8   50     24 $exportok = \@{$pkg."::"."EXPORT_OK"} || [];
168 8         15 $exporttags = \%{$pkg."::"."EXPORT_TAGS"};
  8         46  
169             }
170            
171 8         381 my @allowed_exports = (@$export, @$exportok);
172              
173 8 100 66     108 if (@_ and $_[0] and $_[0] eq '!' || $_[0] eq '-' ) {
      66        
      33        
174 1         260 printf("Export RESET\n");
175 1         4 $export=[];
176 1         2 shift @_;
177             }
178              
179 8         20 for my $pat (@_) { # filter individual params
180 7         15 $_ = $pat; # passed to op_prefix
181 7         24 my ($name, $type, $mapped_op ) = op_prefix();
182 7 50       251 if ($mapped_op eq '!') {
    50          
183 0 0       0 if (grep /$name/, @$export) {
184 0         0 my @new_export = grep { !/$name/ } @$export;
  0         0  
185 0         0 $export=\@new_export;
186             }
187             } elsif (grep /$name/, @allowed_exports) {
188             #printf("allowing export of %s\n", $pat);
189 7         41 push @$export, $pat ;
190             }
191             }
192              
193              
194 8         25 for(@$export) {
195 39         47 my ($type, $mapped_op);
196             #printf("_=%s:", $_||"undef");
197 39         74 ($_, $type, $mapped_op) = op_prefix;
198             #printf("_=%s, t=%s, mapped=%s\n", $_||"undef", $type||"undef", $mapped_op||"undef");
199 39 50       93 if ($mapped_op) {
200 39 50       89 print "skip exp of $_\n" if $mapped_op eq '!';
201 39 50       86 next if $mapped_op eq '!';
202             } else {
203 0         0 require Carp;
204 0   0     0 Carp::croak("Unknown type ". ($type||"(undef)") . " in " . ($_||"(undef)"));
      0        
205             }
206 39         69 my $colon_name = "::" . $_ ;
207 39         82 my ($exf, $imf) = ( $pkg . $colon_name, $caller . $colon_name);
208 7     7   37 no strict q(refs);
  7         14  
  7         1403  
209 39         341 my $case = {
210             '&' => \&$exf,
211             '$' => \$$exf,
212             '@' => \@$exf,
213             '%' => \%$exf,
214             '*' => *$exf};
215 39         13605 *$imf = $case->{$type};
216             }
217             }
218             1}
219              
220              
221             =head1 SYNOPIS
222              
223             In the "Exporting" module:
224              
225             { package module_adder [optional version];
226             use warnings; use strict;
227             use mem; # to allow using module in same file
228             our (@EXPORT, @EXPORT_OK);
229             our $lastsum;
230             our @lastargs;
231             use Xporter(@EXPORT=qw(adder $lastsum @lastargs),
232             @EXPORT_OK=qw(print_last_result));
233              
234             sub adder($$) {@lastargs=@_; $lastsum=$_[0]+$_[1]}
235             sub print_last_result () {
236             use P; # using P allows answer printed or as string
237             if (@lastargs && defined $lastsum){
238             P "%s = %s\n", (join ' + ' , @lastargs), $lastsum;
239             }
240             }
241             }
242              
243             In C-ing module (same or different file)
244              
245             package main; use warnings; use strict;
246             use module_adder qw(print_last_result);
247              
248             adder 4,5;
249              
250             Printing output:
251              
252             print_last_result();
253              
254             #Result:
255            
256             4 + 5 = 9
257              
258             (Or in a test:)
259            
260             ok(print_last_result eq "4 + 5 = 9", "a pod test");
261              
262             =head1 DESCRIPTION
263              
264             C provides C functionality similar to L with
265             some different rules to simplify common cases.
266              
267             The primary difference, in C is that the default C list
268             remains the default C list unless the user specifically asks for it
269             to not be included, whereas in L, asking for any additional
270             exports from the C list, clears the default C list.
271              
272             C makes it easy to reset or clear the default so that choice
273             is left to the user.
274              
275             To reset the default C list to empty, a bare I ('-') or
276             I sign ('!') is placed as the first parameter in the client's import
277             list.
278              
279             =head3 Example
280              
281             Suppose a module has exports:
282              
283             our (@EXPORT, @EXPORT_OK);
284             use Xporter(@EXPORT=qw(one $two %three @four),
285             @EXPORT_OK=qw(&five));
286              
287             In the using module, to only import symbols 'two' and 'five',
288             one would use:
289              
290             =head3 Example
291              
292             use MODULENAME qw(! $two five);
293              
294             That negates the default C list, and allows selective import
295             of the values wanted from either, the default C or the
296             C lists. I modules in the default list don't need
297             to be reiterated in the OK list as they are already assumed to be
298             "OK" to export having been in the default list.
299              
300             (New in 0.1) It is also possible to negate only 1 item from the
301             default C list, as well as import optional symbols in
302             1 statement.
303              
304             =head3 Example
305              
306             use MODULENAME qw(!$two five); #or
307             use MODULENAME qw(!two five);
308              
309             Only export C from the default export list will be
310             excluded. Whereas export C will be added to the list
311             of items to import.
312              
313             Other functions of Exporter are not currently implemented, though
314             certainly requests and code donations made via the CPAN issue database
315             will be considered if possible.
316              
317             =head2 Types and Type Export
318              
319             Listing the EXPORT and EXPORT_OK assignments as params to Xporter will
320             allow their types to be available to importing modules at compile time.
321             the L module was provided as a generic way to force declarations
322             into memory during Perl's initial BEGIN phase so they will be in effect
323             when the program runs.
324              
325             =head2 Version Strings
326              
327             Version strings in the form of a decimal fraction, (0.001001), a
328             V-String (v1.2.1 with no quotes), or a version string
329             ('1.1.1' or 'v1.1.1') are supported, though note, versions in
330             different formats are not interchangeable. The format specified
331             in a module's documentation should be used.
332              
333              
334              
335              
336              
337