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   1482 use strict;
  276         387  
  276         5918  
4 276     276   807 use Symbol;
  276         415  
  276         12057  
5 276     276   900 use IO::Handle;
  276         380  
  276         8503  
6 276     276   114400 use File::Copy;
  276         452223  
  276         12174  
7 276     276   1168 use Fcntl;
  276         267  
  276         47169  
8 276     276   1179 use base qw(Bio::Root::Root);
  276         332  
  276         118949  
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   437 $TEMPCOUNTER = 0;
75 276         310 $FILESPECLOADED = 0;
76 276         327 $FILETEMPLOADED = 0;
77 276         307 $FILEPATHLOADED = 0;
78 276         267 $VERBOSE = 0;
79              
80             # try to load those modules that may cause trouble on some systems
81 276         300 eval {
82 276         1008 require File::Path;
83 276         392 $FILEPATHLOADED = 1;
84             };
85 276 50       971 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       1343 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       1159 if ($^O =~ /mswin/i) {
    50          
101 0         0 $PATHSEP = "\\";
102             } elsif($^O =~ /macos/i) {
103 0         0 $PATHSEP = ":";
104             } else { # unix
105 276         398 $PATHSEP = "/";
106             }
107 276         335 eval {
108 276         699 require File::Spec;
109 276         306 $FILESPECLOADED = 1;
110 276         22709 $TEMPDIR = File::Spec->tmpdir();
111 276         1748 $ROOTDIR = File::Spec->rootdir();
112 276         1082 require File::Temp; # tempfile creation
113 276         547 $FILETEMPLOADED = 1;
114             };
115 276 50       830 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   1343 no strict 'refs';
  276         314  
  276         22638  
143 0 0       0 $OPENFLAGS |= $bit if eval { $bit = &$func(); 1 };
  0         0  
  0         0  
