U
    yh;!                     @   s  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 d dl	Z	d dl
mZ d dl	mZ e jG dd dZG dd dZeedd	d
Zeeeef dddZee	jjdddZe	jjedddZeedddZeedddZeedddZe	jjdddZdd Zejeed f eeef eeejef  d!d"d#Z e	jjedd$d%Z!ed&d'd(Z"d)d* Z#ejd+d,d-Z$ejd+d.d/Z%dS )0    N)AnyCallableDictIterableTuple)_Cc                   @   s*   e Zd ZU dZeed< eed< dd ZdS )Kernelz$Models a (function, source location)funcsourcec                 O   s   | j ||S N)r	   )selfargskwargs r   F/var/www/html/venv/lib/python3.8/site-packages/torch/_library/utils.py__call__   s    zKernel.__call__N)__name__
__module____qualname____doc__r   __annotations__strr   r   r   r   r   r      s   
r   c                   @   s,   e Zd ZdZedddZddddZdS )	RegistrationHandlez2Does something when someone calls .destroy() on it)
on_destroyc                 C   s
   || _ d S r   Z_on_destroy)r   r   r   r   r   __init__   s    zRegistrationHandle.__init__Nreturnc                 C   s   |    d S r   r   )r   r   r   r   destroy   s    zRegistrationHandle.destroy)r   r   r   r   r   r   r   r   r   r   r   r      s   r   )
stacklevelr   c                 C   s&   t t| }|j d|j }|S )zGet a string that represents the caller.

    Example: "/path/to/foo.py:42"

    Use stacklevel=1 to get the caller's source
    Use stacklevel=2 to get the caller's caller's source
    etc.
    :)inspectgetframeinfosys	_getframefilenamelineno)r   framer
   r   r   r   
get_source!   s    	r(   )qualnamer   c                 C   s6   |  d}t|dkr&td|  d|d |d fS )Nz::   zAExpected `qualname` to be of the form "namespace::name", but got zf. The qualname passed to the torch.library APIs must consist of a namespace and a name, e.g. aten::sinr      )splitlen
ValueError)r)   Zsplitsr   r   r   parse_namespace/   s    

r/   c                 C   sH   t | \}}d|kr$|d\}}nd}ttj|}t||}t||S )N.default)r/   r,   getattrtorchZops)r)   	namespacenameoverloadnspacketr   r   r   	lookup_op;   s    
r9   )opr   c                 C   s   t | tjjst| jdkS )N>   primsprimaten)
isinstancer3   _ops
OpOverloadAssertionErrorr4   r:   r   r   r   
is_builtinF   s    rC   )schemar   c                 C   sT   dd }t | tjjr|| S ddlm} t | tr>|| } t | |sLt|| S )zCheck if the schema is functional.

    An operator is functional if:
    - it does not mutate any of its inputs
    - it does not return a view on any of its inputs
    - it has at least one return
    c                 S   sD   | j r
dS | j}t|dko,tdd |D }|r6dS | js@dS dS )NFr   c                 s   s"   | ]}|j d k	o|j j V  qd S r   )
alias_infois_write).0rr   r   r   	<genexpr>X   s    z>is_functional_schema.<locals>.is_functional.<locals>.<genexpr>T)
is_mutablereturnsr-   any)rD   ZretsZis_non_mutating_viewr   r   r   is_functionalT   s    z+is_functional_schema.<locals>.is_functionalr   )FunctionSchema)r>   r3   r   rN   Ztorchgen.modelr   parserA   )rD   rM   rN   r   r   r   is_functional_schemaK   s    	

