U
    <cN$                     @   s$  d Z ddlZddlZddl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mZ ddlmZ ddlmZ ed	Zed
ddejdde	jeeeje	jf eee	jee	jdf f dddZeje	jdddZed
ddejdde	jeedddZed
ddeje	j ee	jdddZ!eje	jeeee	j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d
dd.ejed/d0d1Z)ed
dd2d3d4 Z*eej	j_+eej	j_,e!ej	j _+e)ej	j_-e*ej	j"_.dS )5zAImporting this patches torch._C classes to add ONNX conveniences.    N)AnyIterableTupleUnion)_C)_onnx)_deprecationutils)GLOBALS)	_beartypez^(.+)_(([ifstgz])|(ty))$z1.13z1.14zknote 'g.op()' is to be removed from torch.Graph. Please open a GitHub issue if you need this functionality.   )outputs.)gopnameraw_argsr   returnc          	         s   dd |  D } fdd|D }d|kr<|d\}}nd}|} t |||f||}tjrxt|tj	tj
 |dkr| S t| S )a  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.
        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 `Node`, representing each output of the ONNX operator
            in positional.
        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 node representing the single output of this operator (see the `outputs`
        keyword argument for multi-return nodes).
    c                 S   s   i | ]\}}|d k	r||qS N ).0kvr   r   ;/tmp/pip-unpacked-wheel-gikjz4vx/torch/onnx/_patch_torch.py
<dictcomp>D   s       z_graph_op.<locals>.<dictcomp>c                    s   g | ]}t  |qS r   )_const_if_tensor)r   argr   r   r   
<listcomp>F   s     z_graph_op.<locals>.<listcomp>::onnxr   )itemssplitZ
insertNode	_new_noder
   Zonnx_shape_inferencer   Z(_jit_pass_onnx_node_shape_type_inferencer	   Z_params_dictZexport_onnx_opset_versionoutputtupler   )	r   r   r   r   kwargsargs	namespaceopnr   r   r   	_graph_op   s     .  r)   r   c                 C   s*   |d kr|S t |tjr|S t| d|dS )NConstant)value_z)
isinstancer   Valuer)   )r   r   r   r   r   r   Z   s
    r   zknote 'g.at()' is to be removed from torch.Graph. Please open a GitHub issue if you need this functionality. )overload_name)r   operatorr/   c                O   s   t | df|||d|S )Nz
aten::ATen)Z
operator_sZoverload_name_s)r)   )r   r0   r/   r%   r$   r   r   r   _aten_opc   s    	r1   zknote 'b.op()' is to be removed from torch.Block. Please open a GitHub issue if you need this functionality.)blockr   r%   c                 O   s   d|kr| d\}}nd}|}| | d| |}|dk}ddh}t| D ]"\}	}
|	|krdqRt||	|
|d qRt| }t|dkr| S |S )Nr   r   ateninplacer3   r   )	r    ZaddNodesortedr   _add_attributer#   r   lenr"   )r2   r   r%   r$   r&   r'   r(   r3   
skip_attrsr   r   r   r   r   r   	_block_opv   s    r:   )r   r&   r'   r   r%   r   c                 O   s\   |dk}|  | d| ||}ddh}t| D ]"\}	}
|	|krFq4t||	|
|d q4|S )a4  Creates a new node in the graph.

    Args:
        g: The graph to create the operator on.
        namespace: The namespace of the operator. E.g., "aten", "onnx".
        op: The name of the operator to create.
        outputs: The number of the outputs of the node.

    Returns:
        The new node.
    r3   r   r4   r5   )creater6   r   r7   )r   r&   r'   r   r%   r$   r3   noder9   r   r   r   r   r   r!      s    r!   c                 C   s(   t | tjj o&t | tj o&t | tS r   )r,   torchZ_sixZstring_classesTensorr   )valuer   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   )numelAssertionErrorrA   r   r   r   _scalar   s    rE   )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    rG   )r<   keyr?   r3   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i_)_ATTR_PATTERNmatch
ValueErrorgroupr@   rG   r,   r=   r>   rC   rE   floatgetattr)r<   rH   r?   r3   mnamekindr   r   r   r7      s"    



r7   z/Use 'g.op()' to create a constant node instead.)type_c                 O   s$  t |tjst|dk	std}|dks>|dks>t|dhkrHdg}d}| }|dkrdtj| }n|dkrxtj| }nl|dkrtj	| }nX|d	krtj
| }nD|d
krtj| }n0|dkrtj| }n|dkrtj| }ntd|| |r| jd|d|i|S | jd|d|i|S )zThis helper function can create either constant tensor or constant scalar.

    If dims is None or 0 or [0], generate a 0-d tensor (scalar).
    NFr   r   TcharshortintlongZhalfrR   doublezfUnknown type, type should be one of the following strings: char, short, int, long, half, float, doubler*   r+   Zvalue_t)r*   )r*   )r,   numbersNumberrD   setlowerr=   Z
CharTensorZShortTensorZ	IntTensorZ
LongTensorZ
HalfTensorZFloatTensorZDoubleTensorrP   Zfill_r'   )r   r?   ZdimsrW   r%   r$   ZisscalarZtensorr   r   r   _graph_constant   s8    

ra   z6Internally use '_node_get' in symbolic_helper instead.c                 C   s   |  |}t| ||S )zlGets attributes of a node which is polymorphic over return type.

    This is monkey-patched onto Node.
    )ZkindOfrS   )selfr   selr   r   r   _node_getitem  s    

rd   )/__doc__r]   retypingr   r   r   r   r=   r   Ztorch._Cr   rF   Z
torch.onnxr   r	   Ztorch.onnx._globalsr
   Ztorch.onnx._internalr   compilerN   
deprecatedZbeartypeZGraphstrr>   r-   rZ   r)   r   r1   ZBlockr:   Noder!   r@   rE   boolrG   r7   ra   rd   r'   atZconstant__getitem__r   r   r   r   <module>   s   
=    
  6
	



