o
    eT-                     @   s  d dl Z d dlZd dlZd dlZd dlmZ d dlmZmZm	Z	 ddl
mZmZmZmZ G dd dZded	ed
dfddZded	ed
dfddZ				dBdedede	e de	e de	e de	e d
dfddZdCdedede	e deded
dfddZded
dfdd Zded!ed
dfd"d#Zd$ed
ee fd%d&Zd'ed(eegee f d
ee fd)d*Zd+ed
ee fd,d-Zd$ed
ee fd.d/Zd+ed
ee fd0d1Zd$ed
ee fd2d3Zd4ed
efd5d6Zd7ed
efd8d9Z ded
efd:d;Z!ded<ed
dfd=d>Z"ded?ed
efd@dAZ#dS )D    N)chain)CallableIterableOptional   )TensorProto
ModelProtoAttributeProto
GraphProtoc                   @   s   e Zd ZdeddfddZdS )ExternalDataInfotensorreturnNc                 C   sf   d| _ d | _d | _d | _d| _|jD ]
}t| |j|j q| jr&t	| j| _| jr1t	| j| _d S d S )N )
locationoffsetlengthchecksumbasepathexternal_datasetattrkeyvalueint)selfr   entry r   ID:\Projects\ConvertPro\env\Lib\site-packages\onnx/external_data_helper.py__init__   s   
zExternalDataInfo.__init__)__name__
__module____qualname__r   r   r   r   r   r   r      s    r   r   base_dirr   c                 C   s   t | }t|j}tj||}t|d*}|jr||j |j	r*|
|j	| _n|
 | _W d   dS W d   dS 1 sBw   Y  dS )a  
    Loads data from an external file for tensor.
    Ideally TensorProto should not hold any raw data but if it does it will be ignored.

    Arguments:
        tensor: a TensorProto object.
        base_dir: directory that contains the external data.
    rbN)r   _sanitize_pathr   ospathjoinopenr   seekr   readraw_data)r   r!   infoZfile_locationexternal_data_file_path	data_filer   r   r   load_external_data_for_tensor   s   	
"r.   modelc                 C   s8   t | D ]}t|rt|| tj|_|jdd= qdS )z
    Loads external tensors into model

    Arguments:
        model: ModelProto to load external data to
        base_dir: directory that contains external data
    N)_get_all_tensorsuses_external_datar.   r   DEFAULTdata_locationr   )r/   r!   r   r   r   r   load_external_data_for_model7   s   
r4   r   r   r   r   r   c           	      C   s   |  dstd| j d | jd d = tj| _||d ur!t|nd |d ur*t|nd ||d D ]\}}|d urG| j	 }||_
t||_q2d S )Nr*   zTensor zGdoes not have raw_data field. Cannot set external data for this tensor.)r   r   r   r   r   )HasField
ValueErrornamer   r   EXTERNALr3   r   itemsaddr   strr   )	r   r   r   r   r   r   kvr   r   r   r   set_external_dataH   s$   



r>   T   Fall_tensors_to_one_filesize_thresholdconvert_attributec           	      C   s   t | }|r
t| }|r/tt }|r|}|D ]}|dr,t|j|kr,t	|| qdS |D ]!}|drRt|j|krR|j
}t|sMtt }t	|| q1dS )a  
    Call to set all tensors with raw data as external data. This call should preceed 'save_model'.
    'save_model' saves all the tensors data as external data after calling this function.

    Arguments:
        model (ModelProto): Model to be converted.
        all_tensors_to_one_file (bool): If true, save all tensors to one external file specified by location.
            If false, save each tensor to a file named with the tensor name.
        location: specify the external file that all tensors to save to.
            If not specified, will use the model name.
        size_threshold: Threshold for size of data. Only when tensor's data is >= the size_threshold
            it will be converted to external data. To convert every tensor with raw data to external data set size_threshold=0.
        convert_attribute (bool): If true, convert all tensors to external data
                       If false, convert only non-attribute tensors to external data
    r*   N)_get_initializer_tensorsr0   r;   uuiduuid1r5   sys	getsizeofr*   r>   r7   _is_valid_filename)	r/   r@   r   rA   rB   tensors	file_namer   Ztensor_locationr   r   r   convert_model_to_external_dataa   s(   

rK   c                 C   s@   t | D ]}t|r|dstd|jdd= tj|_qdS )z
    Call to set all tensors which use external data as embedded data. save_model saves all the tensors data as embedded data after calling this function.

    Arguments:
        model (ModelProto): Model to be converted.
    r*   raw_data field doesn't exist.N)r0   r1   r5   r6   r   r   r2   r3   )r/   r   r   r   r    convert_model_from_external_data   s   