rP   )typr   c              	   C   sh   | t t j kpf| t t t j kpf| t t t j kpf| t t t t j kS r   )r   ZListType
TensorTypegetOptionalTyperQ   r   r   r   is_tensorlist_like_typen   s    rV   c                 C   s"   | t j kp | t t j kS r   )r   rR   rS   rT   rU   r   r   r   is_tensor_like_typex   s    rW   rB   c                 C   s   | j dkrdS | j}t|jdks&dS |jd jdkr:dS |jd jj}t|dkrXdS tt|}t|jdk rvdS |jd }|jdkrdS |jj	sdS |jj}t|dkrdS |tt|krdS |jdd D ]}|jdk	r dS qdS )aN  Check if an op is an inplace aten op, i.e. it mutates and returns the first arg.

    TODO: torchgen/model.py's FunctionSchema.parse is the source of truth for this,
    but not all PyTorch builds have torchgen (due to the yaml dependency being weird).
    Figure this out.

    Example: add_(Tensor(a!) x, Tensor y) -> Tensor(a)
    r=   Fr+   r   NT)
r4   _schemar-   rK   rE   Z	after_setnextiter	argumentsrF   )r:   rD   Z	alias_setlocZ	first_argargr   r   r   mutates_and_returns_first_arg|   s6    	



r^   c                 C   s   g }i }t t| jD ]f}| j| }|jrT|j|krF||j ||j< q||j||j< q|t|k rp|||  q||j qt||fS r   )ranger-   r[   
kwarg_onlyr5   default_valueappendtuple)rD   r   r   new_argsZ
new_kwargsiinfor   r   r   fill_defaults   s    

rg   .)rD   r   r   r   c                 c   s~   t | jt |t | ksttt | jD ]L}| j| }|jr\|j|kr,|||j fV  q,|t |krjq,||| fV  q,dS )zzips schema.arguments and (args, kwargs) together.

    Assumes that (args, kwargs) were the inputs to some torch._ops.OpOverload:
    that is, kwargs must be keyword-only arguments and default values may be omitted.
    N)r-   r[   rA   r_   r`   r5   )rD   r   r   re   rf   r   r   r   
zip_schema   s    

rh   c                 C   sD   t | tjjstt| rdS | j}|js.dS t|j	dkr@dS dS )NFr   T)
r>   r3   r?   r@   rA   rC   rX   rJ   r-   rK   )r:   rD   r   r   r   can_generate_trivial_fake_impl   s    ri   r   c                   C   s   t tddS )zIf an op was defined in C++ and extended from Python using the
    torch.library APIs, returns if we require that there have been a
    m.set_python_module("mylib.ops") call from C++ that associates
    the C++ op with a python module.
    ZREQUIRES_SET_PYTHON_MODULET)r2   _utils_internalr   r   r   r   requires_set_python_module   s    rk   c                 O   s~   t | tjjjstg }tjj|| f\}}|D ]6}t |tj	r6tj
|tj
jjr6|t| q6| ||||S r   )r>   r3   utilsZ_python_dispatchZTorchDispatchModerA   Z_pytreeZtree_flattenvaluesZTensorr   Z_dispatch_keyshasZDispatchKeyPythonrb   typeZ__torch_dispatch__)Z	curr_modeZop_overloadr   r   Zoverload_typesZargs_flattened_ar   r   r   handle_dispatch_mode   s    rs   rD   c                 C   s   t dd | jD S )Nc                 s   s   | ]}|j V  qd S r   )r`   )rG   rr   r   r   r   rI      s     z&has_kwarg_only_args.<locals>.<genexpr>)rL   r[   rt   r   r   r   has_kwarg_only_args   s    ru   c                 C   s2   | j D ]&}t|js t|js q|js(q dS dS )NTF)r[   rW   rp   rV   r`   )rD   rr   r   r   r   has_kwarg_only_tensors   s    
rv   )&dataclassesr!   r#   typingr   r   r   r   r   r3   Ztorch._utils_internalrj   r   	dataclassr   r   intr   r(   r/   r?   r@   r9   boolrC   rP   rV   rW   r^   rg   rN   ZArgumentrh   ri   rk   rs   ru   rv   r   r   r   r   <module>   s8   

#
& 
 
	