MSG = 'A python package to run this executable is required,'
BIO = 'biopython'
BIO_BGZF = 'biopython with Bgzf support'
    NCBIXML = create_fake_class(MSG + BIO)
    NCBIWWW = create_fake_class(MSG + BIO)
def create_fake_class(msg):
        def __init__(self, *args, **kwargs):
def create_fake_funct(msg):
    def FakeRequiredfunct(*args, **kwargs):
    class FakePythonRequiredClass(object): class MalformedFile(Exception):
    'The input file is malformed'
    pass def error_quality_disagree(error_msg):
    'It checks if a Biopython ValueError is due to a malformed quality file'
    msg = 'Sequence length and number of quality scores disagree'
    msg2 = 'Lengths of sequence and quality values differs'
    if msg in str(error_msg) or msg2 in str(error_msg):
        return True
    else:
        return False class UnknownFormatError(Exception):
    'Raised when the format of a sequence file cannot be guessed'
    pass class IncompatibleFormatError(Exception):
    'Asked output format is incompatible with input file formats'
    pass class FileIsEmptyError(Exception):
    pass class IsSingleLineFastqError(Exception):
    'File format is single line'
    pass def group_in_packets(iterable, packet_size):
    'ABCDE -> (A, B), (C, D), (E,)'
    iterable = iter(iterable)
    while True:
        chunk = tuple(islice(iterable, packet_size))
        if not chunk:
            break
        yield chunk def group_in_packets_fill_last(iterable, packet_size, fillvalue=None):
    'ABCDE -> (A, B), (C, D), (E, None)'
    # It is faster than group_in_packets
    iterables = [iter(iterable)] * packet_size
    kwargs = {'fillvalue': fillvalue}
    return izip_longest(*iterables, **kwargs) def rel_symlink(path1, path2):
    'It makes the relative to path1 from within dirname(path2)'
    # The working directory can not be used because it is not thread safe
    # working directory is a global environment variable shared by all threads
    path1 = os.path.abspath(path1)
    path2 = os.path.abspath(path2)
    rel_path1 = _rel_path(path1, path2)

    fname2 = os.path.split(path2)[-1]

    temp_dir = tempfile.mkdtemp()
    try:
        temp_link_path = os.path.join(temp_dir, fname2)

        os.symlink(rel_path1, temp_link_path)
        shutil.move(temp_link_path, path2)
    finally:
        os.rmdir(temp_dir) def flush_fhand(fhand):
    try:
        fhand.flush()
    except IOError, error:
        # The pipe could be already closed
        if 'Broken pipe' not in str(error):
            raise FILETYPE = 'file'
STRINGIOTYPE = 'stringio'
OTHERTYPE = 'othertype'
FILEFORMAT_INVENTORY = {}
def _get_some_qual_and_lengths(fhand, force_file_as_non_seek):
def _guess_fastq_version(fhand, force_file_as_non_seek):
def _get_instance_type(fhand):
def _get_fhand_id(fhand):
def get_format(fhand):
def set_format(fhand, file_format):
def _guess_format(fhand, force_file_as_non_seek): GUESS_FORMAT = 'guess' SEQS_PASSED = 'seqs_passed' SEQS_FILTERED_OUT = 'seqs_filtered_out' SEQITEM = 'seqitem' SEQRECORD = 'seqrecord' ORPHAN_SEQS = 'orphan_seqs' SANGER_FASTQ_FORMATS = ('fastq-sanger', 'fastq') ILLUMINA_FASTQ_FORMATS = ('fastq-illumina',) def get_setting(key):
    'It returns the value for one setting'
    return _settings[key] class SeqItem(_SeqItem):
    def __new__(cls, name, lines, annotations=None):
        # This subclass is required to have a default value in a namedtuple
        if annotations is None:
            annotations = {}
        # add default values
        return super(SeqItem, cls).__new__(cls, name, lines, annotations) def get_str_seq(seq):
    seq_class = seq.kind
    if seq_class == SEQITEM:
        seq = seq.object.lines[1].strip()
    elif seq_class == SEQRECORD:
        seq = str(seq.object.seq)
    return seq.strip() def assing_kind_to_seqs(kind, seqs, file_format):
    'It puts each seq into a NamedTuple named Seq'
    return (SeqWrapper(kind, seq, file_format) for seq in seqs)
from itertools import chain, tee, ifilter
from shutil import copyfileobj
from tempfile import NamedTemporaryFile
from crumbs.utils.optional_modules import (FastaIterator, QualPhredIterator,
                                           PairedFastaQualIterator,
                                           FastqPhredIterator, write_seqrecs,
                                           FastqSolexaIterator,
                                           FastqIlluminaIterator,
                                           parse_into_seqrecs)
from crumbs.seq.utils.data import (ambiguous_rna_letters,
                                   ambiguous_dna_letters,
                                   extended_protein_letters)
