o
    Rŀg?0                     @   s   d Z ddlmZ ddlmZ ddlmZ ddlmZ ddlm	Z	 ddlm
Z
 G dd	 d	e
ZG d
d deZedkrEddlmZ e  dS dS )zBio.Align support module (not for general use).

Unless you are writing a new parser or writer for Bio.Align, you should not
use this module.  It provides base classes to try and simplify things.
    )ABC)abstractmethod)Optional)StreamModeError)
Alignments)AlignmentsAbstractBaseClassc                   @   sr   e Zd ZU dZdZdZee ed< dd Z	dd Z
d	d
 Zdd Zdd Zdd Zdd Zedd Zdd ZdS )AlignmentIteratoral  Base class for building Alignment iterators.

    You should write a parse method that returns an Alignment generator.  You
    may wish to redefine the __init__ method as well.

    Subclasses may define the following class attributes:
    - mode   - 't' or 'b' for text or binary files, respectively
    - fmt    - a human-readable name for the file format.
    tNfmtc                 C   s   || _ zt|d| j | _W nB tyP   | jdkr+|ddkr*t| j ddn | jdkrA|ddkr@t| j d	dn
td
| j dd|| _Y nw d| _	| 
| j dS )aO  Create an AlignmentIterator object.

        Arguments:
        - source - input file stream, or path to input file

        This method MAY be overridden by any subclass.

        Note when subclassing:
        - there should be a single non-optional argument, the source.
        - you can add additional optional arguments.
        rr	   r    z# files must be opened in text mode.Nb    z% files must be opened in binary mode.zUnknown mode '')sourceopenmode_stream	TypeErrorreadr   r
   
ValueError_index_read_header)selfr    r   H/var/www/html/myenv/lib/python3.10/site-packages/Bio/Align/interfaces.py__init__&   s2   




zAlignmentIterator.__init__c                 C   sP   z| j }W n
 ty   tdw | |}|du r| j| _t|  jd7  _|S )zReturn the next alignment.N   )r   AttributeErrorStopIteration_read_next_alignmentr   _len)r   stream	alignmentr   r   r   __next__F   s   

zAlignmentIterator.__next__c                 C   sp   z| j }W |S  ty7   | j}|   d}| D ]}|d7 }q|   | j|k r1t|  | j|k s(|| _ Y |S w )a@  Return the number of alignments.

        The number of alignments is cached. If not yet calculated, the iterator
        is rewound to the beginning, and the number of alignments is calculated
        by iterating over the alignments. The iterator is then returned to its
        original position in the file.
        r   r   )r!   r   r   rewindnext)r   lengthindexr#   r   r   r   __len__S   s    