rM   	base_pathc                 C   s   t | }tj||j}| dstdtj|s"t|d	  t|dC}|
dd |jdurL| }|j|krF|d|j|   |
|j | }|| j t| |j|| |  W d   dS 1 smw   Y  dS )	a  
    Writes tensor data to an external file according to information in the `external_data` field.

    Arguments:
        tensor (TensorProto): Tensor object to be serialized
        base_path: System path of a folder where tensor data is to be stored
    r*   rL   abzr+br      N    )r   r$   r%   r&   r   r5   r6   isfiler'   closer(   r   tellwriter*   r>   )r   rN   r+   r,   r-   	file_sizer   r   r   r   save_external_data   s"   


"rW   onnx_model_protoc                 C   s   t t| t| S )z=Scan an ONNX model for all tensors and return as an iterator.)r   rC   _get_attribute_tensorsrX   r   r   r   r0      s   r0   	attributefuncc                 c   sL    | j tjkr|| jE dH  | j tjkr"| jD ]}||E dH  qdS dS )zICreate an iterator through processing ONNX model attributes with functor.N)typer	   ZGRAPHgZGRAPHSZgraphs)r[   r\   graphr   r   r   _recursive_attribute_processor   s   
r`   onnx_model_proto_graphc                 c   s:    | j E dH  | jD ]}|jD ]
}t|tE dH  qq
dS )z@Create an iterator of initializer tensors from ONNX model graph.N)Zinitializernoder[   r`   #_get_initializer_tensors_from_graphra   rb   r[   r   r   r   rc      s   

rc   c                 c       t | jE dH  dS )z:Create an iterator of initializer tensors from ONNX model.N)rc   r_   rZ   r   r   r   rC         rC   c                 c   sL    | j D ]}|jD ]}|dr|jV  |jE dH  t|tE dH  q	qdS )zJCreate an iterator of tensors from node attributes of an ONNX model graph.tN)rb   r[   r5   rg   rI   r`   !_get_attribute_tensors_from_graphrd   r   r   r   rh      s   


rh   c                 c   re   )zDCreate an iterator of tensors from node attributes of an ONNX model.N)rh   r_   rZ   r   r   r   rY      rf   rY   r%   c                 C   s
   |  dS )zRemove path components which would allow traversing up a directory tree from a base path.

    Note: This method is currently very basic and should be expanded.
    z/.)lstrip)r%   r   r   r   r#      s   
r#   filenamec                 C   s    t d}|| }|rdS dS )z8Utility to check whether the provided filename is valid.z^[^<>:;,?"*|/]+$TF)recompilematch)rj   exprm   r   r   r   rH      s
   

rH   c                 C   s   |  do
| jtjkS )z?Returns true if the tensor stores data in an external location.r3   )r5   r3   r   r8   )r   r   r   r   r1      s   r1   	field_keyc                 C   s*   t | jD ]\}}|j|kr| j|= qdS )a
  
    Removes a field from a Tensor's external_data key-value store.

    Modifies tensor object in place.

    Arguments:
        tensor (TensorProto): Tensor object from which value will be removed
        field_key (string): The key of the field to be removed
    N)	enumerater   r   )r   ro   ifieldr   r   r   remove_external_data_field   s
   

rs   filepathc                 C   s8   t | D ]}t|r|drt|| |d q| S )a  
    Serializes data for all the tensors which have data location set to TensorProto.External.

    Note: This function also strips basepath information from all tensors' external_data fields.

    Arguments:
        model (ModelProto): Model object which is the source of tensors to serialize.
        filepath: System path to the directory which should be treated as base path for external data.

    Returns:
        ModelProto: The modified model object.
    r*   )r0   r1   r5   rW   Z
ClearField)r/   rt   r   r   r   r   write_external_data_tensors  s   

ru   )NNNN)TNr?   F)$rD   r$   rk   rF   	itertoolsr   typingr   r   r   Zonnx_pbr   r   r	   r
   r   r;   r.   r4   r   r>   boolrK   rM   rW   r0   r`   rc   rC   rh   rY   r#   rH   r1   rs   ru   r   r   r   r   <module>   sR   
($"(	

