
    Ǆg.                        d dl Z d dlmZmZmZmZmZmZ d dlZd dl	m
Z
  e j                  e      Z G d d      Z G d d      Z G d d	e      Z G d
 d      Z e       Zd Zdej(                  defdZdej(                  deeej(                  f   fdZddee   fdZd ZdefdZdee   fdZdedefdZdedeeef   fdZdej(                  defdZdZ defdZ!y)    N)AnyDictOptionalProtocolTupleUnionparse_namespacec                   4    e Zd Zdededej                  fdZy)FakeScriptObjectwrapped_objscript_class_namexc                 .    || _         || _        || _        y N)r   r   real_obj)selfr   r   r   s       j/home/mcse/projects/flask_80/flask-venv/lib/python3.12/site-packages/torch/_library/fake_class_registry.py__init__zFakeScriptObject.__init__   s    & "3    N)__name__
__module____qualname__r   strtorchScriptObjectr    r   r   r   r      s"    C C EDVDV r   r   c                   @    e Zd Zdededeej                     fdZd Z	y)FakeScriptMethodself_fake_objmethod_nameschemac                 .    || _         || _        || _        y r   )r    r!   r"   )r   r    r!   r"   s       r   r   zFakeScriptMethod.__init__   s     +&r   c                 P    ddl m}  || j                  | j                  g|i |S )Nr   )call_torchbind)!torch._higher_order_ops.torchbindr%   r    r!   )r   argskwargsr%   s       r   __call__zFakeScriptMethod.__call__    s(    Dd00$2B2BTTTVTTr   N)
r   r   r   r   r   r   r   FunctionSchemar   r)   r   r   r   r   r      s4    '  --.	Ur   r   c                   6    e Zd Zedej
                  fd       Zy)HasStaticMethodFromRealr   c                      y r   r   )clsr   s     r   	from_realz!HasStaticMethodFromReal.from_real'   s    r   N)r   r   r   classmethodr   r   r/   r   r   r   r,   r,   &   s!    !3!3  r   r,   c                   n    e Zd ZddZdedefdZdedefdZddeddfdZ	dedefdZ
dd	Zdeddfd
Zy)FakeClassRegistryreturnNc                     i | _         y r   _registered_classr   s    r   r   zFakeClassRegistry.__init__-   s
    13r   full_qualnamec                     || j                   v S r   r5   r   r8   s     r   has_implzFakeClassRegistry.has_impl0   s     6 666r   c                 B    | j                  |       | j                  |   S r   )_check_registeredr6   r:   s     r   get_implzFakeClassRegistry.get_impl3   s!    }-%%m44r   c                 r    | j                  |      rt        j                  d||       || j                  |<   y )NzE%s is already registered. Previous fake class is overridden with  %s.)r;   logwarningr6   )r   r8   
fake_classs      r   registerzFakeClassRegistry.register7   s5    =='KKW
 1;}-r   c                     | j                  |      st        j                  d|       y | j                  j	                  |      S )NziCannot deregister %s. Please use register_fake_class to register it first. Or do you dereigster it twice?)r;   r@   rA   r6   popr:   s     r   
deregisterzFakeClassRegistry.deregister@   s;    }}]+KK2 ))--m<<r   c                 8    | j                   j                          y r   )r6   clearr7   s    r   rH   zFakeClassRegistry.clearJ   s    $$&r   c                 <    || j                   vrt        | d      y )NzH is not registered. Please use register_fake_class to register it first.)r6   RuntimeErrorr:   s     r   r=   z#FakeClassRegistry._check_registeredM   s-     6 66 /!ij  7r   )r3   Nr   )r   r   r   r   r   boolr;   r   r>   rC   rF   rH   r=   r   r   r   r2   r2   ,   sk    47c 7d 75c 5c 5;c ;t ;= = ='s t r   r2   c                     t        | t              st        d      | D ]I  }t        |t              st        d      t        |      dk(  rt        |d   t              r@t        d       y )NzExpect flat x to be a tuple.z&Expect flat x to be a tuple of tuples.   r   zXExpect element of flat x to be a tuple of two elements with first element being a string)
isinstancetuplerJ   lenr   )flat_xtps     r   _check_valid_flat_script_objrS   X   se    fe$9:: "e$GHH2w!|:beS#9j r   r   r3   c                     t        | d      sy| j                         dv sJ d| j                                 | j                         dk(  S )Ntracing_modeF)realfakez0tracing_mode can be either real or fake but got rV   )hasattrrU   )r   s    r   tracing_with_realrY   f   s\    1n%>>    M 
:!..:J9KLM  >>v%%r   c           
          dd l mc m} ddlm} t        |      r|S  |       5  |j                         }d d d        t               |j                  t        j                   fd|      }t        |      j                  |      }t        ||j                         j                         |      }|j!                         D ]  }t#        ||d       }	|	rjt%        |	      st'        d| d|	 d      t#        ||      }
