U
    <cj-                     @   s  d Z ddlZddlZddlZddlmZmZmZmZmZm	Z	m
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 edZd	d
hZejG dd dZejdddeeejeee	ee	edf ejf dddZejddeee
ejejf edddZ ejedddZ!d/e
ej"ej#f eee$e$eee%ejd	ddZ&ejdd Z'ejejd d!d"Z(eje%d#d$d%Z)ejejeee%d&d'd(Z*ejeje%d)d*d+Z+ejejeej, d,d-d.Z-dS )0zFUtilities for manipulating the torch.Graph object and the torchscript.    N)AnyDictIterableOptionalSequenceTupleUnion)_C)_onnx)GLOBALS)	_beartypez^(.+)_(([ifstgz])|(ty))$Zinplaceatenc                   @   s   e Zd ZU dZejed< ejed< eed< ej	ed< e
edf ed< e
ejejf ed< eed	d
dZejddeeejejf edddZejddeedddZdS )GraphContextaI  Extra context for symbolic functions with all methods from torch.Graph.

    NOTE: This class is not meant for external consumption. Please do not depend on
    it outside of torch.onnx as the interface may evolve.

    Attributes:
        graph: The _C.Graph being constructed.
        block: The current _C.Block being constructed.
        opset: The opset version.
        original_node: Current node that is being converted from.
        params_dict: Mapping from graph initializer name to IValue.
        env: Mapping from Torch domain graph Value to ONNX domain graph Value.
    graphblockopsetZoriginal_nodez	_C.IValueparams_dictenv)namereturnc                 C   s   t | j|S N)getattrr   )selfr    r   B/tmp/pip-unpacked-wheel-gikjz4vx/torch/onnx/_internal/jit_utils.py__getattr__.   s    zGraphContext.__getattr__   outputs)opnameraw_argsr   c                O   s   t | |f|d|i|S )a  Creates an ONNX operator "opname", taking "raw_args" as inputs and "kwargs" as attributes.

        The set of operators and the inputs/attributes they take
        is documented at https://github.com/onnx/onnx/blob/master/docs/Operators.md

        Args:
            opname: The ONNX operator name, e.g., `Abs` or `Add`, or an operator qualified
                with a namespace, e.g., `aten::add`.
            raw_args: The inputs to the operator; usually provided
                as arguments to the `symbolic` definition.
            outputs: The number of outputs this operator returns.
                By default an operator is assumed to return a single output.
                If `outputs` is greater than one, this functions returns a tuple
                of output `Value`, representing each output of the ONNX operator
                in order.
            kwargs: The attributes of the ONNX operator, whose keys are named
                according to the following convention: `alpha_f` indicates
                the `alpha` attribute with type `f`.  The valid type specifiers are
                `f` (float), `i` (int), `s` (string) or `t` (Tensor).  An attribute
                specified with type float accepts either a single float, or a
                list of floats (e.g., you would say `dims_i` for a `dims` attribute
                that takes a list of integers).

        Returns:
            The value representing the single output of this operator (see the `outputs`
            keyword argument for multi-return nodes).
        r   )_add_op)r   r   r   r    kwargsr   r   r   op1   s    $zGraphContext.op )overload_name)operatorr%   c                O   s   | j d|||d|S )z~Generates an ONNX ATen op node.

        This function is for backward compatibility with the old symbolic functions.
        
aten::ATen)Z
operator_sZoverload_name_s)r'   )r#   )r   r&   r%   argsr"   r   r   r   aten_opW   s     zGraphContext.aten_opN)__name__
__module____qualname____doc__r	   Graph__annotations__BlockintNoder   strValuer   r   r   beartyper   torchTensorr#   r)   r   r   r   r   r      s"   



%r   r   )r   n_blocks.)graph_contextr   inputsr   r8   r   c                O   sz   | j |f|d|i|}t|tr2|d  }n| }g }t|D ]$}	| }
tj| |
d}|| qF|t	||fS )aP  Creates an ONNX operator "opname", taking inputs and attributes.

    Args:
        graph_context: The context for the current graph.
        opname: The ONNX operator name, e.g., `Abs` or `Add`, or an operator qualified
            with a namespace, e.g., `aten::add`.
        inputs: The inputs to the operator.
        outputs: The number of outputs this operator returns.
            By default an operator is assumed to return a single output.
            If `outputs` is greater than one, this functions returns a tuple
            of output `Value`, representing each output of the ONNX operator
            in order.
        n_blocks: The number of sub-blocks to create in the node.
        attributes: The attributes of the ONNX operator.

    Returns:
        A tuple of (output_values, new_contexts, node) where:
            output_values: ONe or more output value of this operator
                (see the `outputs` keyword argument for multi-return nodes).
            new_contexts: A tuple of new graph contexts for each sub-block.
            node: The node representing the operator.
    r   r   )r   )
