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
            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)
        seq_iters.append(seq_iter)
    return chain.from_iterable(seq_iters)


def _write_seqitems(items, fhand, file_format):
    'It writes one seq item (tuple of name and string)'
    for seq in items:
        seqitems_fmt = seq.file_format
        if file_format and 'fastq' in seqitems_fmt and 'fasta' in file_format:
            seq_lines = seq.object.lines
            try:
                fhand.write('>' + seq_lines[0][1:] + seq_lines[1])
            except IOError, error:
                # The pipe could be already closed
                if not 'Broken pipe' in str(error):
                    raise
        elif file_format and seqitems_fmt != file_format:
            msg = 'Input and output file formats do not match, you should not '
            msg += 'use SeqItems: ' + str(seq.file_format) + ' '
            msg += str(file_format)
            raise RuntimeError(msg)
        else:
            try:
                fhand.write(''.join(seq.object.lines))
            except IOError, error:
                # The pipe could be already closed
                if not 'Broken pipe' in str(error):
                    raise


def write_seqs(seqs, fhand=None, file_format=None):
    'It writes the given sequences'
    if fhand is None:
        fhand = NamedTemporaryFile(suffix='.' + file_format.replace('-', '_'))

    seqs, seqs2 = tee(seqs)
    try:
        seq = seqs2.next()
    except StopIteration:
        # No sequences to write, so we're done
        return fhand
    del seqs2
    seq_class = seq.kind
    if seq_class == SEQITEM:
        _write_seqitems(seqs, fhand, file_format)
    elif seq_class == SEQRECORD:
        seqs = (seq.object for seq in seqs)
        _write_seqrecords(seqs, fhand, file_format)
    else:
        raise ValueError('Unknown class for seq: ' + seq_class)
    return fhand


def read_seqs(fhands, out_format=None, prefered_seq_classes=None):
    'It returns a stream of seqs in different codings: seqrecords, seqitems...'

    if not prefered_seq_classes:
        prefered_seq_classes = [SEQITEM, SEQRECORD]
    try:
        in_format = get_format(fhands[0])
    except FileIsEmptyError:
        return []
    # seqitems is incompatible with different input and output formats
    # or when in_format != a fasta or fastq
    if ((out_format not in (None, GUESS_FORMAT) and in_format != out_format
         and SEQITEM in prefered_seq_classes) or
        (in_format not in ('fasta',) + SANGER_FASTQ_FORMATS +
         ILLUMINA_FASTQ_FORMATS)):
        prefered_seq_classes.pop(prefered_seq_classes.index(SEQITEM))

    if not prefered_seq_classes:
        msg = 'No valid seq class left or prefered'
        raise ValueError(msg)

    for seq_class in prefered_seq_classes:
        if seq_class == SEQITEM:
            try:
                return _read_seqitems(fhands)
            except NotImplementedError:
                continue
        elif seq_class == SEQRECORD:
            try:
                seqs = _read_seqrecords(fhands)

                return assing_kind_to_seqs(SEQRECORD, seqs, None)