
    lj7                    >   d Z ddlmZ ddlZddlZddlZddlZddlmZm	Z	m
Z
mZ ddlmZ ddlmZmZmZmZ ddlmZmZmZ ddlZddlmZmZ erdd	lmZ dd
lmZ ddl m!Z! ddl"m#Z# ddl$m%Z% g dZ&h dZ' G d d          Z( G d dej)                  Z*d"dZ+d#d!Z,dS )$zUtilities for scene caching.    )annotationsN)CallableHashableIterableSequence)perf_counter)FunctionTypeMappingProxyType
MethodType
ModuleType)TYPE_CHECKINGAnyoverload)configlogger)	Animation)Camera)Mobject)OpenGLCamera)Scene)KEYS_TO_FILTER_OUTget_hash_from_play_callget_json>   
backgroundoriginal_idpixel_arraypixel_array_to_cairo_contextc                      e Zd ZdZ e            ZdZdZedd            Z	e	 ddd            Z
ed d            Zed!d            Zed"d            Ze	 d#d$d            ZdS )%	_MemoizeraE  Implements the memoization logic to optimize the hashing procedure and prevent
    the circular references within iterable processed.

    Keeps a record of all the processed objects, and handle the logic to return a place
    holder instead of the original object if the object has already been processed
    by the hashing logic (i.e, recursively checked, converted to JSON, etc..).

    This class uses two signatures functions to keep a track of processed objects :
    hash or id. Whenever possible, hash is used to ensure a broader object
    content-equality detection.
    APi clstype[_Memoizer]returnNonec                8    | j                                          d S N)_already_processedclearr!   s    N/home/agentuser/manim-venv/lib/python3.11/site-packages/manim/utils/hashing.pyreset_already_processedz!_Memoizer.reset_already_processed8   s    $$&&&&&    F	is_methodboolr   c                     d fd}|S )ad  Decorator to handle the arguments that goes through the decorated function.
        Returns the value of ALREADY_PROCESSED_PLACEHOLDER if the obj has been processed,
        or lets the decorated function call go ahead.

        Parameters
        ----------
        is_method
            Whether the function passed is a method, by default False.
        funcCallable[[Any], Any]r#   r   c                "     r fdS  fdS )Nc                <                          | fd          S )Nc                     |           S r&    )objr0   selfs    r*   <lambda>z^_Memoizer.check_already_processed_decorator.<locals>.layer.<locals>.<lambda>.<locals>.<lambda>P   s    dC r,   default_function_handle_already_processed)r7   r6   r!   r0   s   ` r*   r8   zL_Memoizer.check_already_processed_decorator.<locals>.layer.<locals>.<lambda>N   s0    )F)F%@%@%@%@%@ *G * * r,   c                2                         |           S )Nr9   r;   )r6   r!   r0   s    r*   r8   zL_Memoizer.check_already_processed_decorator.<locals>.layer.<locals>.<lambda>R   s    s<<SSW<XX r,   r5   )r0   r!   r-   s   `r*   layerz:_Memoizer.check_already_processed_decorator.<locals>.layerJ   sA            YXXXXXr,   )r0   r1   r#   r   r5   )r!   r-   r>   s   `` r*   !check_already_processed_decoratorz+_Memoizer.check_already_processed_decorator<   s5    	Y 	Y 	Y 	Y 	Y 	Y 	Y r,   r6   r   c                0    |                      |d           S )a  Checks if obj has been already processed. Returns itself if it has not been,
        or the value of ALREADY_PROCESSED_PLACEHOLDER if it has.
        Marks the object as processed in the second case.

        Parameters
        ----------
        obj
            The object to check.

        Returns
        -------
        Any
            Either the object itself or the placeholder.
        c                    | S r&   r5   xs    r*   r8   z3_Memoizer.check_already_processed.<locals>.<lambda>g   s    A r,   r;   r!   r6   s     r*   check_already_processedz!_Memoizer.check_already_processedV   s    " ,,S++>>>r,   c                n    |                      |d            |                     |t          d d          S )zMarks an object as processed.

        Parameters
        ----------
        obj
            The object to mark as processed.
        c                    | S r&   r5   rB   s    r*   r8   z-_Memoizer.mark_as_processed.<locals>.<lambda>r   s    Q r,   c                    | S r&   r5   rB   s    r*   r8   z-_Memoizer.mark_as_processed.<locals>.<lambda>s   s    a r,   F)	memoizing)r<   _returnidrD   s     r*   mark_as_processedz_Memoizer.mark_as_processedi   s8     	%%c;;777{{3KK5{AAAr,   r:   r1   	str | Anyc                (   t          |t          t          t          t          f          r|d | j        fvr|S t          |t                    r-	 |                     |t          |          S # t          $ r Y nw xY w|                     |t          |          S r&   )
isinstanceintfloatstrcomplexALREADY_PROCESSED_PLACEHOLDERr   rJ   hash	TypeErrorrK   )r!   r6   r:   s      r*   r<   z#_Memoizer._handle_already_processedu   s     	
 
 	 $ ABBB Jc8$$ 	{{3.>???    	
 {{3$4555s   A( (
A54A5Tobj_to_membership_signCallable[[Any], int]default_funcrI   c                (    ||          }|| j         v r| j        S |rkt          j        sEt	          | j                   | j        k    r(t          j        d           t          j        d           | j                             |            ||          S )NzIt looks like the scene contains a lot of sub-mobjects. Caching is sometimes not suited to handle such large scenes, you might consider disabling caching with --disable_caching to potentially speed up the rendering process.z\You can disable this warning by setting disable_caching_warning to True in your config file.)	r'   rT   r   disable_caching_warninglenTHRESHOLD_WARNINGr   warningadd)r!   r6   rW   rY   rI   obj_membership_signs         r*   rJ   z_Memoizer._return   s     54S99#"88844 	<2.//33HHH6   3  
 "&&':;;;|C   r,   N)r!   r"   r#   r$   )F)r!   r"   r-   r.   r#   r   )r!   r"   r6   r   r#   r   )r!   r"   r6   r   r#   r$   )r!   r"   r6   r   r:   r1   r#   rM   )T)r!   r"   r6   r   rW   rX   rY   r1   rI   r.   r#   rM   )__name__
__module____qualname____doc__setr'   rT   r]   classmethodr+   r?   rE   rL   r<   rJ   r5   r,   r*   r   r   %   s       
 
  %)!' ' ' [' 05    [2 ? ? ? [?$ 	B 	B 	B [	B 6 6 6 [66  ! ! ! ! [! ! !r,   r   c                  ^     e Zd ZddZedd            Zedd
            Zd Zd fdZ xZS )_CustomEncoderr6   r   r#   c                   t          |t                    st          |t          t          f          rt	          j        |          }i t          j        |j                  t          j        |j                  }t          |          D ] }t          ||         t                    r||= !	 t	          j
        |          }n# t          t          f$ r d}Y nw xY w|                     ||d          S t          |t          j                  rA|j        dk    r't          j        |d          }dt%          |           S t%          |          S t'          |d          r3|j        }t          |t*                    rdS |                     |          S t          |t          j                  rt/          |          S t1          t3          |                    S )a  This method is used to serialize objects to JSON format.

        If obj is a function, then it will return a dict with two keys : 'code', for
        the code source, and 'nonlocals' for all nonlocalsvalues. (including nonlocals
        functions, that will be serialized as this is recursive.)
        if obj is a np.darray, it converts it into a list.
        if obj is an object with __dict__ attribute, it returns its __dict__.
        Else, will let the JSONEncoder do the stuff, and throw an error if the type is
        not suitable for JSONEncoder.

        Parameters
        ----------
        obj
            Arbitrary object to convert

        Returns
        -------
        Any
            Python object that JSON encoder will recognize

         )code	nonlocalsi  )d   rm   zTRUNCATED ARRAY: __dict__MappingProxy)rO   r   r   r	   inspectgetclosurevarscopyglobalsrl   list	getsourceOSErrorrV   _cleaned_iterablenpndarraysizeresizereprhasattrrn   r
   uint8rP   rR   type)r7   r6   cvarscvardictirk   temps          r*   defaultz_CustomEncoder.default   s   , 3
++ "	&2
 2
 "	 *3//EQ$)EM22Qdi6P6PQH(^^ $ $ hqk:66 $ (--Y'   
  ))4h*O*OPPPRZ(( 	x$iZ00649966699S*%% 	<D $ 011 &%~))$///RX&& 	s88O499~~s   +C   CCiterableSequence[Any]	list[Any]c                    d S r&   r5   r7   r   s     r*   rw   z _CustomEncoder._cleaned_iterable   s    GJsr,   dict[Any, Any]c                    d S r&   r5   r   s     r*   rw   z _CustomEncoder._cleaned_iterable   s    MPSr,   c                    dddfd	dfdt          |t          t          f          r |          S t          |t                    r |          S t	          d          )a  Check for circular reference at each iterable that will go through the JSONEncoder, as well as key of the wrong format.

        If a key with a bad format is found (i.e not a int, string, or float), it gets replaced by its hash using the same process implemented here.
        If a circular reference is found within the iterable, it will be replaced by the value of ALREADY_PROCESSED_PLACEHOLDER.

        Parameters
        ----------
        iterable
            The iterable to check.
        keyr   r#   rP   c                    t          j        t          j        | t                                                              S )Nr)   )zlibcrc32jsondumpsrh   encoder   s    r*   _key_to_hashz6_CustomEncoder._cleaned_iterable.<locals>._key_to_hash   s-    :dj.AAAHHJJKKKr,   lstr   r   c                ,   d gt          |           z  }t          |           D ]o\  }}t                              |          }t	          |t
          t          f          r |          }n#t	          |t                    r |          }n|}|||<   p|S r&   )r\   	enumerater   rE   rO   rt   tupledict)r   processed_listr   el	new_value_iter_check_dict_iter_check_lists        r*   r   z:_CustomEncoder._cleaned_iterable.<locals>._iter_check_list  s    "Vc#hh.N"3 . .266r::b4-00 # 0 0 4 4IID)) # 0 0 4 4II "I$-q!!!!r,   dctr   c                   i }|                                  D ]\  }}t                              |          }|t          v r)t	          |t
          t          t          t          f          s| |          }n|}t	          |t                    r |          }n*t	          |t          t          f          r |          }n|}|||<   |S r&   )itemsr   rE   r   rO   rR   rP   rQ   r.   r   rt   r   )	r   processed_dictkvk_newr   r   r   r   s	         r*   r   z:_CustomEncoder._cleaned_iterable.<locals>._iter_check_dict  s    N		 2 2155a88***!!c3t%<== !-(LOOEEEa&& " 0 0 3 3IID%=11 " 0 0 3 3II !I(1u%%!!r,   z3'iterable' is neither an iterable nor a dictionary.N)r   r   r#   rP   )r   r   r#   r   )r   r   r#   r   )rO   rt   r   r   rV   )r7   r   r   r   r   s     @@@r*   rw   z _CustomEncoder._cleaned_iterable   s    	L 	L 	L 	L	" 	" 	" 	" 	" 	" 	"	" 	" 	" 	" 	" 	" 	" 	"( hu.. 	S##H---$'' 	S##H---QRRRr,   rR   c                &   t                               |           t          |t          t          t
          f          r4t                                          |                     |                    S t                                          |          S )a  Overriding of :meth:`JSONEncoder.encode`, to make our own process.

        Parameters
        ----------
        obj
            The object to encode in JSON.

        Returns
        -------
        :class:`str`
           The object encoder with the standard json process.
        )	r   rL   rO   r   rt   r   superr   rw   )r7   r6   	__class__s     r*   r   z_CustomEncoder.encode*  sl     	##C(((cD$.// 	?77>>$"8"8"="=>>>ww~~c"""r,   )r6   r   r#   r   )r   r   r#   r   )r   r   r#   r   r6   r   r#   rR   )ra   rb   rc   r   r   rw   r   __classcell__)r   s   @r*   rh   rh      s        : : : :x JJJ XJPPP XP5S 5S 5Sn# # # # # # # # # #r,   rh   r6   r   r#   rR   c                8    t          j        | t                    S )zRecursively serialize `object` to JSON using the :class:`CustomEncoder` class.

    Parameters
    ----------
    obj
        The dict to flatten

    Returns
    -------
    :class:`str`
        The flattened object
    r)   )r   r   rh   )r6   s    r*   r   r   =  s     :c~....r,   scene_objectr   camera_objectCamera | OpenGLCameraanimations_listIterable[Animation]current_mobjects_listIterable[Mobject]c                   t          j        d           t                      }t                              |            t          |          }d t          |t                    D             }d |D             }d |||fD             \  }}	}