from crumbs.exceptions import (MalformedFile, error_quality_disagree,
                               UnknownFormatError, IncompatibleFormatError,
                               FileIsEmptyError, IsSingleLineFastqError)
from crumbs.iterutils import group_in_packets, group_in_packets_fill_last
from crumbs.utils.file_utils import rel_symlink, flush_fhand
from crumbs.seq.utils.file_formats import get_format, peek_chunk_from_file
from crumbs.utils.tags import (GUESS_FORMAT, SEQS_PASSED, SEQS_FILTERED_OUT,
                               SEQITEM, SEQRECORD, ORPHAN_SEQS,
                               SANGER_FASTQ_FORMATS, ILLUMINA_FASTQ_FORMATS)
from crumbs.settings import get_setting
from crumbs.seq.seq import SeqItem, get_str_seq, assing_kind_to_seqs
import cStringIO
    for seq in read_seqs([fhand_]):
        for letter in get_str_seq(seq):
            total_letters += 1
            if letter in ('gcatnuGCATNU'):
                nucleotides += 1
            if letter in only_prot:
                return 'prot'
    nucl_freq = nucleotides / total_letters
    if nucl_freq > 0.8:
        return 'nucl'

    raise RuntimeError('unable to guess the seq type')


def _get_name_from_lines(lines):
    'It returns the name and the chunk from a list of names'
    name = lines[0].partition(' ')[0][1:].strip()
    return name


def _get_name_from_chunk_fastq(lines):
    'It returns the name and the chunk from a list of names'
    if len(lines) != 4:
        raise RuntimeError('Malformed fastq')
    if not lines[0].startswith('@'):
        raise RuntimeError('Not a valid fastq file: not start with @')
    if not lines[1].startswith('+'):
        raise RuntimeError('Too complex fastq for this function')
    if len(lines[1]) != len(lines[3]):
        raise RuntimeError('Qual has different length than seq')
    name = lines[0].split()[0][1:]
    return name


def _line_is_not_empty(line):
    return False if line in ['\n', '\r\n'] else True


def _itemize_fastq_singleline(fhand):
    'It returns the fhand divided in chunks, one per seq'
    # group_in_packets_fill_last is faster than group_in_packets
    blobs = group_in_packets_fill_last(ifilter(_line_is_not_empty, fhand), 4)
    return (SeqItem(_get_name_from_lines(lines), lines) for lines in blobs)


def _itemize_fastx(fhand):
    try:
        for read in _itemize_fastx_multiline(fhand):
            yield read
    except IsSingleLineFastqError:
        for read in _itemize_fastq_singleline(fhand):
            yield read


# adapted from https://github.com/lh3/readfq
def _itemize_fastx_multiline(fhand):  # this is a generator function
    last_line = None  # this is a buffer keeping the last unprocessed line
    is_empty = True
    n_single_line_seqs = 0
    n_seqs_read = 0
    while True:  # mimic closure; is it a bad idea?
        if not last_line:  # the first record or a record following a fastq
            for line in fhand:  # search for the start of the next record
                if line[0] in '@>':  # fasta/q header line
                    last_line = line  # save this line
                    break
        if not last_line:
            break
        title = last_line
        seq_lines = []
        last_line = None
        name = title[1:-1].partition(" ")[0]
        for line in fhand:  # read the sequence
            if line[0] in '@+>':
                last_line = line
                break
            seq_lines.append(line.rstrip())
        if not last_line or last_line[0] != '+':  # this is a fasta record
            yield SeqItem(name, [title, ''.join(seq_lines) + '\n'])
            n_seqs_read += 1
            is_empty = False
            if not last_line:
                break
        else:  # this is a fastq record
            seq = ''.join(seq_lines)
            length = 0
            qual_lines = []
            len_seq = len(seq)
            for line in fhand:  # read the quality
                qual_lines.append(line.rstrip())
                length += len(line) - 1
                if length >= len_seq:  # have read enough quality
                    if length != len_seq:
                        msg = 'Malformed fastq file: seq and quality lines'
                        msg += 'have different lengths'
                        raise MalformedFile(msg)
                    last_line = None
                    is_empty = False
                    yield SeqItem(name, [title, seq + '\n', '+\n',
                                ''.join(qual_lines) + '\n'])
                    n_seqs_read += 1
                    if len(qual_lines) == 1:
                        n_single_line_seqs += 1
                        if n_seqs_read == 1000:
                            if n_single_line_seqs == n_seqs_read:
                                raise IsSingleLineFastqError()
                    break
            if last_line:  # reach EOF before reading enough quality
                msg = 'Malformed fastq file: quality line missing'
                raise MalformedFile(msg)
    if is_empty:
        raise FileIsEmptyError('File is empty')


def _read_seqitems(fhands):
    'it returns an iterator of seq items (tuples of name and chunk)'
    seq_iters = []
    for fhand in fhands:
        file_format = get_format(fhand)
        seq_iter = _itemize_fastx(fhand)

        seq_iter = assing_kind_to_seqs(SEQITEM, seq_iter, file_format)