o
    Rŀg0                     @   s   d Z ddl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 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ddddZdddZdd Zdd Zdd Zdd Zdd Zd d! ZG d"d# d#eZG d$d% d%eZdS )&zBio.SeqIO support for the "xdna" file format.

The Xdna binary format is generated by Christian Marck's DNA Strider program
and also used by Serial Cloner.
    N)match)pack)unpack)BiopythonWarning)Seq)ExactPosition)
SeqFeature)SimpleLocation)	SeqRecord   )SequenceIterator)SequenceWriterDNARNAprotein)r   r            linearcircular)r   r   c                 C   s&   |  |}t||k rtd| |S )z9Read the specified number of bytes from the given handle.z Cannot read %d bytes from handle)readlen
ValueError)handlelengthdata r   D/var/www/html/myenv/lib/python3.10/site-packages/Bio/SeqIO/XdnaIO.py_read'   s   
r   c                 C   s2   t dt| dd }t d| t| |d dS )zRead a Pascal string.

    A Pascal string comprises a single byte giving the length of the string
    followed by as many bytes.
    >Br   r   z%dsASCII)r   r   decode)r   r   r   r   r   _read_pstring/   s   r"   c                 C   s   t t| S )N)intr"   )r   r   r   r   _read_pstring_as_integer9   s   r$   c                 C   s*   t | }|dkrt| t|}||fS dS )a  Read an overhang specification.

    An overhang is represented in a XDNA file as:
      - a Pascal string containing the text representation of the overhang
        length, which also indicates the nature of the overhang:
        - a length of zero means no overhang,
        - a negative length means a 3' overhang,
        - a positive length means a 5' overhang;
      - the actual overhang sequence.

    Examples:
      - 0x01 0x30: no overhang ("0", as a P-string)
      - 0x01 0x32 0x41 0x41: 5' AA overhang (P-string "2", then "AA")
      - 0x02 0x2D 0x31 0x43: 3' C overhang (P-string "-1", then "C")

    Returns a tuple (length, sequence).

    r   )NN)r$   r   abs)r   r   overhangr   r   r   _read_overhang=   s
   r'   c                 C   sV   dd |  dD D ]}td|}|r| \}}|g||< q
d|vr(|g|d< q
dS )zParse the description field of a Xdna feature.

    The 'description' field of a feature sometimes contains several
    GenBank-like qualifiers, separated by carriage returns (CR, 0x0D).
    c                 S   s   g | ]
}t |d kr|qS )r   )r   ).0xr   r   r   
<listcomp>_   s    z._parse_feature_description.<locals>.<listcomp>z^([^=]+)="([^"]+)"?$"noteN)splitr   groups)desc
qualifierslinemqualvaluer   r   r   _parse_feature_descriptionX   s   

r6   c                 C   s   t | }t | }t | pd}t| }t| }tdt| d\}}}	|r&d}
nd}
||}}t |  t|d ||
d}i }|rC|g|d< t|| t|||d}|j| d	S )
zRead a single sequence feature.misc_featurez>BBxBr   r   )strandlabel)typer1   N)	r"   r$   r   r   r	   r6   r   featuresappend)r   recordnamer0   r;   startendforwarddisplayarrowr9   locationr1   featurer   r   r   _read_featurek   s$   


rG   c                       0   e Zd ZdZ fddZdd Zdd Z  ZS )XdnaIteratorzParser for Xdna files.c                    s   t  j|ddd dS )a   Parse a Xdna file and return a SeqRecord object.

        Argument source is a file-like object in binary mode or a path to a file.

        Note that this is an "iterator" in name only since an Xdna file always
        contain a single sequence.

        bXdna)modefmtNsuper__init__)selfsource	__class__r   r   rP      s   	zXdnaIterator.__init__c                 C   s:   | d}|stdt|dk rtd| ||}|S )z9Start parsing the file, and return a SeqRecord generator.p   zEmpty file.z2Improper header, cannot read 112 bytes from handle)r   r   r   iterate)rQ   r   headerrecordsr   r   r   parse   s   