| d|	 d|
 }t                      }t          j        ddt          ||z
            d	d
         i           t                                           t          j        dd|i           |S )a4  Take the list of animations and a list of mobjects and output their hashes. This is meant to be used for `scene.play` function.

    Parameters
    -----------
    scene_object
        The scene object.

    camera_object
        The camera object used in the scene.

    animations_list
        The list of animations.

    current_mobjects_list
        The list of mobjects.

    Returns
    -------
    :class:`str`
        A string concatenation of the respective hashes of `camera_object`, `animations_list` and `current_mobjects_list`, separated by `_`.
    zHashing ...c                ,    g | ]}t          |          S r5   r   .0rC   s     r*   
<listcomp>z+get_hash_from_play_call.<locals>.<listcomp>l  s    RRRAHQKKRRRr,   r   c                ,    g | ]}t          |          S r5   r   r   s     r*   r   z+get_hash_from_play_call.<locals>.<listcomp>m  s    !M!M!M!(1++!M!M!Mr,   c              3  |   K   | ]7}t          j        t          |                                                    V  8d S r&   )r   r   r|   r   )r   json_vals     r*   	<genexpr>z*get_hash_from_play_call.<locals>.<genexpr>n  sR       ; ; 	
4>>((**++; ; ; ; ; ;r,   _zHashing done in %(time)s s.timeN   zHash generated :  %(h)sh)	r   debugr   r   rL   r   sortedrR   r+   )r   r   r   r   t_startcamera_jsonanimations_list_jsoncurrent_mobjects_list_jsonhash_camerahash_animationshash_current_mobjectshash_completet_ends                r*   r   r   M  s'   6 LnnG---=))KRRS1Q1Q1QRRR!M!M7L!M!M!M; ;$&:<VW; ; ;7K"7 #NN_NN7LNNMNNE
L.UW_9M9Mbqb9Q0RSSS%%'''
L*S-,@AAAr,   r   )
r   r   r   r   r   r   r   r   r#   rR   )-rd   
__future__r   rr   rp   r   r   collections.abcr   r   r   r   r   r   typesr	   r
   r   r   typingr   r   r   numpyrx   manim._configr   r   manim.animation.animationr   manim.camera.camerar   manim.mobject.mobjectr   manim.renderer.opengl_rendererr   manim.scene.scener   __all__r   r   JSONEncoderrh   r   r   r5   r,   r*   <module>r      s   " " " " " " " "     B B B B B B B B B B B B       H H H H H H H H H H H H / / / / / / / / / /     ( ( ( ( ( ( ( ( (333333******------;;;;;;''''''
G
G
G   H! H! H! H! H! H! H! H!VJ# J# J# J# J#T% J# J# J#Z/ / / / + + + + + +r,   