r#   
isinstancer   noderangeZaddBlockdataclassesreplaceappendtuple)r9   r   r   r8   r:   
attributesZoutput_valuesr<   Znew_contexts_Z	new_blockZnew_contextr   r   r   add_op_with_blocksf   s     
rD   r   )r9   r   r(   r   c             
      sp    fdd|D }dd |  D }d|kr4d| }t j||| j j|tjd}|dkrd| S t|	 S )	a4  Creates an ONNX operator "opname", taking "args" as inputs and attributes "kwargs".

    The set of operators and the inputs/attributes they take
    is documented at https://github.com/onnx/onnx/blob/master/docs/Operators.md

    This function is monkey-patched onto Graph.

    Args:
        g: The Torch Graph or Block.
        opname: The ONNX operator name, e.g., `Abs` or `Add`, or an operator qualified
            with a namespace, e.g., `aten::add`.
        args: The inputs to the operator; usually provided
            as arguments to the `symbolic` definition.
        outputs: The number of outputs this operator returns.
            By default an operator is assumed to return a single output.
            If `outputs` is greater than one, this functions returns a tuple
            of output `Value`, representing each output of the ONNX operator
            in order.
        kwargs: The attributes of the ONNX operator, whose keys are named
            according to the following convention: `alpha_f` indicates
            the `alpha` attribute with type `f`.  The valid type specifiers are
            `f` (float), `i` (int), `s` (string) or `t` (Tensor).  An attribute
            specified with type float accepts either a single float, or a
            list of floats (e.g., you would say `dims_i` for a `dims` attribute
            that takes a list of integers).

    Returns:
        (Union[_C.Value, Tuple[_C.Value, ...]])
        The value representing the single output of this operator (see the `outputs`
        keyword argument for multi-return nodes).
    c                    s   g | ]}t  |qS r   )_const_if_tensor).0argr9   r   r   
<listcomp>   s     z_add_op.<locals>.<listcomp>c                 S   s   i | ]\}}|d k	r||qS r   r   )rF   kvr   r   r   
<dictcomp>   s       z_add_op.<locals>.<dictcomp>z::zonnx::)r   opset_version	n_outputsshape_inferencer   )
items_create_noder   r   r   r   Zonnx_shape_inferenceoutputrA   r   )r9   r   r   r(   r"   r:   rB   r<   r   rH   r   r!      s"    'r!   rH   c                 C   s*   |d kr|S t |tjr|S t| d|dS )Nzonnx::Constant)Zvalue_z)r;   r	   r4   r!   )r9   rG   r   r   r   rE      s
    rE   T)	graph_or_block	domain_opr:   rB   r   rM   rN   rO   r   c                 C   s   t | tjr*| }||||}	||	}	n<t | tjrf| }
|
||}	|dkrftd|D ]}|	  qXt	|	
 }t||kst|d}t| D ]"\}}|tkrqt|	|||d q|rt|	|| |	S )z:Creates an node 'domain_op', taking inputs and attributes.r   zaten::)r   )r;   r	   r.   createZ
insertNoder0   ZaddNoder=   Z	addOutputrA   r   lenAssertionError
startswithsortedrP   _SKIP_NODE_ATTRIBUTES_add_attributeZ(_jit_pass_onnx_node_shape_type_inference)rS   rT   r:   rB   r   rM   rN   rO   r   r<   r   rC   Znode_ouputsr   keyvaluer   r   r   rQ      s(    

rQ   c                 C   s(   t | tjj o&t | tj o&t | tS r   )r;   r6   Z_sixZstring_classesr7   r   )r]   r   r   r   _is_onnx_list  s
    r^   xc                 C   s   |   dkst| d S )z,Convert a scalar tensor into a Python value.r   r   )numelrW   r_   r   r   r   _scalar  s    rb   )r   c                   C   s   t jtjjkotjS r   )r   Zoperator_export_type_C_onnxZOperatorExportTypesZONNX_ATEN_FALLBACKZ_CAFFE2_ATEN_FALLBACKr   r   r   r   _is_caffe2_aten_fallback  s    rd   )r<   r\   r]   r   c                 C   s   t |}|dkr"td| d|d|d }}t|rH|d7 }|rt rt|tjr|	 dkrrtdt
|}t|trd}nd	}t| | d
||S )z7Initializes the right attribute based on type of value.NzInvalid attribute specifier 'z<' names must be suffixed with type, e.g. 'dim_i' or 'dims_i'r      sz Should not pass tensor attributefirC   )_ATTR_PATTERNmatch
ValueErrorgroupr^   rd   r;   r6   r7   ra   rb   floatr   )r<   r\   r]   r   mr   kindr   r   r   r[     s"    



r[   )r`   r   c                 C   s   |   tj S r   )typeZisSubtypeOfr	   
TensorTypegetr_   r   r   r   
_is_tensor9  s    rs   )r]   r   c                 C   s&   t | sd S ttj|  }| S r   )rs   typingcastr	   rq   rp   device)r]   Ztensor_typer   r   r   get_device_from_value>  s    rw   )T).r-   r>   rert   r   r   r   r   r   r   r   r6   r	   Ztorch._Cr
   rc   Ztorch.onnx._globalsr   Ztorch.onnx._internalr   compileri   rZ   Z	dataclassr   r5   r3   r4   r1   r2   rD   r7   r!   rE   r.   r0   dictboolrQ   r^   rb   rd   r[   rs   rv   rw   r   r   r   r   <module>   st   $
P/> '