zXdnaIterator.parsec                 c   s   t d|\}}}}}}|dkrtd|tvrtdt||d}	t||d}
|
dd }tt|	|
||d}t| rHt| |jd< |t	v rSt	| |jd	< t
|d
d
krt| t| t dt|d
d }|dkrt|| |d
8 }|dksr|V  dS )z.Parse the file and generate SeqRecord objects.z>BBB25xII60xI12xr   zUnsupported XDNA versionzUnknown sequence typer     )descriptionr?   idmolecule_typetopologyr   r   N)r   r   
_seq_typesr   r!   r.   r
   r   annotations_seq_topologiesr   r   r'   rG   )rQ   r   rW   versionseq_typer^   r   
neg_length
com_lengthsequencecommentr?   r>   num_featuresr   r   r   rV      s2   

zXdnaIterator.iterate)__name__
__module____qualname____doc__rP   rY   rV   __classcell__r   r   rS   r   rI      s
    rI   c                       rH   )
XdnaWriterzWrite files in the Xdna format.c                    s   t  j|dd dS )zInitialize an Xdna writer object.

        Arguments:
         - target - Output stream opened in binary mode, or a path to a file.

        wb)rL   NrN   )rQ   targetrS   r   r   rP      s   zXdnaWriter.__init__c                 C   s  t |}zt|}W n ty   tddw zt| td ty(   Y nw d| _|jd}|du r9d}nd|v r@d}nd	|v rGd
}n	d|v rNd}nd}|jdddkr\d}nd}|j|j	ri|j}n	|j	 d|j }| j
tdd||t|dt|d | j
t|j | j
|d | j
tdd | d | d dd |jD }t|jt| }|dkrtd| dt t|dkrt|d }td| t |dd }| j
tdt| |D ]}	| |	jddgd  d}
|	jD ](}|dv rq|	j| D ]}t|
dkr |
d }
|
| d| d  }
qq| |
 | |	j t|	jjd }t|	jj}d}|	jjd!krW||}}d}| t| | t| | j
td"|ddd | d# q| jrtd$t dS )%a  Write the specified record to a Xdna file.

        Note that the function expects a list (or iterable) of records
        as per the SequenceWriter interface, but the list should contain
        only one record as the Xdna format is a mono-record format.
        zMust have one sequenceNzMore than one sequence foundFr]   r   r   r   r   r   r   r   r^   r   r   rZ   z>BBB25xII60xI11xB   r    r   0c                 S   s,   g | ]}t |jjtrt |jjtr|qS r   )
isinstancerE   r@   r   rA   )r(   fr   r   r   r*   .  s    z)XdnaWriter.write_file.<locals>.<listcomp>z	Dropping z features with fuzzy locationsz%Too many features, dropping the last r:    )r:   translationr+   z="r,   r8   z>BBBBz127,127,127z1Some annotations were truncated to 255 characters)iternextStopIterationr   _has_truncated_stringsr`   getr[   
startswithr\   r   writer   r   bytesseqencode_write_pstringr<   warningswarnr   r1   r;   r#   rE   r@   rA   r9   str)rQ   rX   r>   r]   seqtyper^   rg   r<   droprF   r[   qnamevalr@   rA   r9   r   r   r   
write_file   s   







zXdnaWriter.write_filec                 C   sJ   t |dkrd| _|dd }| jtdt | | j|d dS )z*Write the given string as a Pascal string.rq   TNr   r    )r   rz   r   r}   r   r   )rQ   sr   r   r   r   g  s
   zXdnaWriter._write_pstring)ri   rj   rk   rl   rP   r   r   rm   r   r   rS   r   rn      s    	 rn   )rl   r   rer   structr   r   Bior   Bio.Seqr   Bio.SeqFeaturer   r   r	   Bio.SeqRecordr
   
Interfacesr   r   r_   ra   r   r"   r$   r'   r6   rG   rI   rn   r   r   r   r   <module>   s8   

&I