#!/usr/bin/python
#
# Copyright (c) 2012 Mikkel Schubert <MSchubert@snm.ku.dk>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
# copies of the Software, and to permit persons to whom the Software is 
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
# SOFTWARE.
#
"""
An alternative to 'samtools view -Sb -', needed because samtools does not
properly handle SAM-files with no records. For example, the following
command will not work:
$ samtools view -H INPUT | samtools view -Sb -
"""

import os
import sys
import optparse
import subprocess

import pypeline.ui
import pypeline.atomiccmd

from pypeline.common.utilities import safe_coerce_to_tuple


def select_cat(filename):
    with open(filename) as source:
        header = source.read(2)
        if header == "\x1f\x8b":
            return "zcat"
        elif header == "BZ":
            return "bzcat"

        return "cat"




def call(input_files, output_file):
    executable = select_cat(input_files[0])
    command = [executable] + input_files
     
    with open(output_file, "w") as output:
        proc = subprocess.Popen(command, 
                                stdout    = output, 
                                close_fds = True)
        return proc.wait()


def main(argv):
    parser = optparse.OptionParser()
    parser.add_option("--output")

    config, args = parser.parse_args(argv)
    if not args:
        pypeline.ui.print_err("%s takes at least one input file" % sys.argv[0])
        sys.exit(1)
    elif not config.output:
        pypeline.ui.print_err("%s required that --output is set" % sys.argv[0])
        sys.exit(1)
                               
    return call(input_files   = args,
                output_file   = config.output)


def build_atomiccmd(cls, input_files, output_file):
    filename = os.path.realpath(__file__)
    if filename.endswith(".pyc"):
        filename = filename[:-1]
         
    command  = [filename, "--output", "%(TEMP_OUT_FILE)s"]
    files = {"TEMP_OUT_FILE" : output_file}
    for (counter, filename) in enumerate(safe_coerce_to_tuple(input_files), start = 1):
        files["IN_FILE_%02i" % counter] = filename
        command.append("%%(IN_FILE_%02i)s" % counter)
          
    return cls(command, **files)
     

if __name__ == '__main__':
    sys.exit(main(sys.argv[1:]))

@@ -1875,16 +1875,112 @@
 ut_files
+%0A%0A    if not output_file:%0A        return subprocess.Popen(command, close_fds = True).wait()%0A    
 %0A     %0A 
@@ -2447,136 +2447,8 @@
 (1)%0A
-    elif not config.output:%0A        pypeline.ui.print_err(%22%25s required that --output is set%22 %25 sys.argv%5B0%5D)%0A        sys.exit(1)%0A
     
@@ -2745,17 +2745,16 @@
 command 
- 
 = %5Bfilen
@@ -2760,43 +2760,111 @@
 name
-, %22--output%22, %22%25(TEMP_OUT_FILE)s%22%5D%0A
+%5D%0A    files = %7B%7D%0A%0A    if output_file == cls.PIPE:%0A        files%5B%22OUT_STDOUT%22%5D = cls.PIPE%0A    else:%0A    
     
@@ -2868,20 +2868,17 @@
    files
- = %7B
+%5B
 %22TEMP_OU
@@ -2888,10 +2888,11 @@
 ILE%22
- :
+%5D =
  out
@@ -2899,17 +2899,75 @@
 put_file
-%7D
+%0A        command.extend((%22--output%22, %22%25(TEMP_OUT_FILE)s%22))%0A
 %0A    for

Allow unicat to stdout.