File Coverage

Bio/Root/IO.pm
Criterion Covered Total %
statement 235 375 62.6
branch 103 244 42.2
condition 53 147 36.0
subroutine 32 33 96.9
pod 15 15 100.0
total 438 814 53.8


line stmt bran cond sub pod time code
1             package Bio::Root::IO;
2              
3 276     276   1439 use strict;
  276         395  
  276         5840  
4 276     276   828 use Symbol;
  276         391  
  276         12031  
5 276     276   896 use IO::Handle;
  276         384  
  276         8302  
6 276     276   113719 use File::Copy;
  276         453730  
  276         12187  
7 276     276   1202 use Fcntl;
  276         282  
  276         48122  
8 276     276   1090 use base qw(Bio::Root::Root);
  276         336  
  276         119998  
9              
10             # as of 2016, worked on most systems, but will test this in a RC
11             my %modes = ( 0 => 'r', 1 => 'w', 2 => 'rw' );
12              
13             =head1 SYNOPSIS
14              
15             # Use stream I/O in your module
16             $self->{'io'} = Bio::Root::IO->new(-file => "myfile");
17             $self->{'io'}->_print("some stuff");
18             my $line = $self->{'io'}->_readline();
19             $self->{'io'}->_pushback($line);
20             $self->{'io'}->close();
21              
22             # obtain platform-compatible filenames
23             $path = Bio::Root::IO->catfile($dir, $subdir, $filename);
24             # obtain a temporary file (created in $TEMPDIR)
25             ($handle) = $io->tempfile();
26              
27             =head1 DESCRIPTION
28              
29             This module provides methods that will usually be needed for any sort
30             of file- or stream-related input/output, e.g., keeping track of a file
31             handle, transient printing and reading from the file handle, a close
32             method, automatically closing the handle on garbage collection, etc.
33              
34             To use this for your own code you will either want to inherit from
35             this module, or instantiate an object for every file or stream you are
36             dealing with. In the first case this module will most likely not be
37             the first class off which your class inherits; therefore you need to
38             call _initialize_io() with the named parameters in order to set file
39             handle, open file, etc automatically.
40              
41             Most methods start with an underscore, indicating they are private. In
42             OO speak, they are not private but protected, that is, use them in
43             your module code, but a client code of your module will usually not
44             want to call them (except those not starting with an underscore).
45              
46             In addition this module contains a couple of convenience methods for
47             cross-platform safe tempfile creation and similar tasks. There are
48             some CPAN modules related that may not be available on all
49             platforms. At present, File::Spec and File::Temp are attempted. This
50             module defines $PATHSEP, $TEMPDIR, and $ROOTDIR, which will always be set,
51             and $OPENFLAGS, which will be set if either of File::Spec or File::Temp fails.
52              
53             The -noclose boolean (accessed via the noclose method) prevents a
54             filehandle from being closed when the IO object is cleaned up. This
55             is special behavior when a object like a parser might share a
56             filehandle with an object like an indexer where it is not proper to
57             close the filehandle as it will continue to be reused until the end of the
58             stream is reached. In general you won't want to play with this flag.
59              
60             =head1 AUTHOR Hilmar Lapp
61              
62             =cut
63              
64             our ($FILESPECLOADED, $FILETEMPLOADED,
65             $FILEPATHLOADED, $TEMPDIR,
66             $PATHSEP, $ROOTDIR,
67             $OPENFLAGS, $VERBOSE,
68             $ONMAC, $HAS_EOL, );
69              
70             my $TEMPCOUNTER;
71             my $HAS_WIN32 = 0;
72              
73             BEGIN {
74 276     276   406 $TEMPCOUNTER = 0;
75 276         318 $FILESPECLOADED = 0;
76 276         318 $FILETEMPLOADED = 0;
77 276         288 $FILEPATHLOADED = 0;
78 276         298 $VERBOSE = 0;
79              
80             # try to load those modules that may cause trouble on some systems
81 276         334 eval {
82 276         1047 require File::Path;
83 276         419 $FILEPATHLOADED = 1;
84             };
85 276 50       912 if( $@ ) {
86 0 0       0 print STDERR "Cannot load File::Path: $@" if( $VERBOSE > 0 );
87             # do nothing
88             }
89              
90             # If on Win32, attempt to find Win32 package
91 276 50       1387 if($^O =~ /mswin/i) {
92 0         0 eval {
93 0         0 require Win32;
94 0         0 $HAS_WIN32 = 1;
95             };
96             }
97              
98             # Try to provide a path separator. Why doesn't File::Spec export this,
99             # or did I miss it?
100 276 50       1157 if ($^O =~ /mswin/i) {
    50          
101 0         0 $PATHSEP = "\\";
102             } elsif($^O =~ /macos/i) {
103 0         0 $PATHSEP = ":";
104             } else { # unix
105 276         418 $PATHSEP = "/";
106             }
107 276         333 eval {
108 276         728 require File::Spec;
109 276         329 $FILESPECLOADED = 1;
110 276         22689 $TEMPDIR = File::Spec->tmpdir();
111 276         1641 $ROOTDIR = File::Spec->rootdir();
112 276         1068 require File::Temp; # tempfile creation
113 276         569 $FILETEMPLOADED = 1;
114             };
115 276 50       1058 if( $@ ) {
116 0 0       0 if(! defined($TEMPDIR)) { # File::Spec failed
117             # determine tempdir
118 0 0 0     0 if (defined $ENV{'TEMPDIR'} && -d $ENV{'TEMPDIR'} ) {
    0 0        
119 0         0 $TEMPDIR = $ENV{'TEMPDIR'};
120             } elsif( defined $ENV{'TMPDIR'} && -d $ENV{'TMPDIR'} ) {
121 0         0 $TEMPDIR = $ENV{'TMPDIR'};
122             }
123 0 0       0 if($^O =~ /mswin/i) {
    0          
124 0 0       0 $TEMPDIR = 'C:\TEMP' unless $TEMPDIR;
125 0         0 $ROOTDIR = 'C:';
126             } elsif($^O =~ /macos/i) {
127 0 0       0 $TEMPDIR = "" unless $TEMPDIR; # what is a reasonable default on Macs?
128 0         0 $ROOTDIR = ""; # what is reasonable??
129             } else { # unix
130 0 0       0 $TEMPDIR = "/tmp" unless $TEMPDIR;
131 0         0 $ROOTDIR = "/";
132             }
133 0 0 0     0 if (!( -d $TEMPDIR && -w $TEMPDIR )) {
134 0         0 $TEMPDIR = '.'; # last resort
135             }
136             }
137             # File::Temp failed (alone, or File::Spec already failed)
138             # determine open flags for tempfile creation using Fcntl
139 0         0 $OPENFLAGS = O_CREAT | O_EXCL | O_RDWR;
140 0         0 for my $oflag (qw/FOLLOW BINARY LARGEFILE EXLOCK NOINHERIT TEMPORARY/){
141 0         0 my ($bit, $func) = (0, "Fcntl::O_" . $oflag);
142 276     276   1237 no strict 'refs';
  276         328  
  276         22450  
143 0 0       0 $OPENFLAGS |= $bit if eval { $bit = &$func(); 1 };
  0         0  
  0         0  
144             }
145             }
146 276         175189 $ONMAC = "\015" eq "\n";
147             }
148              
149              
150             =head2 new
151              
152             Title : new
153             Usage : my $io = Bio::Root::IO->new( -file => 'data.txt' );
154             Function: Create new class instance. It automatically calls C<_initialize_io>.
155             Args : Same named parameters as C<_initialize_io>.
156             Returns : A Bio::Root::IO object
157              
158             =cut
159              
160             sub new {
161 10839     10839 1 16991 my ($caller, @args) = @_;
162 10839         21094 my $self = $caller->SUPER::new(@args);
163 10839         19921 $self->_initialize_io(@args);
164 10832         14923 return $self;
165             }
166              
167              
168             =head2 _initialize_io
169              
170             Title : _initialize_io
171             Usage : $io->_initialize_io(@params);
172             Function: Initializes filehandle and other properties from the parameters.
173             Args : The following named parameters are currently recognized:
174             -file name of file to read or write to
175             -fh file handle to read or write to (mutually exclusive
176             with -file and -string)
177             -input name of file, or filehandle (GLOB or IO::Handle object)
178             to read of write to
179             -string string to read from (will be converted to filehandle)
180             -url name of URL to open
181             -flush boolean flag to autoflush after each write
182             -noclose boolean flag, when set to true will not close a
183             filehandle (must explicitly call close($io->_fh)
184             -retries number of times to try a web fetch before failure
185             -ua_parms when using -url, hashref of key => value parameters
186             to pass to LWP::UserAgent->new(). A useful value might
187             be, for example, {timeout => 60 } (ua defaults to 180s)
188             Returns : True
189              
190             =cut
191              
192             sub _initialize_io {
193 13052     13052   14993 my($self, @args) = @_;
194              
195 13052         26745 $self->_register_for_cleanup(\&_io_cleanup);
196              
197 13052         40478 my ($input, $noclose, $file, $fh, $string,
198             $flush, $url, $retries, $ua_parms) =
199             $self->_rearrange([qw(INPUT NOCLOSE FILE FH STRING FLUSH URL RETRIES UA_PARMS)],
200             @args);
201              
202 13052         18165 my $mode;
203              
204 13052 50       19128 if ($url) {
205 0   0     0 $retries ||= 5;
206              
207 0         0 require LWP::UserAgent;
208 0         0 my $ua = LWP::UserAgent->new(%$ua_parms);
209 0         0 my $http_result;
210 0         0 my ($handle, $tempfile) = $self->tempfile();
211 0         0 CORE::close($handle);
212              
213 0         0 for (my $try = 1 ; $try <= $retries ; $try++) {
214 0         0 $http_result = $ua->get($url, ':content_file' => $tempfile);
215 0 0       0 $self->warn("[$try/$retries] tried to fetch $url, but server ".
216             "threw ". $http_result->code . ". retrying...")
217             if !$http_result->is_success;
218 0 0       0 last if $http_result->is_success;
219             }
220 0 0       0 $self->throw("Failed to fetch $url, server threw ".$http_result->code)
221             if !$http_result->is_success;
222              
223 0         0 $file = $tempfile;
224 0         0 $mode = '>';
225             }
226              
227 13052         12398 delete $self->{'_readbuffer'};
228 13052         16046 delete $self->{'_filehandle'};
229 13052 100       21106 $self->noclose( $noclose) if defined $noclose;
230             # determine whether the input is a file(name) or a stream
231 13052 100       17401 if ($input) {
232 23 50 0     49 if (ref(\$input) eq 'SCALAR') {
    0 0        
233             # we assume that a scalar is a filename
234 23 100 100     47 if ($file && ($file ne $input)) {
235 1         5 $self->throw("Input file given twice: '$file' and '$input' disagree");
236             }
237 22         22 $file = $input;
238             } elsif (ref($input) &&
239             ((ref($input) eq 'GLOB') || $input->isa('IO::Handle'))) {
240             # input is a stream
241 0         0 $fh = $input;
242             } else {
243             # let's be strict for now
244 0         0 $self->throw("Unable to determine type of input $input: ".
245             "not string and not GLOB");
246             }
247             }
248              
249 13051 100 100     25641 if (defined($file) && defined($fh)) {
250 2         6 $self->throw("Providing both a file and a filehandle for reading - ".
251             "only one please!");
252             }
253              
254 13049 100       18680 if ($string) {
255 47 100 100     187 if (defined($file) || defined($fh)) {
256 3         7 $self->throw("File or filehandle provided with -string, ".
257             "please unset if you are using -string as a file");
258             }
259 44 50   4   552 open $fh, '<', \$string or $self->throw("Could not read string: $!");
  4         18  
  4         5  
  4         23  
260             }
261              
262 13046 100 100     29173 if (defined($file) && ($file ne '')) {
263 1162         3752 $self->file($file);
264 1162         3060 ($mode, $file) = $self->cleanfile;
265 1162   100     4057 $mode ||= '<';
266 1162 100       2948 my $action = ($mode =~ m/>/) ? 'write' : 'read';
267 1162         3670 $fh = Symbol::gensym();
268 1162 100       66327 open $fh, $mode, $file or $self->throw("Could not $action file '$file': $!");
269             }
270              
271 13045 100       19551 if (defined $fh) {
272             # check filehandle to ensure it's one of:
273             # a GLOB reference, as in: open(my $fh, "myfile");
274             # an IO::Handle or IO::String object
275             # the UNIVERSAL::can added to fix Bug2863
276 2430 50 66     30528 unless ( ( ref $fh and ( ref $fh eq 'GLOB' ) )
      33        
      66        
      33        
      66        
277             or ( ref $fh and ( UNIVERSAL::can( $fh, 'can' ) )
278             and ( $fh->isa('IO::Handle')
279             or $fh->isa('IO::String') ) )
280             ) {
281 0         0 $self->throw("Object $fh does not appear to be a file handle");
282             }
283 2430 50       5030 if ($HAS_EOL) {
284 0         0 binmode $fh, ':raw:eol(LF-Native)';
285             }
286 2430         7561 $self->_fh($fh); # if $fh not provided, defaults to STDIN and STDOUT
287             }
288              
289 13045 50       31746 $self->_flush_on_write(defined $flush ? $flush : 1);
290              
291 13045         16936 return 1;
292             }
293              
294              
295             =head2 _fh
296              
297             Title : _fh
298             Usage : $io->_fh($newval);
299             Function: Get or set the file handle for the stream encapsulated.
300             Args : Optional filehandle to use
301             Returns : Filehandle for the stream
302              
303             =cut
304              
305             sub _fh {
306 429299     429299   292873 my ($self, $value) = @_;
307 429299 100       529331 if ( defined $value) {
308 2462         4618 $self->{'_filehandle'} = $value;
309             }
310 429299         678810 return $self->{'_filehandle'};
311             }
312              
313              
314             =head2 mode
315              
316             Title : mode
317             Usage : $io->mode();
318             $io->mode(-force => 1);
319             Function: Determine if the object was opened for reading or writing
320             Args : -force: Boolean. Once mode() has been called, the mode is cached for
321             further calls to mode(). Use this argument to override this
322             behavior and re-check the object's mode.
323             Returns : Mode of the object:
324             'r' for readable
325             'w' for writable
326             'rw' for readable and writable
327             '?' if mode could not be determined (e.g. for a -url)
328              
329             =cut
330              
331             sub mode {
332 8     8 1 10 my ($self, %arg) = @_;
333              
334             # Method 1: IO::Handle::fdopen
335             # my $iotest = new IO::Handle;
336             # $iotest->fdopen( dup(fileno($fh)) , 'r' );
337             # if ($iotest->error == 0) { ... }
338             # It did not actually seem to work under any platform, since there would no
339             # error if the filehandle had been opened writable only. It could not be
340             # hacked around when dealing with unseekable (piped) filehandles.
341              
342             # Method 2: readline, a.k.a. the <> operator
343             # no warnings "io";
344             # my $line = <$fh>;
345             # if (defined $line) {
346             # $self->{'_mode'} = 'r';
347             # ...
348             # It did not work well either because <> returns undef, i.e. querying the
349             # mode() after having read an entire file returned 'w'.
350              
351 8 50 33     45 if ( $arg{-force} || not exists $self->{'_mode'} ) {
352             # Determine stream mode
353 8         5 my $mode;
354 8         13 my $fh = $self->_fh;
355 8 50       13 if (defined $fh) {
356             # use fcntl if not Windows-based
357 8 50       16 if ($^O !~ /MSWin32/) {
358 8         20 my $m = fcntl($fh, F_GETFL, 0);
359 8 50       26 $mode = exists $modes{$m & 3} ? $modes{$m & 3} : '?';
360             } else {
361             # Determine read/write status of filehandle
362 276     276   1207 no warnings 'io';
  276         323  
  276         628028  
363 0 0       0 if ( defined( read $fh, my $content, 0 ) ) {
364             # Successfully read 0 bytes
365 0         0 $mode = 'r'
366             }
367 0 0       0 if ( defined( syswrite $fh, '') ) {
368             # Successfully wrote 0 bytes
369 0   0     0 $mode ||= '';
370 0         0 $mode .= 'w';
371             }
372             }
373             } else {
374             # Stream does not have a filehandle... cannot determine mode
375 0         0 $mode = '?';
376             }
377             # Save mode for future use
378 8         13 $self->{'_mode'} = $mode;
379             }
380 8         24 return $self->{'_mode'};
381             }
382              
383              
384             =head2 file
385              
386             Title : file
387             Usage : $io->file('>'.$file);
388             my $file = $io->file;
389             Function: Get or set the name of the file to read or write.
390             Args : Optional file name (including its mode, e.g. '<' for reading or '>'
391             for writing)
392             Returns : A string representing the filename and its mode.
393              
394             =cut
395              
396             sub file {
397 1168     1168 1 1647 my ($self, $value) = @_;
398 1168 100       2296 if ( defined $value) {
399 1162         2125 $self->{'_file'} = $value;
400             }
401 1168         1446 return $self->{'_file'};
402             }
403              
404              
405             =head2 cleanfile
406              
407             Title : cleanfile
408             Usage : my ($mode, $file) = $io->cleanfile;
409             Function: Get the name of the file to read or write, stripped of its mode
410             ('>', '<', '+>', '>>', etc).
411             Args : None
412             Returns : In array context, an array of the mode and the clean filename.
413              
414             =cut
415              
416             sub cleanfile {
417 1168     1168 1 1307 my ($self) = @_;
418 1168         7421 return ($self->{'_file'} =~ m/^ (\+?[><]{1,2})?\s*(.*) $/x);
419             }
420              
421              
422             =head2 format
423              
424             Title : format
425             Usage : $io->format($newval)
426             Function: Get the format of a Bio::Root::IO sequence file or filehandle. Every
427             object inheriting Bio::Root::IO is guaranteed to have a format.
428             Args : None
429             Returns : Format of the file or filehandle, e.g. fasta, fastq, genbank, embl.
430              
431             =cut
432              
433             sub format {
434 12     12 1 43 my ($self) = @_;
435 12         34 my $format = (split '::', ref($self))[-1];
436 12         38 return $format;
437             }
438              
439              
440             =head2 variant
441              
442             Title : format
443             Usage : $io->format($newval)
444             Function: Get the variant of a Bio::Root::IO sequence file or filehandle.
445             The format variant depends on the specific format used. Note that
446             not all formats have variants. Also, the Bio::Root::IO-implementing
447             modules that require access to variants need to define a global hash
448             that has the allowed variants as its keys.
449             Args : None
450             Returns : Variant of the file or filehandle, e.g. sanger, solexa or illumina for
451             the fastq format, or undef for formats that do not have variants.
452              
453             =cut
454              
455             sub variant {
456 70151     70151 1 47077 my ($self, $variant) = @_;
457 70151 100       76437 if (defined $variant) {
458 70         82 $variant = lc $variant;
459 70         115 my $var_name = '%'.ref($self).'::variant';
460 70         2836 my %ok_variants = eval $var_name; # e.g. %Bio::Assembly::IO::ace::variant
461 70 50       277 if (scalar keys %ok_variants == 0) {
462 0         0 $self->throw("Could not validate variant because global variant ".
463             "$var_name was not set or was empty\n");
464             }
465 70 50       120 if (not exists $ok_variants{$variant}) {
466 0         0 $self->throw("$variant is not a valid variant of the " .
467             $self->format . ' format');
468             }
469 70         191 $self->{variant} = $variant;
470             }
471 70151         134608 return $self->{variant};
472             }
473              
474              
475             =head2 _print
476              
477             Title : _print
478             Usage : $io->_print(@lines)
479             Function: Print lines of text to the IO stream object.
480             Args : List of strings to print
481             Returns : True on success, undef on failure
482              
483             =cut
484              
485             sub _print {
486 28134     28134   20398 my $self = shift;
487 28134   50     28377 my $fh = $self->_fh() || \*STDOUT;
488 28134         51261 my $ret = print $fh @_;
489 28134         58745 return $ret;
490             }
491              
492              
493             =head2 _insert
494              
495             Title : _insert
496             Usage : $io->_insert($string,1)
497             Function: Insert some text in a file at the given line number (1-based).
498             Args : * string to write in file
499             * line number to insert the string at
500             Returns : True
501              
502             =cut
503              
504             sub _insert {
505 2     2   4 my ($self, $string, $line_num) = @_;
506             # Line number check
507 2 50       6 if ($line_num < 1) {
508 0         0 $self->throw("Could not insert text at line $line_num: the minimum ".
509             "line number possible is 1.");
510             }
511             # File check
512 2         3 my ($mode, $file) = $self->cleanfile;
513 2 50       6 if (not defined $file) {
514 0         0 $self->throw('Could not insert a line: IO object was initialized with '.
515             'something else than a file.');
516             }
517             # Everything that needs to be written is written before we read it
518 2         4 $self->flush;
519              
520             # Edit the file line by line (no slurping)
521 2         4 $self->close;
522 2         2 my $temp_file;
523 2         1 my $number = 0;
524 2         80 while (-e "$file.$number.temp") {
525 0         0 $number++;
526             }
527 2         4 $temp_file = "$file.$number.temp";
528 2         7 copy($file, $temp_file);
529 2 50       439 open my $fh1, '<', $temp_file or $self->throw("Could not read temporary file '$temp_file': $!");
530 2 50       80 open my $fh2, '>', $file or $self->throw("Could not write file '$file': $!");
531 2         21 while (my $line = <$fh1>) {
532 2 100       5 if ($. == $line_num) { # right line for new data
533 1         6 print $fh2 $string . $line;
534             }
535             else {
536 1         6 print $fh2 $line;
537             }
538             }
539 2         9 CORE::close $fh1;
540 2         20 CORE::close $fh2;
541 2 50       88 unlink $temp_file or $self->throw("Could not delete temporary file '$temp_file': $!");
542              
543             # Line number check (again)
544 2 50 33     7 if ( $. > 0 && $line_num > $. ) {
545 0         0 $self->throw("Could not insert text at line $line_num: there are only ".
546             "$. lines in file '$file'");
547             }
548             # Re-open the file in append mode to be ready to add text at the end of it
549             # when the next _print() statement comes
550 2 50       40 open my $new_fh, '>>', $file or $self->throw("Could not append to file '$file': $!");
551 2         6 $self->_fh($new_fh);
552             # If file is empty and we're inserting at line 1, simply append text to file
553 2 100 66     10 if ( $. == 0 && $line_num == 1 ) {
554 1         3 $self->_print($string);
555             }
556 2         12 return 1;
557             }
558              
559              
560             =head2 _readline
561              
562             Title : _readline
563             Usage : local $Bio::Root::IO::HAS_EOL = 1;
564             my $io = Bio::Root::IO->new(-file => 'data.txt');
565             my $line = $io->_readline();
566             $io->close;
567             Function: Read a line of input and normalize all end of line characters.
568              
569             End of line characters are typically "\n" on Linux platforms, "\r\n"
570             on Windows and "\r" on older Mac OS. By default, the _readline()
571             method uses the value of $/, Perl's input record separator, to
572             detect the end of each line. This means that you will not get the
573             expected lines if your input has Mac-formatted end of line characters.
574             Also, note that the current implementation does not handle pushed
575             back input correctly unless the pushed back input ends with the
576             value of $/. For each line parsed, its line ending, e.g. "\r\n" is
577             converted to "\n", unless you provide the -raw argument.
578              
579             Altogether it is easier to let the PerlIO::eol module automatically
580             detect the proper end of line character and normalize it to "\n". Do
581             so by setting $Bio::Root::IO::HAS_EOL to 1.
582              
583             Args : -raw : Avoid converting end of line characters to "\n" This option
584             has no effect when using $Bio::Root::IO::HAS_EOL = 1.
585             Returns : Line of input, or undef when there is nothing to read anymore
586              
587             =cut
588              
589             sub _readline {
590 384199     384199   354512 my ($self, %param) = @_;
591 384199 100       395288 my $fh = $self->_fh or return;
592 384187         246989 my $line;
593              
594             # if the buffer been filled by _pushback then return the buffer
595             # contents, rather than read from the filehandle
596 384187 100       225345 if( @{$self->{'_readbuffer'} || [] } ) {
  384187 100       896198  
597 1600         1236 $line = shift @{$self->{'_readbuffer'}};
  1600         2395  
598             } else {
599 382587         539173 $line = <$fh>;
600             }
601              
602             # Note: In Windows the "-raw" parameter has no effect, because Perl already discards
603             # the '\r' from the line when reading in text mode from the filehandle
604             # ($line = <$fh>), and put it back automatically when printing
605 384187 100 66     1601709 if( !$HAS_EOL && !$param{-raw} && (defined $line) ) {
      100        
606             # don't strip line endings if -raw or $HAS_EOL is specified
607 383582         358043 $line =~ s/\015\012/\012/g; # Change all CR/LF pairs to LF
608 383582 50       548170 $line =~ tr/\015/\n/ unless $ONMAC; # Change all single CRs to NEWLINE
609             }
610 384187         952331 return $line;
611             }
612              
613              
614             =head2 _pushback
615              
616             Title : _pushback
617             Usage : $io->_pushback($newvalue)
618             Function: Puts a line previously read with _readline back into a buffer.
619             buffer can hold as many lines as system memory permits.
620              
621             Note that this is only supported for pushing back data ending with
622             the current, localized value of $/. Using this method to push
623             modified data back onto the buffer stack is not supported; see bug
624             843.
625              
626             Args : newvalue
627             Returns : True
628              
629             =cut
630              
631             # fix for bug 843, this reveals some unsupported behavior
632              
633             #sub _pushback {
634             # my ($self, $value) = @_;
635             # if (index($value, $/) >= 0) {
636             # push @{$self->{'_readbuffer'}}, $value;
637             # } else {
638             # $self->throw("Pushing modifed data back not supported: $value");
639             # }
640             #}
641              
642             sub _pushback {
643 1622     1622   1834 my ($self, $value) = @_;
644 1622 100       2557 return unless $value;
645 1620         1288 unshift @{$self->{'_readbuffer'}}, $value;
  1620         3289  
646 1620         2080 return 1;
647             }
648              
649              
650             =head2 close
651              
652             Title : close
653             Usage : $io->close()
654             Function: Closes the file handle associated with this IO instance,
655             excepted if -noclose was specified.
656             Args : None
657             Returns : True
658              
659             =cut
660              
661             sub close {
662 13393     13393 1 13199 my ($self) = @_;
663              
664             # do not close if we explicitly asked not to
665 13393 100       21865 return if $self->noclose;
666              
667 13343 100       24538 if( defined( my $fh = $self->{'_filehandle'} )) {
668 2211         5241 $self->flush;
669 2211 50 66     13068 return if ref $fh eq 'GLOB' && (
      66        
670             \*STDOUT == $fh || \*STDERR == $fh || \*STDIN == $fh
671             );
672              
673             # don't close IO::Strings
674 2210 100 66     35019 CORE::close $fh unless ref $fh && $fh->isa('IO::String');
675             }
676 13342         15946 $self->{'_filehandle'} = undef;
677 13342         11676 delete $self->{'_readbuffer'};
678 13342         22963 return 1;
679             }
680              
681              
682             =head2 flush
683              
684             Title : flush
685             Usage : $io->flush()
686             Function: Flushes the filehandle
687             Args : None
688             Returns : True
689              
690             =cut
691              
692             sub flush {
693 3421     3421 1 4949 my ($self) = shift;
694              
695 3421 50       6637 if( !defined $self->{'_filehandle'} ) {
696 0         0 $self->throw("Flush failed: no filehandle was active");
697             }
698              
699 3421 100       12400 if( ref($self->{'_filehandle'}) =~ /GLOB/ ) {
700 1244         3999 my $oldh = select($self->{'_filehandle'});
701 1244         8976 $| = 1;
702 1244         3419 select($oldh);
703             } else {
704 2177         7407 $self->{'_filehandle'}->flush();
705             }
706 3421         6081 return 1;
707             }
708              
709              
710             =head2 noclose
711              
712             Title : noclose
713             Usage : $io->noclose($newval)
714             Function: Get or set the NOCLOSE flag - setting this to true will prevent a
715             filehandle from being closed when an object is cleaned up or
716             explicitly closed.
717             Args : Optional new value (a scalar or undef)
718             Returns : Value of noclose (a scalar)
719              
720             =cut
721              
722             sub noclose {
723 13427     13427 1 11564 my $self = shift;
724 13427 100       22426 return $self->{'_noclose'} = shift if @_;
725 13393         24258 return $self->{'_noclose'};
726             }
727              
728              
729             =head2 _io_cleanup
730              
731             =cut
732              
733             sub _io_cleanup {
734 11145     11145   10434 my ($self) = @_;
735 11145         18668 $self->close();
736 11145         19220 my $v = $self->verbose;
737              
738             # we are planning to cleanup temp files no matter what
739 11145 50 66     24382 if ( exists($self->{'_rootio_tempfiles'})
      66        
740             and ref($self->{'_rootio_tempfiles'}) =~ /array/i
741             and not $self->save_tempfiles
742             ) {
743 34 50       59 if( $v > 0 ) {
744             warn( "going to remove files ",
745 0         0 join(",", @{$self->{'_rootio_tempfiles'}}),
  0         0  
746             "\n");
747             }
748 34         26 unlink (@{$self->{'_rootio_tempfiles'}} );
  34         742  
749             }
750             # cleanup if we are not using File::Temp
751 11145 0 33     55491 if ( $self->{'_cleanuptempdir'}
      0        
      0        
752             and exists($self->{'_rootio_tempdirs'})
753             and ref($self->{'_rootio_tempdirs'}) =~ /array/i
754             and not $self->save_tempfiles
755             ) {
756 0 0       0 if( $v > 0 ) {
757             warn( "going to remove dirs ",
758 0         0 join(",", @{$self->{'_rootio_tempdirs'}}),
  0         0  
759             "\n");
760             }
761 0         0 $self->rmtree( $self->{'_rootio_tempdirs'});
762             }
763             }
764              
765              
766             =head2 exists_exe
767              
768             Title : exists_exe
769             Usage : $exists = $io->exists_exe('clustalw');
770             $exists = Bio::Root::IO->exists_exe('clustalw')
771             $exists = Bio::Root::IO::exists_exe('clustalw')
772             Function: Determines whether the given executable exists either as file
773             or within the path environment. The latter requires File::Spec
774             to be installed.
775             On Win32-based system, .exe is automatically appended to the program
776             name unless the program name already ends in .exe.
777             Args : Name of the executable
778             Returns : 1 if the given program is callable as an executable, and 0 otherwise
779              
780             =cut
781              
782             sub exists_exe {
783 3     3 1 6 my ($self, $exe) = @_;
784 3 50       5 $self->throw("Must pass a defined value to exists_exe") unless defined $exe;
785 3 50 33     9 $exe = $self if (!(ref($self) || $exe));
786 3 50 33     12 $exe .= '.exe' if(($^O =~ /mswin/i) && ($exe !~ /\.(exe|com|bat|cmd)$/i));
787 3 100 100     38 return $exe if ( -f $exe && -x $exe ); # full path and exists
788              
789             # Ewan's comment. I don't think we need this. People should not be
790             # asking for a program with a pathseparator starting it
791             # $exe =~ s/^$PATHSEP//;
792              
793             # Not a full path, or does not exist. Let's see whether it's in the path.
794 2 50       5 if($FILESPECLOADED) {
795 2         33 for my $dir (File::Spec->path()) {
796 14         22 my $f = Bio::Root::IO->catfile($dir, $exe);
797 14 50 33     199 return $f if( -f $f && -x $f );
798             }
799             }
800 2         10 return 0;
801             }
802              
803              
804             =head2 tempfile
805              
806             Title : tempfile
807             Usage : my ($handle,$tempfile) = $io->tempfile();
808             Function: Create a temporary filename and a handle opened for reading and
809             writing.
810             Caveats: If you do not have File::Temp on your system you should
811             avoid specifying TEMPLATE and SUFFIX.
812             Args : Named parameters compatible with File::Temp: DIR (defaults to
813             $Bio::Root::IO::TEMPDIR), TEMPLATE, SUFFIX.
814             Returns : A 2-element array, consisting of temporary handle and temporary
815             file name.
816              
817             =cut
818              
819             sub tempfile {
820 40     40 1 1646 my ($self, @args) = @_;
821 40         38 my ($tfh, $file);
822 40         70 my %params = @args;
823              
824             # map between naming with and without dash
825 40         127 for my $key (keys(%params)) {
826 51 50       97 if( $key =~ /^-/ ) {
827 0         0 my $v = $params{$key};
828 0         0 delete $params{$key};
829 0         0 $params{uc(substr($key,1))} = $v;
830             } else {
831             # this is to upper case
832 51         48 my $v = $params{$key};
833 51         50 delete $params{$key};
834 51         96 $params{uc($key)} = $v;
835             }
836             }
837 40 100       91 $params{'DIR'} = $TEMPDIR if(! exists($params{'DIR'}));
838 40 100 66     126 unless (exists $params{'UNLINK'} &&
839             defined $params{'UNLINK'} &&
840             ! $params{'UNLINK'} ) {
841 35         47 $params{'UNLINK'} = 1;
842             } else {
843 5         6 $params{'UNLINK'} = 0;
844             }
845              
846 40 50       58 if($FILETEMPLOADED) {
847 40 100       63 if(exists($params{'TEMPLATE'})) {
848 4         4 my $template = $params{'TEMPLATE'};
849 4         2 delete $params{'TEMPLATE'};
850 4         15 ($tfh, $file) = File::Temp::tempfile($template, %params);
851             } else {
852 36         94 ($tfh, $file) = File::Temp::tempfile(%params);
853             }
854             } else {
855 0         0 my $dir = $params{'DIR'};
856             $file = $self->catfile(
857             $dir,
858             (exists($params{'TEMPLATE'}) ?
859             $params{'TEMPLATE'} :
860 0 0 0     0 sprintf( "%s.%s.%s", $ENV{USER} || 'unknown', $$, $TEMPCOUNTER++))
861             );
862              
863             # sneakiness for getting around long filenames on Win32?
864 0 0       0 if( $HAS_WIN32 ) {
865 0         0 $file = Win32::GetShortPathName($file);
866             }
867              
868             # Try to make sure this will be marked close-on-exec
869             # XXX: Win32 doesn't respect this, nor the proper fcntl,
870             # but may have O_NOINHERIT. This may or may not be in Fcntl.
871 0         0 local $^F = 2;
872             # Store callers umask
873 0         0 my $umask = umask();
874             # Set a known umaskr
875 0         0 umask(066);
876             # Attempt to open the file
877 0 0       0 if ( sysopen($tfh, $file, $OPENFLAGS, 0600) ) {
878             # Reset umask
879 0         0 umask($umask);
880             } else {
881 0         0 $self->throw("Could not write temporary file '$file': $!");
882             }
883             }
884              
885 40 100       9523 if( $params{'UNLINK'} ) {
886 35         34 push @{$self->{'_rootio_tempfiles'}}, $file;
  35         78  
887             }
888              
889 40 100       144 return wantarray ? ($tfh,$file) : $tfh;
890             }
891              
892              
893             =head2 tempdir
894              
895             Title : tempdir
896             Usage : my ($tempdir) = $io->tempdir(CLEANUP=>1);
897             Function: Creates and returns the name of a new temporary directory.
898              
899             Note that you should not use this function for obtaining "the"
900             temp directory. Use $Bio::Root::IO::TEMPDIR for that. Calling this
901             method will in fact create a new directory.
902              
903             Args : args - ( key CLEANUP ) indicates whether or not to cleanup
904             dir on object destruction, other keys as specified by File::Temp
905             Returns : The name of a new temporary directory.
906              
907             =cut
908              
909             sub tempdir {
910 31     31 1 49 my ($self, @args) = @_;
911 31 50 33     265 if ($FILETEMPLOADED && File::Temp->can('tempdir')) {
912 31         97 return File::Temp::tempdir(@args);
913             }
914              
915             # we have to do this ourselves, not good
916             # we are planning to cleanup temp files no matter what
917 0         0 my %params = @args;
918 0         0 print "cleanup is " . $params{CLEANUP} . "\n";
919             $self->{'_cleanuptempdir'} = ( defined $params{CLEANUP} &&
920 0   0     0 $params{CLEANUP} == 1);
921             my $tdir = $self->catfile( $TEMPDIR,
922             sprintf("dir_%s-%s-%s",
923 0   0     0 $ENV{USER} || 'unknown',
924             $$,
925             $TEMPCOUNTER++));
926 0         0 mkdir($tdir, 0755);
927 0         0 push @{$self->{'_rootio_tempdirs'}}, $tdir;
  0         0  
928 0         0 return $tdir;
929             }
930              
931              
932             =head2 catfile
933              
934             Title : catfile
935             Usage : $path = Bio::Root::IO->catfile(@dirs, $filename);
936             Function: Constructs a full pathname in a cross-platform safe way.
937              
938             If File::Spec exists on your system, this routine will merely
939             delegate to it. Otherwise it tries to make a good guess.
940              
941             You should use this method whenever you construct a path name
942             from directory and filename. Otherwise you risk cross-platform
943             compatibility of your code.
944              
945             You can call this method both as a class and an instance method.
946              
947             Args : components of the pathname (directories and filename, NOT an
948             extension)
949             Returns : a string
950              
951             =cut
952              
953             sub catfile {
954 10585     10585 1 17867 my ($self, @args) = @_;
955              
956 10585 50       102456 return File::Spec->catfile(@args) if $FILESPECLOADED;
957             # this is clumsy and not very appealing, but how do we specify the
958             # root directory?
959 0 0       0 if($args[0] eq '/') {
960 0         0 $args[0] = $ROOTDIR;
961             }
962 0         0 return join($PATHSEP, @args);
963             }
964              
965              
966             =head2 rmtree
967              
968             Title : rmtree
969             Usage : Bio::Root::IO->rmtree($dirname );
970             Function: Remove a full directory tree
971              
972             If File::Path exists on your system, this routine will merely
973             delegate to it. Otherwise it runs a local version of that code.
974              
975             You should use this method to remove directories which contain
976             files.
977              
978             You can call this method both as a class and an instance method.
979              
980             Args : roots - rootdir to delete or reference to list of dirs
981              
982             verbose - a boolean value, which if TRUE will cause
983             C to print a message each time it
984             examines a file, giving the name of the file, and
985             indicating whether it's using C or
986             C to remove it, or that it's skipping it.
987             (defaults to FALSE)
988              
989             safe - a boolean value, which if TRUE will cause C
990             to skip any files to which you do not have delete
991             access (if running under VMS) or write access (if
992             running under another OS). This will change in the
993             future when a criterion for 'delete permission'
994             under OSs other than VMS is settled. (defaults to
995             FALSE)
996             Returns : number of files successfully deleted
997              
998             =cut
999              
1000             # taken straight from File::Path VERSION = "1.0403"
1001             sub rmtree {
1002 0     0 1 0 my ($self, $roots, $verbose, $safe) = @_;
1003 0 0       0 if ( $FILEPATHLOADED ) {
1004 0         0 return File::Path::rmtree ($roots, $verbose, $safe);
1005             }
1006              
1007 0   0     0 my $force_writable = ($^O eq 'os2' || $^O eq 'dos' || $^O eq 'MSWin32' ||
1008             $^O eq 'amigaos' || $^O eq 'cygwin');
1009 0         0 my $Is_VMS = $^O eq 'VMS';
1010              
1011 0         0 my @files;
1012 0         0 my $count = 0;
1013 0   0     0 $verbose ||= 0;
1014 0   0     0 $safe ||= 0;
1015 0 0 0     0 if ( defined($roots) && length($roots) ) {
1016 0 0       0 $roots = [$roots] unless ref $roots;
1017             } else {
1018 0         0 $self->warn("No root path(s) specified\n");
1019 0         0 return 0;
1020             }
1021              
1022 0         0 my $root;
1023 0         0 for $root (@{$roots}) {
  0         0  
1024 0         0 $root =~ s#/\z##;
1025 0 0       0 (undef, undef, my $rp) = lstat $root or next;
1026 0         0 $rp &= 07777; # don't forget setuid, setgid, sticky bits
1027 0 0       0 if ( -d _ ) {
1028             # notabene: 0777 is for making readable in the first place,
1029             # it's also intended to change it to writable in case we have
1030             # to recurse in which case we are better than rm -rf for
1031             # subtrees with strange permissions
1032 0 0 0     0 chmod(0777, ($Is_VMS ? VMS::Filespec::fileify($root) : $root))
    0          
1033             or $self->warn("Could not make directory '$root' read+writable: $!")
1034             unless $safe;
1035 0 0       0 if (opendir DIR, $root){
1036 0         0 @files = readdir DIR;
1037 0         0 closedir DIR;
1038             } else {
1039 0         0 $self->warn("Could not read directory '$root': $!");
1040 0         0 @files = ();
1041             }
1042              
1043             # Deleting large numbers of files from VMS Files-11 filesystems
1044             # is faster if done in reverse ASCIIbetical order
1045 0 0       0 @files = reverse @files if $Is_VMS;
1046 0 0       0 ($root = VMS::Filespec::unixify($root)) =~ s#\.dir\z## if $Is_VMS;
1047 0         0 @files = map("$root/$_", grep $_!~/^\.{1,2}\z/s,@files);
1048 0         0 $count += $self->rmtree([@files],$verbose,$safe);
1049 0 0 0     0 if ($safe &&
    0          
1050             ($Is_VMS ? !&VMS::Filespec::candelete($root) : !-w $root)) {
1051 0 0       0 print "skipped '$root'\n" if $verbose;
1052 0         0 next;
1053             }
1054 0 0 0     0 chmod 0777, $root
1055             or $self->warn("Could not make directory '$root' writable: $!")
1056             if $force_writable;
1057 0 0       0 print "rmdir '$root'\n" if $verbose;
1058 0 0       0 if (rmdir $root) {
1059 0         0 ++$count;
1060             }
1061             else {
1062 0         0 $self->warn("Could not remove directory '$root': $!");
1063 0 0       0 chmod($rp, ($Is_VMS ? VMS::Filespec::fileify($root) : $root))
    0          
1064             or $self->warn("and can't restore permissions to "
1065             . sprintf("0%o",$rp) . "\n");
1066             }
1067             }
1068             else {
1069 0 0 0     0 if ( $safe
    0 0        
1070             and ($Is_VMS ? !&VMS::Filespec::candelete($root)
1071             : !(-l $root || -w $root))
1072             ) {
1073 0 0       0 print "skipped '$root'\n" if $verbose;
1074 0         0 next;
1075             }
1076 0 0 0     0 chmod 0666, $root
1077             or $self->warn( "Could not make file '$root' writable: $!")
1078             if $force_writable;
1079 0 0       0 warn "unlink '$root'\n" if $verbose;
1080             # delete all versions under VMS
1081 0         0 for (;;) {
1082 0 0       0 unless (unlink $root) {
1083 0         0 $self->warn("Could not unlink file '$root': $!");
1084 0 0       0 if ($force_writable) {
1085 0 0       0 chmod $rp, $root
1086             or $self->warn("and can't restore permissions to "
1087             . sprintf("0%o",$rp) . "\n");
1088             }
1089 0         0 last;
1090             }
1091 0         0 ++$count;
1092 0 0 0     0 last unless $Is_VMS && lstat $root;
1093             }
1094             }
1095             }
1096              
1097 0         0 return $count;
1098             }
1099              
1100              
1101             =head2 _flush_on_write
1102              
1103             Title : _flush_on_write
1104             Usage : $io->_flush_on_write($newval)
1105             Function: Boolean flag to indicate whether to flush
1106             the filehandle on writing when the end of
1107             a component is finished (Sequences, Alignments, etc)
1108             Args : Optional new value
1109             Returns : Value of _flush_on_write
1110              
1111             =cut
1112              
1113             sub _flush_on_write {
1114 14253     14253   13551 my ($self, $value) = @_;
1115 14253 100       22124 if (defined $value) {
1116 13046         15957 $self->{'_flush_on_write'} = $value;
1117             }
1118 14253         16616 return $self->{'_flush_on_write'};
1119             }
1120              
1121              
1122             =head2 save_tempfiles
1123              
1124             Title : save_tempfiles
1125             Usage : $io->save_tempfiles(1)
1126             Function: Boolean flag to indicate whether to retain tempfiles/tempdir
1127             Args : Value evaluating to TRUE or FALSE
1128             Returns : Boolean value : 1 = save tempfiles/tempdirs, 0 = remove (default)
1129              
1130             =cut
1131              
1132             sub save_tempfiles {
1133 34     34 1 32 my $self = shift;
1134 34 50       60 if (@_) {
1135 0         0 my $value = shift;
1136 0 0       0 $self->{save_tempfiles} = $value ? 1 : 0;
1137             }
1138 34   50     140 return $self->{save_tempfiles} || 0;
1139             }
1140              
1141              
1142             1;