File Coverage

blib/lib/IO/NestedCapture.pm
Criterion Covered Total %
statement 192 209 91.8
branch 37 44 84.0
condition 6 6 100.0
subroutine 36 38 94.7
pod 15 16 93.7
total 286 313 91.3


line stmt bran cond sub pod time code
1             package IO::NestedCapture;
2              
3 6     6   260707 use strict;
  6         18  
  6         230  
4 6     6   31 use warnings;
  6         10  
  6         676  
5              
6 6     6   35 use Carp;
  6         15  
  6         686  
7 6     6   27709 use File::Temp;
  6         265393  
  6         1416  
8              
9             require Exporter;
10             our @ISA = qw/ Exporter /;
11              
12             our @EXPORT_OK = qw/
13             CAPTURE_NONE
14             CAPTURE_STDIN
15             CAPTURE_STDOUT
16             CAPTURE_IN_OUT
17             CAPTURE_STDERR
18             CAPTURE_IN_ERR
19             CAPTURE_OUT_ERR
20             CAPTURE_ALL
21              
22             capture_in
23             capture_out
24             capture_err
25             capture_in_out
26             capture_out_err
27             capture_in_err
28             capture_all
29             /;
30              
31             our %EXPORT_TAGS = (
32             'constants' => [ qw/
33             CAPTURE_NONE
34             CAPTURE_STDIN
35             CAPTURE_STDOUT
36             CAPTURE_IN_OUT
37             CAPTURE_STDERR
38             CAPTURE_IN_ERR
39             CAPTURE_OUT_ERR
40             CAPTURE_ALL
41             / ],
42              
43             'subroutines' => [ qw/
44             capture_in
45             capture_out
46             capture_err
47             capture_in_out
48             capture_out_err
49             capture_in_err
50             capture_all
51             / ],
52             );
53              
54             our $VERSION = '1.03';
55              
56 6     6   62 use constant CAPTURE_NONE => 0;
  6         19  
  6         391  
57 6     6   33 use constant CAPTURE_STDIN => 1;
  6         12  
  6         244  
58 6     6   34 use constant CAPTURE_STDOUT => 2;
  6         14  
  6         245  
59 6     6   38 use constant CAPTURE_IN_OUT => 3;
  6         13  
  6         263  
60 6     6   32 use constant CAPTURE_STDERR => 4;
  6         12  
  6         236  
61 6     6   83 use constant CAPTURE_IN_ERR => 5;
  6         14  
  6         262  
62 6     6   28 use constant CAPTURE_OUT_ERR => 6;
  6         11  
  6         301  
63 6     6   30 use constant CAPTURE_ALL => 7;
  6         8  
  6         7529  