zAlignmentIterator.__len__c                 C   s   | S Nr   r   r   r   r   	__enter__i   s   zAlignmentIterator.__enter__c                 C   s:   z| j }W n
 ty   Y d S w || jur|  | ` d S r*   )r   r   r   close)r   exc_type	exc_valueexc_tracebackr"   r   r   r   __exit__l   s   

zAlignmentIterator.__exit__c                 C   s   |t dddkrtdt| j}| j}t }| j}|d ||| |   |	|  | j| _
|   | j|k rCt|  | j|k s:|S )a  Return the alignments as an Alignments object (which inherits from list).

        Only an index of the form [:] (i.e., a full slice) is supported.
        The file stream is returned to its zero position, and the file header
        is read and stored in an Alignments object. Next, we iterate over the
        alignments and store them in the Alignments object.  The iterator
        is then returned to its original position in the file, and the
        Alignments object is returned. The Alignments object contains the exact
        same information as the Alignment iterator self, but stores the
        alignments in a list instead of as an iterator, allowing indexing.

        Typical usage is

        >>> from Bio import Align
        >>> alignments = Align.parse("Blat/dna_rna.psl", "psl")
        >>> alignments.metadata
        {'psLayout version': '3'}

        As `alignments` is an iterator and not a list, we cannot retrieve an
        alignment by its index:

        >>> alignment = alignments[2]  # doctest:+ELLIPSIS
        Traceback (most recent call last):
          ...
        KeyError: 'only [:] (a full slice) can be used as the index'

        So we use the iterator to create a list-like Alignments object:

        >>> alignments = alignments[:]

        While `alignments` is a list-like object, it has the same `metadata`
        attribute representing the information stored in the file header:

        >>> alignments.metadata
        {'psLayout version': '3'}

        Now we can index individual alignments:

        >>> len(alignments)
        4
        >>> alignment = alignments[2]
        >>> alignment.target.id, alignment.query.id
        ('chr3', 'NR_111921.1')

        Nz0only [:] (a full slice) can be used as the indexr   )sliceKeyErrortyper   r   r   r   seekr%   extendr!   r&   )r   r(   read_header
alignmentsr"   r   r   r   __getitem__u   s    .





zAlignmentIterator.__getitem__c                 C      dS )z.Read the file header and store it in metadata.Nr   r   r"   r   r   r   r         zAlignmentIterator._read_headerc                 C   r:   )z2Read one Alignment from the stream, and return it.Nr   r;   r   r   r   r       s    z&AlignmentIterator._read_next_alignmentc                 C   s"   | j d | | j  d| _d S )Nr   )r   r5   r   r   r+   r   r   r   r%      s   
zAlignmentIterator.rewind)__name__
__module____qualname____doc__r   r
   r   str__annotations__r   r$   r)   r,   r1   r9   r   r   r    r%   r   r   r   r   r      s   
 
 	B
r   c                   @   sj   e Zd ZU dZdZdZee ed< dd Z	dd Z
d	d
 Zdd Zdd Zdd ZeZdd Zdd ZdS )AlignmentWritera  Base class for alignment writers. This class should be subclassed.

    It is intended for alignment file formats with an (optional)
    header, one or more alignments, and an (optional) footer.

    The user may call the write_file() method to write a complete
    file containing the alignments.

    Alternatively, users may call the write_header(), followed
    by multiple calls to format_alignment() and/or write_alignments(),
    followed finally by write_footer().

    Subclasses may define the following class attributes:
    - mode   - 'w' or 'wb' for text or binary files, respectively
    - fmt    - a human-readable name for the file format.
    wNr
   c                 C   s   |durb| j dkr.z|d W n ty   tdd ty*   t|| j }Y n5w |}n1| j dkrXz|d W n tyF   tdd tyT   t|| j }Y nw |}ntd| j  || _|| _dS )	aG  Create the writer object.

        Arguments:
        - target - output file stream, or path to output file

        This method MAY be overridden by any subclass.

        Note when subclassing:
        - there should be a single non-optional argument, the target.
        - you can add additional optional arguments.
        NrD   r   z!File must be opened in text mode.wbr   z#File must be opened in binary mode.zUnknown mode '%s')	r   writer   r   r   r   RuntimeErrorr   _target)r   targetr"   r   r   r   r      s4   



zAlignmentWriter.__init__c                 C   r:   )z)Write the file header to the output file.Nr   )r   r"   r8   r   r   r   write_header  r<   zAlignmentWriter.write_headerc                 C   r:   )z)Write the file footer to the output file.Nr   r;   r   r   r   write_footer  r<   zAlignmentWriter.write_footerc                 C   s   t d)zXFormat a single alignment as a string.

        alignment - an Alignment object
        z!This method should be implemented)NotImplementedError)r   r#   r   r   r   format_alignment  s   z AlignmentWriter.format_alignmentc                 C   sH   d}|D ]}|dkrt d| j d| |}|| |d7 }q|S )zWrite a single alignment to the output file, and return 1.

        alignments - A list or iterator returning Alignment objects
        stream     - Output file stream.
        r   r   zAlignment files in the z, format can contain a single alignment only.)r   r
   rM   rF   r   r"   r8   countr#   liner   r   r   write_single_alignment   s   


z&AlignmentWriter.write_single_alignmentc                 C   s.   d}|D ]}|  |}|| |d7 }q|S )zWrite alignments to the output file, and return the number of alignments.

        alignments - A list or iterator returning Alignment objects
        stream     - Output file stream.
        r   r   )rM   rF   rN   r   r   r   write_multiple_alignments1  s   


z)AlignmentWriter.write_multiple_alignmentsc                 C   s&   |  || | ||}| | |S )zWrite the alignments to the file strenm, and return the number of alignments.

        alignments - A list or iterator returning Alignment objects
        stream     - Output file stream.
        )rJ   write_alignmentsrK   )r   r"   r8   rO   r   r   r   
write_file@  s   
zAlignmentWriter.write_filec                 C   sB   | j }z| ||}W || jur|  |S || jur |  w w )zWrite a file with the alignments, and return the number of alignments.

        alignments - A list or iterator returning Alignment objects
        )r   rT   rH   r-   )r   r8   r"   rO   r   r   r   rF   K  s   


zAlignmentWriter.write)r=   r>   r?   r@   r   r
   r   rA   rB   r   rJ   rK   rM   rQ   rR   rS   rT   rF   r   r   r   r   rC      s   
 ,
rC   __main__)run_doctestN)r@   abcr   r   typingr   Bior   	Bio.Alignr   r   r   rC   r=   
Bio._utilsrV   r   r   r   r   <module>   s    . 