144             }
145             }
146 276         175620 $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 9234     9234 1 13498 my ($caller, @args) = @_;
162 9234         16825 my $self = $caller->SUPER::new(@args);
163 9234         16756 $self->_initialize_io(@args);
164 9227         13424 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 10912     10912   12296 my($self, @args) = @_;
194              
195 10912         21935 $self->_register_for_cleanup(\&_io_cleanup);
196              
197 10912         33787 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 10912         14643 my $mode;
203              
204 10912 50       15552 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 10912         10159 delete $self->{'_readbuffer'};
228 10912         12967 delete $self->{'_filehandle'};
229 10912 100       16520 $self->noclose( $noclose) if defined $noclose;
230             # determine whether the input is a file(name) or a stream
231 10912 100       14530 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     46 if ($file && ($file ne $input)) {
235 1         4 $self->throw("Input file given twice: '$file' and '$input' disagree");
236             }
237 22         20 $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 10911 100 100     21605 if (defined($file) && defined($fh)) {
250 2         5 $self->throw("Providing both a file and a filehandle for reading - ".
251             "only one please!");
252             }
253              
254 10909 100       15253 if ($string) {
255 47 100 100     163 if (defined($file) || defined($fh)) {
256 3         5 $self->throw("File or filehandle provided with -string, ".
257             "please unset if you are using -string as a file");
258             }
259 44 50   4   519 open $fh, '<', \$string or $self->throw("Could not read string: $!");
  4         16  
  4         4  
  4         25  
260             }
261              
262 10906 100 100     25326 if (defined($file) && ($file ne '')) {
263 1162         3796 $self->file($file);
264 1162         2963 ($mode, $file) = $self->cleanfile;
265 1162   100     4265 $mode ||= '<';
266 1162 100       3077 my $action = ($mode =~ m/>/) ? 'write' : 'read';
267 1162         3633 $fh = Symbol::gensym();
268 1162 100       65714 open $fh, $mode, $file or $self->throw("Could not $action file '$file': $!");
269             }
270              
271 10905 100       16250 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 1895 50 66     16835 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 1895 50       3798 if ($HAS_EOL) {
284 0         0 binmode $fh, ':raw:eol(LF-Native)';
285             }
286 1895         5517 $self->_fh($fh); # if $fh not provided, defaults to STDIN and STDOUT
287             }
288              
289 10905 50       24915 $self->_flush_on_write(defined $flush ? $flush : 1);
290              
291 10905         13660 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 427694     427694   302117 my ($self, $value) = @_;
307 427694 100       534889 if ( defined $value) {
308 1927         2916 $self->{'_filehandle'} = $value;
309             }
310 427694         678349 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 12 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     39 if ( $arg{-force} || not exists $self->{'_mode'} ) {
352             # Determine stream mode
353 8         8 my $mode;
354 8         11 my $fh = $self->_fh;
355 8 50       9 if (defined $fh) {
356             # use fcntl if not Windows-based
357 8 50       17 if ($^O !~ /MSWin32/) {
358 8         19 my $m = fcntl($fh, F_GETFL, 0);
359 8 50       24 $mode = exists $modes{$m & 3} ? $modes{$m & 3} : '?';
360             } else {
361             # Determine read/write status of filehandle
362 276     276   1296 no warnings 'io';
  276         318  
  276         625687  
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         8 $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 1640 my ($self, $value) = @_;
398 1168 100       3157 if ( defined $value) {
399 1162         2010 $self->{'_file'} = $value;
400             }
401 1168         1435 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 1292 my ($self) = @_;
418 1168         7494 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 66 my ($self) = @_;
435 12         47 my $format = (split '::', ref($self))[-1];
436 12         51 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 44653 my ($self, $variant) = @_;
457 70151 100       71802 if (defined $variant) {
458 70         100 $variant = lc $variant;
459 70         156 my $var_name = '%'.ref($self).'::variant';
460 70         3236 my %ok_variants = eval $var_name; # e.g. %Bio::Assembly::IO::ace::variant
461 70 50       266 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       184 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         199 $self->{variant} = $variant;
470             }
471 70151         116091 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 27599     27599   19320 my $self = shift;
487 27599   50     26887 my $fh = $self->_fh() || \*STDOUT;
488 27599         45752 my $ret = print $fh @_;
489 27599         41377 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   3 my ($self, $string, $line_num) = @_;
506             # Line number check
507 2 50       5 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         5 $self->close;
522 2         2 my $temp_file;
523 2         1 my $number = 0;
524 2         58 while (-e "$file.$number.temp") {
525 0         0 $number++;
526             }
527 2         5 $temp_file = "$file.$number.temp";
528 2         7 copy($file, $temp_file);
529 2 50       377 open my $fh1, '<', $temp_file or $self->throw("Could not read temporary file '$temp_file': $!");
530 2 50       65 open my $fh2, '>', $file or $self->throw("Could not write file '$file': $!");
531 2         18 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         5 print $fh2 $line;
537             }
538             }
539 2         9 CORE::close $fh1;
540 2         17 CORE::close $fh2;
541 2 50       80 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         5 $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         11 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   360859 my ($self, %param) = @_;
591 384199 100       395571 my $fh = $self->_fh or return;
592 384187         250966 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       224670 if( @{$self->{'_readbuffer'} || [] } ) {
  384187 100       898423  
597 1600         1258 $line = shift @{$self->{'_readbuffer'}};
  1600         2484  
598             } else {
599 382587         535054 $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     1608336 if( !$HAS_EOL && !$param{-raw} && (defined $line) ) {
      100        
606             # don't strip line endings if -raw or $HAS_EOL is specified
607 383582         356755 $line =~ s/\015\012/\012/g; # Change all CR/LF pairs to LF
608 383582 50       548696 $line =~ tr/\015/\n/ unless $ONMAC; # Change all single CRs to NEWLINE
609             }
610 384187         951611 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   1800 my ($self, $value) = @_;
644 1622 100       2601 return unless $value;
645 1620         1326 unshift @{$self->{'_readbuffer'}}, $value;
  1620         3282  
646 1620         2180 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 11253     11253 1 10974 my ($self) = @_;
663              
664             # do not close if we explicitly asked not to
665 11253 100       16351 return if $self->noclose;
666              
667 11203 100       19456 if( defined( my $fh = $self->{'_filehandle'} )) {
668 1676         3546 $self->flush;
669 1676 50 66     11816 return if ref $fh eq 'GLOB' && (
      66        
670             \*STDOUT == $fh || \*STDERR == $fh || \*STDIN == $fh
671             );
672              
673             # don't close IO::Strings
674 1675 100 66     43824 CORE::close $fh unless ref $fh && $fh->isa('IO::String');
675             }
676 11202         12738 $self->{'_filehandle'} = undef;
677 11202         9882 delete $self->{'_readbuffer'};
678 11202         18147 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 2351     2351 1 2769 my ($self) = shift;
694              
695 2351 50       4530 if( !defined $self->{'_filehandle'} ) {
696 0         0 $self->throw("Flush failed: no filehandle was active");
697             }
698              
699 2351 100       7735 if( ref($self->{'_filehandle'}) =~ /GLOB/ ) {
700 1244         4057 my $oldh = select($self->{'_filehandle'});
701 1244         8134 $| = 1;
702 1244         3234 select($oldh);
703             } else {
704 1107         2415 $self->{'_filehandle'}->flush();
705             }
706 2351         3424 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 11287     11287 1 9391 my $self = shift;
724 11287 100       18417 return $self->{'_noclose'} = shift if @_;
725 11253         20019 return $self->{'_noclose'};
726             }
727              
728              
729             =head2 _io_cleanup
730              
731             =cut
732              
733             sub _io_cleanup {
734 9540     9540   8860 my ($self) = @_;
735 9540         15229 $self->close();
736 9540         16449 my $v = $self->verbose;
737              
738             # we are planning to cleanup temp files no matter what
739 9540 50 66     19309 if ( exists($self->{'_rootio_tempfiles'})
      66        
740             and ref($self->{'_rootio_tempfiles'}) =~ /array/i
741             and not $self->save_tempfiles
742             ) {
743 34 50       56 if( $v > 0 ) {
744             warn( "going to remove files ",
745 0         0 join(",", @{$self->{'_rootio_tempfiles'}}),
  0         0  
746             "\n");
747             }
748 34         24 unlink (@{$self->{'_rootio_tempfiles'}} );
  34         711  
749             }
750             # cleanup if we are not using File::Temp
751 9540 0 33     46721 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 5 my ($self, $exe) = @_;
784 3 50       7 $self->throw("Must pass a defined value to exists_exe") unless defined $exe;
785 3 50 33     8 $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     36 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         28 for my $dir (File::Spec->path()) {
796 14         21 my $f = Bio::Root::IO->catfile($dir, $exe);
797 14 50 33     182 return $f if( -f $f && -x $f );
798             }
799             }
800 2         8 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 1207 my ($self, @args) = @_;
821 40         38 my ($tfh, $file);
822 40         74 my %params = @args;
823              
824             # map between naming with and without dash
825 40         130 for my $key (keys(%params)) {
826 51 50       88 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         95 my $v = $params{$key};
833 51         52 delete $params{$key};
834 51         101 $params{uc($key)} = $v;
835             }
836             }
837 40 100       88 $params{'DIR'} = $TEMPDIR if(! exists($params{'DIR'}));
838 40 100 66     134 unless (exists $params{'UNLINK'} &&
839             defined $params{'UNLINK'} &&
840             ! $params{'UNLINK'} ) {
841 35         46 $params{'UNLINK'} = 1;
842             } else {
843 5         7 $params{'UNLINK'} = 0;
844             }
845              
846 40 50       57 if($FILETEMPLOADED) {
847 40 100       57 if(exists($params{'TEMPLATE'})) {
848 4         4 my $template = $params{'TEMPLATE'};
849 4         5 delete $params{'TEMPLATE'};
850 4         10 ($tfh, $file) = File::Temp::tempfile($template, %params);
851             } else {
852 36         102 ($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       9626 if( $params{'UNLINK'} ) {
886 35         34 push @{$self->{'_rootio_tempfiles'}}, $file;
  35         79  
887             }
888              
889 40 100       178 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 46 my ($self, @args) = @_;
911 31 50 33     276 if ($FILETEMPLOADED && File::Temp->can('tempdir')) {
912 31         82 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 8980     8980 1 15264 my ($self, @args) = @_;
955              
956 8980 50       81287 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 11578     11578   10496 my ($self, $value) = @_;
1115 11578 100       17120 if (defined $value) {
1116 10906         12389 $self->{'_flush_on_write'} = $value;
1117             }
1118 11578         12116 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       58 if (@_) {
1135 0         0 my $value = shift;
1136 0 0       0 $self->{save_tempfiles} = $value ? 1 : 0;
1137             }
1138 34   50     146 return $self->{save_tempfiles} || 0;
1139             }
1140              
1141              
1142             1;