d }t)        |
t        j*                        r|
j,                  }t/        ||t1        |||             |h d}||vst2        j5                  d||        |S # 1 sw Y   ,xY w)	Nr   )_disable_current_modesc                 &    j                  |       S r   )from_tensor)t	fake_modes    r   <lambda>z#maybe_to_fake_obj.<locals>.<lambda>   s    )''* r   zExpect z to be a callable but got .>   __get_state____set_state____obj_flatten__z.fake object of %s doesn't implement method %s.)torch.utils._pytreeutils_pytreetorch.utils._python_dispatchr[   rY   rd   rS   tree_map_onlyr   Tensor"_find_fake_class_for_script_object__obj_unflatten__r   _typequalified_name_method_namesgetattrcallablerJ   rN   ScriptMethodr"   setattrr   r@   rA   )r_   r   pytreer[   rQ   fake_flattenedfake_xfake_x_wrappednameattr	real_attrmethod_schemaoverride_skip_lists   `            r   maybe_to_fake_objr}   q   se    )(C  
 	! %""$% !())*N 02DD^TF%faggi.F.F.H!LN! WvtT*D>"WTF2LTFRS#TUU4(I =AM)U%7%78 ) 0 0 }E "W--LaQUV+W, K% %s   E  E*rB   c                 4     dt         f fd}||S  ||      S )a
  Register a fake implementation for this class.

    It's in the same spirit of registering a fake implementation for
    an operator but with the difference that it
    associates a fake class with the original torch bind class (registered
    with torch::class_). In this way, torch.compile can handle them properly
    in components such as Dynamo and AOTAutograd.

    This API may be used as a decorator (see example). For the fake class, users
    are required to provide a from_real classmethod that takes a real object and
    returns an instance of the fake class. All tensors in the fake object should also
    be properly fakified with to_fake_tensor() in from_real.


    Examples:
        # For a custom class Foo defined in test_custom_class_registration.cpp:

        TORCH_LIBRARY(_TorchScriptTesting, m) {
          m.class_<TensorQueue>("_TensorQueue")
            .def(torch::init<at::Tensor>())
            .def("push", &TensorQueue::push)
            .def("pop", &TensorQueue::pop)
            .def("top", &TensorQueue::top)
            .def("size", &TensorQueue::size)
            .def("clone_queue", &TensorQueue::clone_queue)
            .def("__obj_flatten__", &TensorQueue::__obj_flatten__)
            .def_pickle(
                // __getstate__
                [](const c10::intrusive_ptr<TensorQueue>& self)
                    -> c10::Dict<std::string, at::Tensor> {
                  return self->serialize();
                },
                // __setstate__
                [](c10::Dict<std::string, at::Tensor> data)
                    -> c10::intrusive_ptr<TensorQueue> {
                  return c10::make_intrusive<TensorQueue>(std::move(data));
                });
            };
        # We could register a fake class FakeTensorQueue in Python as follows:
        import torch

        @torch._library.register_fake_class("_TorchScriptTesting::_TensorQueue")
        class FakeTensorQueue:
            def __init__(self, queue):
                self.queue = queue

            @classmethod
            def __obj_unflatten__(cls, flattened_ctx):
                return cls(**dict(ctx))

            def push(self, x):
                self.queue.append(x)

            def pop(self):
                return self.queue.pop(0)

            def size(self):
                return len(self.queue)

    In this example, the original TensorQeue need to addd a __obj_flatten__ method
    to the class TensorQueue and the flattend result is passed into FakeTensorQueue's
    __obj_unflatten__ as inputs to create a fake class. This protocol allows pytorch to look
    at the contents of the script object and properly handle them in the subsystems
    like dynamo, aot_aotugrad or more.
    rB   c                 X   t              \  }}t        j                  j                  ||      }t	        | t
        d       }|st        |  dt
         d      t        | j                  t
           t              st        t
         d      t        j                  t              |        | S )Nz doesn't define a classmethod ra   z method is not a classmethod.)r
   r   _C _get_custom_class_python_wrapperrp   _CONVERT_FROM_REAL_NAMErJ   rN   __dict__r0   global_fake_class_registryrC   _full_qual_class_name)rB   nsrx   torchbind_classfrom_methodqualnames        r   innerz"register_fake_class.<locals>.inner   s    "8,D  ((CCBMj*A4H,<=T<UUVW  *--.EFT*++HI  	#++,A(,KZXr   )r,   )r   rB   r   s   `  r   register_fake_classr      s)    F1 ( r   c                 >    t         j                  t        |             S r   )r   rF   r   )r   s    r   deregister_fake_classr     s    %001Fx1PQQr   c                 ,    t         j                  |       S r   )r   r;   r8   s    r   has_fake_classr     s    %..}==r   c                 D    t        |       sy t        j                  |       S r   )r   r   r>   r   s    r   find_fake_classr     s    -(%..}==r   r   c                 4    t        |       \  }}d|z   dz   |z   S )Nz__torch__.torch.classes.ra   r	   )r   r   rx   s      r   r   r     s%    x(HB%*S0477r   r8   c                 \    | j                  d      }t        |      dk(  sJ |\  }}}}}||fS )Nra      )splitrP   )r8   splits_torchtorch_nsclassesr   
class_names          r   _ns_and_class_namer     s>      %Fv;!06-FHgr:z>r   c                     | j                         j                         }t        |      \  }}t        |      }|t	        d| d| d| dt
         d	      |S )Nz ScriptObject's zA haven't registered a fake class. Please use register_fake_class(z::a  ) to annotate a fake class for the script obj. Specifically, create a python class that implements a fake version for all the methods that're used in the program and put annotated class in the program e.g. after loading the library. The fake methods can be written in the same way as a meta kernel for an operator but need to additionally simulate the object's states. Be sure to add a z; classmethod to enable creating a fake obj from a real one.)rm   rn   r   r   rJ   r   )r   r8   r   r   rB   s        r   rk   rk     s{    GGI,,.M'6NB
 /J}o .//1d"ZL A? @W>W X>?
 	
 r   rl   c                 d   t        |      }t        |t        d       }|st        | dt         d      t        j
                  j                  j                  | d       t        j
                  j                  j                  fd      5  |j                  |      cd d d        S # 1 sw Y   y xY w)Nz must define a classmethod z2 that converts the real object to the fake object.c                       S r   r   )ctxs   r   r`   z%_fake_obj_from_real.<locals>.<lambda>?  s     r   )
rk   rp   r   rJ   r   _library	fake_implFakeImplCtxset_ctx_getterr/   )r_   r   rB   from_real_methodr   s       @r   _fake_obj_from_realr   3  s    3A6Jz+BDIl56M5N@B
 	
 ..
"
"
.
.y$
?C		!	!	0	0	= '##A&' ' 's   B&&B/r   )"loggingtypingr   r   r   r   r   r   r   torch._library.utilsr
   	getLoggerr   r@   r   r   r,   r2   r   rS   r   rK   rY   r}   r   r   r   r   r   r   r   rk   r   r   r   r   r   <module>r      s=    > >  0 g! U U"h % %P /0 &++ & &4$$4
U///04nYh7N.O YxR>T >>hsm >8C 8C 8c eCHo %*<*<  " . ' 'r   