64              
65             =head1 NAME
66              
67             IO::NestedCapture - module for performing nested STD* handle captures
68              
69             =head1 SYNOPSIS
70              
71             use IO::NestedCapture qw/ :subroutines /;
72              
73             my $in = IO::NestedCapture->get_next_in;
74             print $in "Harry\n";
75             print $in "Ron\n";
76             print $in "Hermione\n";
77              
78             capture_in_out {
79             my @profs = qw( Dumbledore Flitwick McGonagall );
80             while () {
81             my $prof = shift @prof;
82             print STDOUT "$_ favors $prof";
83             }
84             };
85              
86             my $out = IO::NestedCapture->get_last_out;
87             while (<$out>) {
88             print;
89             }
90              
91             # This program will output:
92             # Harry favors Dumbledore
93             # Ron favors Flitwick
94             # Hermione favors McGonagall
95              
96             =head1 DESCRIPTION
97              
98             This module was partially inspired by L, but is intended for a very different purpose and is not otherwise related to that package. In particular, I have a need for some pretty aggressive output/input redirection in a web project I'm working on. I'd like to be able to pipe input into a subroutine and then capture that subroutines output to be used as input on the next.
99              
100             I was using a fairly clumsy, fragile, and brute force method for doing this. If you're interested, you can take a look at the code on PerlMonks.org:
101              
102             http://perlmonks.org/?node_id=459275
103              
104             This module implements a much saner approach that involves only a single tie per file handle (regardless of what you want to tie it to). It works by tying the STDIN, STDOUT, and STDERR file handles. Then, uses internal tied class logic to handle any nested use or other work.
105              
106             With this module you can capture any combination of STDIN, STDOUT, and STDERR. In the case of STDIN, you may feed any input into capture you want (or even set it to use another file handle). For STDOUT and STDERR you may review the full output of these or prior to capture set a file handle that will receive all the data during the capture.
107              
108             As of version 1.02 of this library, there are two different interfaces to the library. The object-oriented version was first, but the new subroutine interface is a little less verbose and a little safer.
109              
110             =head2 OBJECT-ORIENTED INTERFACE
111              
112             The object-oriented interface is available either through the C class directly or through a single instance of the class available through the C method.
113              
114             my $capture = IO::NestedCapture->instance;
115             $capture->start(CAPTURE_STDOUT);
116            
117             # Is the same as...
118              
119             IO::NestedCapture->start(CAPTURE_STDOUT);
120              
121             It doesn't really make much difference.
122              
123             You will probably want to important one, several, or all of the capture constants to use this interface.
124              
125             =head2 SUBROUTINE INTERFACE
126              
127             This interface is available via the import of one of the capture subroutines (or not if you want to fully qualify the names):
128              
129             use IO::NestedCapture 'capture_out';
130             capture_out {
131             # your code to print to STDOUT here...
132             };
133              
134             # Is similar to...
135             IO::NestedCapture::capture_err {
136             # your code to print to STDERR here...
137             };
138              
139             This interface has the advantage of being a little more concise and automatically starts and stops the capture before and after running the code block. This will help avoid typos and other mistakes in your code, such as forgetting to call C when you are done.
140              
141             =head2 NESTED CAPTURE SUBROUTINES
142              
143             These subroutines are used with the subroutine interface. (See L.) These subroutines actually use the object-oriented interface internally, so they merely provide a convenient set of shortcuts to it that may help save you some trouble.
144              
145             For each subroutine, the subroutine captures one or more file handles before running the given code block and uncaptures them after. In case of an exception, the file handles will still be uncaptured properly. Make sure to put a semi-colon after each method call.
146              
147             To manipulate the input, output, and error handles before or after the capture, you will still need to use parts of the object-oriented interface.
148              
149             You will want to import the subroutines you want to use when you load the C object:
150              
151             use IO::NestedCapture qw/ capture_in capture_out /;
152              
153             or you can import all of the capture subroutines with the C<:subroutines> mnemonic:
154              
155             use IO::NestedCapture ':subroutines';
156              
157             In place of a block, you may also give a code reference as the argument to any of these calls:
158              
159             sub foo { print "bah\n" }
160              
161             capture_all \&foo;
162              
163             This will run the subroutine foo (with no arguments) and capture the streams it reads/writes. Also, each of the capture subroutines return the return value of the block or rethrow the exceptions raised in the block after stopping the capture.
164              
165             =over
166              
167             =item capture_in { };
168              
169             This subroutine captures C for the duration of the given block.
170              
171             =cut
172              
173             sub capture_in(&) {
174 1     1 1 551 my $self = IO::NestedCapture->instance;
175 1         2 my $code = shift;
176              
177             # capture input and then turn off capture, even on error
178 1         4 $self->start(CAPTURE_STDIN);
179 1         2 my $result = eval {
180 1         3 $code->();
181             };
182 1         6 my $ERROR = $@;
183 1         3 $self->stop(CAPTURE_STDIN);
184              
185             # rethrow any errors or return normally
186 1 50       5 die $ERROR if $ERROR;
187 0         0 return $result;
188             }
189              
190             =item capture_out { };
191              
192             This subroutine captures C for the duration of the given block.
193              
194             =cut
195              
196             sub capture_out(&) {
197 1     1 1 903 my $self = IO::NestedCapture->instance;
198 1         1 my $code = shift;
199              
200             # capture output and then turn off capture, even on error
201 1         12 $self->start(CAPTURE_STDOUT);
202 1         2 my $result = eval {
203 1         3 $code->();
204             };
205 1         7 my $ERROR = $@;
206 1         4 $self->stop(CAPTURE_STDOUT);
207              
208             # rethrow any errors or return normally
209 1 50       8 die $ERROR if $ERROR;
210 0         0 return $result;
211             }
212              
213             =item capture_err { };
214              
215             This subroutine captures C for the duration of the given block.
216              
217             =cut
218              
219             sub capture_err(&) {
220 1     1 1 965 my $self = IO::NestedCapture->instance;
221 1         2 my $code = shift;
222              
223             # capture error output and then turn off capture, even on error
224 1         3 $self->start(CAPTURE_STDERR);
225 1         2 my $result = eval {
226 1         3 $code->();
227             };
228 1         6 my $ERROR = $@;
229 1         2 $self->stop(CAPTURE_STDERR);
230              
231             # rethrow any errors or return normally
232 1 50       5 die $ERROR if $ERROR;
233 0         0 return $result;
234             }
235              
236             =item capture_in_out { };
237              
238             This subroutine captures C and C for the duration of the given block.
239              
240             =cut
241              
242             sub capture_in_out(&) {
243 1     1 1 1113 my $self = IO::NestedCapture->instance;
244 1         2 my $code = shift;
245              
246             # capture input and output and then turn off capture, even on error
247 1         3 $self->start(CAPTURE_IN_OUT);
248 1         2 my $result = eval {
249 1         4 $code->();
250             };
251 1         8 my $ERROR = $@;
252 1         4 $self->stop(CAPTURE_IN_OUT);
253              
254             # rethrow any errors or return normally
255 1 50       7 die $ERROR if $ERROR;
256 0         0 return $result;
257             }
258              
259             =item capture_in_err { };
260              
261             This subroutine captures C and C for the duration of the given block.
262              
263             =cut
264              
265             sub capture_in_err(&) {
266 1     1 1 1503 my $self = IO::NestedCapture->instance;
267 1         3 my $code = shift;
268              
269             # capture input and error output and then turn off capture, even on error
270 1         4 $self->start(CAPTURE_IN_ERR);
271 1         3 my $result = eval {
272 1         4 $code->();
273             };
274 1         8 my $ERROR = $@;
275 1         3 $self->stop(CAPTURE_IN_ERR);
276              
277             # rethrow any errors or return normally
278 1 50       7 die $ERROR if $ERROR;
279 0         0 return $result;
280             }
281              
282             =item capture_out_err { };
283              
284             This subroutine captures C and C for the duration of the given block.
285              
286             =cut
287              
288             sub capture_out_err(&) {
289 1     1 1 1604 my $self = IO::NestedCapture->instance;
290 1         2 my $code = shift;
291              
292             # capture output and error output and then turn off capture, even on error
293 1         4 $self->start(CAPTURE_OUT_ERR);
294 1         2 my $result = eval {
295 1         4 $code->();
296             };
297 1         9 my $ERROR = $@;
298 1         5 $self->stop(CAPTURE_OUT_ERR);
299              
300             # rethrow any errors or return normally
301 1 50       13 die $ERROR if $ERROR;
302 0         0 return $result;
303             }
304              
305             =item capture_all { };
306              
307             This subroutine captures C, C, and C for the duration of the given block.
308              
309             =cut
310              
311             sub capture_all(&) {
312 1     1 1 1659 my $self = IO::NestedCapture->instance;
313 1         2 my $code = shift;
314              
315             # capture input, output and error output and then turn off capture, even on
316             # error
317 1         10 $self->start(CAPTURE_ALL);
318 1         2 my $result = eval {
319 1         5 $code->();
320             };
321 1         7 my $ERROR = $@;
322 1         4 $self->stop(CAPTURE_ALL);
323              
324             # rethrow any errors or return normally
325 1 50       6 die $ERROR if $ERROR;
326 0         0 return $result;
327             }
328              
329             =back
330              
331             =head2 NESTED CAPTURE CONSTANTS
332              
333             These constants are used with the object-oriented interface. (See L.)
334              
335             You will want to import the constants you want when you load the C module:
336              
337             use IO::NestedCapture qw/ CAPTURE_STDIN CAPTURE_STDOUT /;
338              
339             or you may import all of them with the C<:constants> mnemonic.:
340              
341             use IO::NestedCapture ':constants';
342              
343             =over
344              
345             =item CAPTURE_STDIN
346              
347             Used to start or stop capture on STDIN.
348              
349             =item CAPTURE_STDOUT
350              
351             Used to start or stop capture on STDOUT.
352              
353             =item CAPTURE_STDERR
354              
355             Used to start or stop capture on STDERR.
356              
357             =item CAPTURE_IN_OUT
358              
359             Used to start or stop capture on STDIN and STDOUT. This is a shortcut for "C".
360              
361             =item CAPTURE_IN_ERR
362              
363             Used to start or stop cpature on STDIN and STDERR. This is a shortcut for "C".
364              
365             =item CAPTURE_OUT_ERR
366              
367             Used to start or stop capture on STDOUT and STDERR. This is a shortcut for "C".)
368              
369             =item CAPTURE_ALL
370              
371             Used to start or stop capture on STDIN, STDOUT, and STDERR. This is a shortcut for "C".
372              
373             =back
374              
375             =head2 OBJECT-ORIENTED CAPTURE METHODS
376              
377             These are the methods used for the object-oriented interface. (See L.)
378              
379             =over
380              
381             =item $capture = IO::NestedCapture-Einstance;
382              
383             Retrieves an instance of the singleton. Use of this method is optional.
384              
385             =cut
386              
387             my $instance;
388             sub instance {
389             # We've already got one...
390 117 100   117 1 1664 return $instance if $instance;
391              
392             # I told 'im we already got one...
393 5         14 my $class = shift;
394 5         26 return $instance = bless {}, $class;
395             }
396              
397             =item IO::NestedCapture-Estart($capture_what)
398              
399             =item $capture-Estart($capture_what)
400              
401             The C<$capture_what> variable is a bit field that should be set to one or more of the L bit-or'd together. Until this method is called, the STD* handles are not tied to the C interface. The tie will only occur on the very first call to this method. After that, the nesting is handled with stacks internal to the C singleton.
402              
403             If you're capturing STDIN, you should be sure to fill in the input using the C method first if you want there to be any to be read.
404              
405             If you're capturing STDOUT or STDERR, you should be sure to set the file handles to output too, if you want to do that before calling this method.
406              
407             =cut
408              
409             my %fhs = (
410             CAPTURE_STDIN() => 'STDIN',
411             CAPTURE_STDOUT() => 'STDOUT',
412             CAPTURE_STDERR() => 'STDERR',
413             );
414              
415             sub start {
416 28     28 1 8957 my $self = shift->instance;
417 28         57 my $capture_what = shift;
418              
419             # check parameters for sanity
420 28 100       279 $capture_what >= CAPTURE_NONE
421             or croak "start() called without specifying which handles to capture.";
422 27 100       215 $capture_what <= CAPTURE_ALL
423             or croak "start() called with unknown capture parameters.";
424              
425             # For each capture constant asked to start, let's make sure it's tied and
426             # then push us up onto the next level
427 26         63 for my $capcon ((CAPTURE_STDIN, CAPTURE_STDOUT, CAPTURE_STDERR)) {
428 76 100       317 if ($capture_what & $capcon) {
429            
430             # figure out what we're checking
431 35         76 my $fh = $fhs{$capcon};
432              
433 6     6   39 no strict 'refs';
  6         12  
  6         2969  
434              
435             # croak if it's tied to the wrong thingy, tie it if we're untied
436 35 100 100     295 if (tied(*$fh) && !UNIVERSAL::isa(tied(*$fh), 'IO::NestedCapture')) {
    100          
437 1         108 croak "start() failed because $fh is not tied as expected.";
438             } elsif (!tied(*$fh)) {
439 27         135 tie *$fh, 'IO::NestedCapture', $fh;
440             }
441              
442             # grab the one being prepped or create it
443 34         78 my $pushed_fh;
444 34         49 my $pushed_reset = 0;
445 34 100       111 if ($pushed_fh = delete $self->{"${fh}_next"}) {
446            
447             # if this is our own file handle, we want to go back to the top
448             # of the file before starting. if this is the user's file
449             # handle, we won't mess with it.
450 9         29 my $next_reset = delete $self->{"${fh}_next_reset"};
451 9 100       513 seek $pushed_fh, 0, 0 if $next_reset;
452             } else {
453 25         95 $pushed_fh = File::Temp::tempfile;
454 25         16264 $pushed_reset = 1;
455             }
456              
457             # put this one on top of the file handle stack
458 34         57 push @{ $self->{"${fh}_current"} }, $pushed_fh;
  34         191  
459 34         54 push @{ $self->{"${fh}_current_reset"} }, $pushed_reset;
  34         134  
460             }
461             }
462             }
463              
464             =item IO::NestedCapture-Estop($uncapture_what)
465              
466             =item $capture-Estop($uncapture_what)
467              
468             The C<$uncapture_what> variable is a bit field that should be set to one or more of the L bit-or'd together. If this method is called and the internal nesting state shows that this is the last layer to remove, the associated STD* handles are untied. If C<$uncapture_what> indicates that a certain handle should be uncaptured, but it isn't currently captured, an error will be thrown.
469              
470             =cut
471              
472             sub stop {
473 28     28 1 29292 my $self = shift->instance;
474 28         55 my $uncapture_what = shift;
475              
476             # check parameters for sanity
477 28 100       285 $uncapture_what > 0
478             or croak "stop() called without specifying which handles to uncapture.";
479 27 100       254 $uncapture_what <= CAPTURE_ALL
480             or croak "stop() called with unknown uncapture parameters.";
481              
482             # For each uncapture constant asked to stop, check to make sure we're
483             # stopping after one or more starts, pop the file handle, and untie if it's
484             # the last one
485 26         56 for my $uncapcon ((CAPTURE_STDIN, CAPTURE_STDOUT, CAPTURE_STDERR)) {
486 74 100       278 if ($uncapture_what & $uncapcon) {
487             # figure out what we're checking
488 36         72 my $fh = $fhs{$uncapcon};
489              
490             # is this in use or should we croak?
491 36 100 100     337 (defined $self->{"${fh}_current"} && @{ $self->{"${fh}_current"} })
  35         317  
492             or croak "stop() asked to stop $fh, but it wasn't started";
493              
494 34         59 $self->{"${fh}_last"} = pop @{ $self->{"${fh}_current"} };
  34         125  
495 34         811 seek $self->{"${fh}_last"}, 0, 0
496 34 100       654 if pop @{ $self->{"${fh}_current_reset"} };
497              
498 34 100       128 unless (@{ $self->{"${fh}_current"} }) {
  34         121  
499 6     6   49 no strict 'refs';
  6         12  
  6         5649  
500 27         227 untie *$fh;
501             }
502             }
503             }
504             }
505              
506             =item $handle = IO::NestedCapture-Eget_next_in
507              
508             =item $handle = $capture-Eget_next_in
509              
510             This method returns the file handle that will be used for STDIN after the next call to C. If one has not been set using C, then a seekable file handle will be created. If you just use the automatically created file handle (which is created using L), then C will seek to the top of the file handle before use.
511              
512             =cut
513              
514             sub get_next_in {
515 9     9 1 2706 my $self = shift->instance;
516              
517 9 100       39 unless ($self->{'STDIN_next'}) {
518 8         43 $self->{'STDIN_next'} = File::Temp::tempfile;
519 8         6363 $self->{'STDIN_next_reset'} = 1;
520             }
521              
522 9         34 return $self->{'STDIN_next'};
523             }
524              
525             =item IO::NestedCapture-Eset_next_in($handle)
526              
527             =item $capture-Ein($handle)
528              
529             The given file handle is used as the file handle to read from after C is called. If you set a file handle yourself, you must make sure that it is ready to be read from when you call C (i.e., the file handle pointer won't be reset to the top of the file automatically).
530              
531             =cut
532              
533             sub set_next_in {
534 1     1 1 4 my $self = shift->instance;
535 1         10 my $handle = shift;
536              
537 1         3 $self->{'STDIN_next'} = $handle;
538 1         3 delete $self->{'STDIN_next_reset'};
539              
540 1         2 return;
541             }
542              
543             =item $handle = IO::NestedCapture-Eget_last_out
544              
545             =item $handle = $capture-Eget_last_out
546              
547             Retrieve the file handle used to capture the output prior to the previous call to C. If this file handle was automatically generated (i.e., not set with C, then the file pointer will already be set to the top of the file and ready to read).
548              
549             =cut
550              
551             sub get_last_out {
552 9     9 1 4661 my $self = shift->instance;
553 9         46 return $self->{'STDOUT_last'};
554             }
555              
556             =item IO::NestedCapture-Eset_next_out($handle)
557              
558             =item $capture-Eset_next_out($handle)
559              
560             Install your own file handle to capture the output following the next call to C. Make sure the file handle is in the exact state you want before calling C.
561              
562             =cut
563              
564             sub set_next_out {
565 0     0 1 0 my $self = shift->instance;
566 0         0 my $handle = shift;
567              
568 0         0 $self->{'STDOUT_next'} = $handle;
569 0         0 delete $self->{'STDOUT_next_reset'};
570              
571 0         0 return;
572             }
573              
574             =item $handle = IO::NestedCapture-Eget_last_error
575              
576             =item $handle = $capture-Eget_last_error
577              
578             Retrieve the file handle used to capture the error output prior to the previous call to C. If this file handle was automatically generated (i.e., not set with C, then the file pointer will already be set to the top of the file and ready to read).
579              
580             =cut
581              
582             sub get_last_err {
583 3     3 0 23095 my $self = shift->instance;
584 3         13 return $self->{'STDERR_last'};
585             }
586              
587             =item IO::NestedCapture-Eset_next_err($handle)
588              
589             =item $capture-Eset_next_err($handle)
590              
591             Install your own file handle to capture the error output following the next call to C. Make sure the file handle is in the exact state you want before calling C.
592              
593             =cut
594              
595             sub set_next_err {
596 0     0 1 0 my $self = shift->instance;
597 0         0 my $handle = shift;
598              
599 0         0 $self->{'STDERR_next'} = $handle;
600 0         0 delete $self->{'STDERR_next_reset'};
601              
602 0         0 return;
603             }
604              
605             =back
606              
607             =cut
608              
609             # The rest of this is private tie stuff...
610              
611             # Okay, so the documentation lies. This isn't really a singleton, but the extra
612             # objects are internally used as ties only.
613             sub TIEHANDLE {
614 27     27   45 my $class = shift;
615 27         76 my $instance = $class->instance;
616              
617             # Make a non-singleton tie class... shhhhhh.
618 27         242 my $self = bless {
619             instance => $instance,
620             fh => shift,
621             }, $class;
622             }
623              
624             sub WRITE {
625 1     1   305 my $self = shift;
626 1         3 my $buf = shift;
627 1         3 my $len = shift;
628 1         2 my $off = shift;
629              
630             # load state
631 1         2 my $capture = $self->{instance};
632 1         2 my $fh = $self->{fh};
633              
634             # write
635 1         58 syswrite $capture->{"${fh}_current"}[-1], $buf, $len, $off;
636             }
637              
638             sub PRINT {
639 33     33   8377 my $self = shift;
640              
641             # load state
642 33         212 my $capture = $self->{instance};
643 33         46 my $fh = $self->{fh};
644 33         85 my $handle = $capture->{"${fh}_current"}[-1];
645              
646             # write
647 33         305 print $handle @_;
648             }
649              
650             sub PRINTF {
651 1     1   8 my $self = shift;
652            
653             # load state
654 1         3 my $capture = $self->{instance};
655 1         2 my $fh = $self->{fh};
656 1         4 my $handle = $capture->{"${fh}_current"}[-1];
657              
658             # write
659 1         23 printf $handle @_;
660             }
661              
662             sub READ {
663 1     1   538 my $self = shift;
664              
665             # load state
666 1         2 my $capture = $self->{instance};
667 1         3 my $fh = $self->{fh};
668 1         4 my $handle = $capture->{"${fh}_current"}[-1];
669              
670             # read
671 1         13 read $handle, $_[0], $_[1], $_[2];
672             }
673              
674             sub READLINE {
675 39     39   4524 my $self = shift;
676              
677             # load state
678 39         62 my $capture = $self->{instance};
679 39         69 my $fh = $self->{fh};
680 39         97 my $handle = $capture->{"${fh}_current"}[-1];
681              
682             # read
683 39         481 readline $handle;
684             }
685              
686             sub GETC {
687 7     7   605 my $self = shift;
688              
689             # load state
690 7         12 my $capture = $self->{instance};
691 7         10 my $fh = $self->{fh};
692 7         16 my $handle = $capture->{"${fh}_current"}[-1];
693              
694             # read
695 7         46 getc $handle;
696             }
697              
698             sub CLOSE {
699 1     1   3 my $self = shift;
700              
701             # load state
702 1         4 my $capture = $self->{instance};
703 1         3 my $fh = $self->{fh};
704 1         296 my $handle = $capture->{"${fh}_current"}[-1];
705              
706             # close
707 1         357 close $handle;
708             }
709              
710             =head1 EXPORTS
711              
712             This module exports all of the constants used with the object-oriented interface and the subroutines used with the subroutine interface.
713              
714             See L for the specific constant names or use C<:constants> to import all the constants.
715              
716             See L for the specific subroutine names or use C<:subroutines> to import all the subroutines.
717              
718             =head1 SEE ALSO
719              
720             L
721              
722             =head1 AUTHOR
723              
724             Andrew Sterling Hanenkamp, Ehanenkamp@cpan.orgE
725              
726             =head1 COPYRIGHT AND LICENSE
727              
728             Copyright 2005 Andrew Sterling Hanenkamp.
729              
730             This code is licensed and distributed under the same terms as Perl itself.
731              
732             =cut
733              
734             1