
    /_iE;                        U d Z ddlm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 ddlmZ ddlmZ ddlmZmZmZ er
ddlZddlmZ  ee      Zd	ed
<    G d de      ZddZ G d d      Z G d d      Zy)z@Provides global MediaFileManager object as `media_file_manager`.    )annotationsN)TYPE_CHECKINGBinaryIOFinalTextIO	TypedDictcast)
get_logger)$convert_data_to_bytes_and_infer_mime)MediaFileKindMediaFileStorageMediaFileStorageError)Callabler   _LOGGERc                  :    e Zd ZU dZded<   ded<   ded<   ded<   y	)
DeferredCallableEntryz/Typed metadata for deferred download callables.<Callable[[], bytes | str | BinaryIO | TextIO | io.RawIOBase]callable
str | NonemimetypefilenamestrcoordinatesN)__name__
__module____qualname____doc____annotations__     c/var/www/html/land_sniper/venv/lib/python3.12/site-packages/streamlit/runtime/media_file_manager.pyr   r   '   s    9JJr    r   c                 :    ddl m}   |        }|y|j                  S )z'Get the active AppSession's session_id.r   )get_script_run_ctxdontcare)7streamlit.runtime.scriptrunner_utils.script_run_contextr#   
session_id)r#   ctxs     r!   _get_session_idr(   0   s%     
C
{ >>r    c                  \    e Zd ZdZej
                  fddZedd       Zed	d       Z	d
dZ
y)MediaFileMetadatazBMetadata that the MediaFileManager needs for each file it manages.c                     || _         d| _        y NF)_kind_is_marked_for_delete)selfkinds     r!   __init__zMediaFileMetadata.__init__B   s    
%*"r    c                    | j                   S N)r-   r/   s    r!   r0   zMediaFileMetadata.kindF   s    zzr    c                    | j                   S r3   r.   r4   s    r!   is_marked_for_deletez&MediaFileMetadata.is_marked_for_deleteJ   s    )))r    c                    d| _         y )NTr6   r4   s    r!   mark_for_deletez!MediaFileMetadata.mark_for_deleteN   s
    %)"r    N)r0   r   returnNone)r:   r   )r:   boolr:   r;   )r   r   r   r   r   MEDIAr1   propertyr0   r7   r9   r   r    r!   r*   r*   ?   s@    L-:-@-@ +   * **r    r*   c                      e Zd ZdZddZddZddZddZddZdddZ		 	 d	 	 	 	 	 	 	 	 	 	 	 dd	Z
	 d	 	 	 	 	 	 	 	 	 dd
ZddZy)MediaFileManagera  In-memory file manager for MediaFile objects.

    This keeps track of:
    - Which files exist, and what their IDs are. This is important so we can
      serve files by ID -- that's the whole point of this class!
    - Which files are being used by which AppSession (by ID). This is
      important so we can remove files from memory when no more sessions need
      them.
    - The exact location in the app where each file is being used (i.e. the
      file's "coordinates"). This is is important so we can mark a file as "not
      being used by a certain session" if it gets replaced by another file at
      the same coordinates. For example, when doing an animation where the same
      image is constantly replace with new frames. (This doesn't solve the case
      where the file's coordinates keep changing for some reason, though! e.g.
      if new elements keep being prepended to the app. Unlikely to happen, but
      we should address it at some point.)
    c                    || _         i | _        t        j                  t              | _        i | _        t        j                         | _	        y r3   )
_storage_file_metadatacollectionsdefaultdictdict_files_by_session_and_coord_deferred_callables	threadingLock_lock)r/   storages     r!   r1   zMediaFileManager.__init__e   sG     =? ##D) 	( FH 
 ^^%
r    c                    t        | j                  j                               }| j                  j	                         D ]!  }|j                  |j	                                # |S )zCompute the set of files that are stored in the manager, but are
        not referenced by any active session. These are files that can be
        safely deleted.

        Thread safety: callers must hold `self._lock`.
        )setrD   keysrH   valuesdifference_update)r/   file_idssession_file_ids_by_coords      r!   _get_inactive_file_idsz'MediaFileManager._get_inactive_file_idsy   s_     t**//12 *.)I)I)P)P)R 	K%&&'@'G'G'IJ	K r    c                   t         j                  d       | j                  5  | j                         D ]  }| j                  |   }|j
                  t        j                  k(  r| j                  |       A|j
                  t        j                  k(  s_|j                  r| j                  |       }|j                           | j                          ddd       y# 1 sw Y   yxY w)zuRemove all files that are no longer referenced by any active session.

        Safe to call from any thread.
        zRemoving orphaned files...N)r   debugrL   rU   rD   r0   r   r>   _delete_fileDOWNLOADABLEr7   r9   #_remove_orphaned_deferred_callables)r/   file_idfiles      r!   remove_orphaned_filesz&MediaFileManager.remove_orphaned_files   s    
 	23ZZ 	7668 /**7399 3 33%%g.YY-"<"<<00))'2,,./ 446	7 	7 	7s   A/CA CC$c                d   t         j                  d       t        t                  }| j                  j                         D ]!  }|j                  |j                                # | j                  D cg c]  }||vr|
 }}|D ]%  }t         j                  d|       | j                  |= ' yc c}w )zRemove deferred callables that are not referenced by any active session.

        Thread safety: callers must hold `self._lock`.
        z'Removing orphaned deferred callables...zRemoving deferred callable: %sN)r   rW   rO   r   rH   rQ   updaterI   )r/   active_file_idsrT   r[   deferred_ids_to_removes        r!   rZ   z4MediaFileManager._remove_orphaned_deferred_callables   s    
 	?@ c(*)-)I)I)P)P)R 	G%""#<#C#C#EF	G  33"
o- "
 "

 . 	2GMM:GD((1	2"
s   3B-c                    t         j                  d|       | j                  j                  |       | j                  |= y)zDelete the given file from storage, and remove its metadata from
        self._files_by_id.

        Thread safety: callers must hold `self._lock`.
        zDeleting File: %sN)r   rW   rC   delete_filerD   )r/   r[   s     r!   rX   zMediaFileManager._delete_file   s3     	)73!!'*(r    Nc                   |
t               }t        j                  d|       | j                  5  || j                  v r| j                  |= ddd       t        j                  d| j                  j                                t        j                  dt        | j                        t        | j                               y# 1 sw Y   uxY w)a#  Remove the given session's file references.

        (This does not remove any files from the manager - you must call
        `remove_orphaned_files` for that.)

        Should be called whenever ScriptRunner completes and when a session ends.

        Safe to call from any thread.
        Nz*Disconnecting files for session with ID %szSessions still active: %rz"Files: %s; Sessions with files: %s)r(   r   rW   rL   rH   rP   lenrD   )r/   r&   s     r!   clear_session_refsz#MediaFileManager.clear_session_refs   s     (*JBJOZZ 	AT===44Z@	A 	')I)I)N)N)P	
 	0##$001	
	A 	As   B??Cc                j   t               }| j                  5  |rt        j                  nt        j                  }| j
                  j                  ||||      }t        |      }	|	| j                  |<   || j                  |   |<   | j
                  j                  |      cddd       S # 1 sw Y   yxY w)a  Add a new MediaFile with the given parameters and return its URL.

        If an identical file already exists, return the existing URL
        and registers the current session as a user.

        Safe to call from any thread.

        Parameters
        ----------
        path_or_data : bytes or str
            If bytes: the media file's raw data. If str: the name of a file
            to load from disk.
        mimetype : str
            The mime type for the file. E.g. "audio/mpeg".
            This string will be used in the "Content-Type" header when the file
            is served over HTTP.
        coordinates : str
            Unique string identifying an element's location.
            Prevents memory leak of "forgotten" file IDs when element media
            is being replaced-in-place (e.g. an st.image stream).
            coordinates should be of the form: "1.(3.-14).5"
        file_name : str or None
            Optional file_name. Used to set the filename in the response header.
        is_for_static_download: bool
            Indicate that data stored for downloading as a file,
            not as a media for rendering at page. [default: False]

        Returns
        -------
        str
            The url that the frontend can use to fetch the media.

        Raises
        ------
        If a filename is passed, any Exception raised when trying to read the
        file will be re-raised.
        r0   N)r(   rL   r   rY   r>   rC   load_and_get_idr*   rD   rH   get_url)
r/   path_or_datar   r   	file_nameis_for_static_downloadr&   r0   r[   metadatas
             r!   addzMediaFileManager.add   s    \ %&
ZZ 	2 * **"(( 
 mm33hiG )d3H+3D(HOD,,Z8E==((1	2 	2 	2s   BB))B2c           	         t               }| j                  5  t        j                         j                  }t        d||||d      | j                  |<   || j                  |   |<   |cddd       S # 1 sw Y   yxY w)a  Register a callable for deferred execution. Returns placeholder file_id.

        The callable will be executed later when execute_deferred() is called,
        typically when the user clicks a download button.

        Safe to call from any thread.

        Parameters
        ----------
        data_callable : Callable[[], bytes | str | BinaryIO | TextIO | io.RawIOBase]
            A callable that returns the file data when invoked.
        mimetype : str or None
            The mime type for the file. E.g. "text/csv".
            If None, the mimetype will be inferred from the data type when
            execute_deferred() is called.
        coordinates : str
            Unique string identifying an element's location.
        file_name : str or None
            Optional file_name. Used to set the filename in the response header.

        Returns
        -------
        str
            A placeholder file_id that can be used to execute the callable later.
        r   )r   r   r   r   N)r(   rL   uuiduuid4hexr	   rI   rH   )r/   data_callabler   r   rl   r&   r[   s          r!   add_deferredzMediaFileManager.add_deferred  s    @ %&
ZZ 	 jjl&&G 15' - ( )#.	1D$$W- IPD,,Z8E'	 	 	s   AA11A:c           	     x   | j                   5  || j                  vrt        d| d      | j                  |   }ddd       	  d          }t	        |t        dt        |                   \  }}|d   xs |}| j                   5  | j                  j                  ||t        j                  |d	         }t        t        j                  
      }	|	| j                  |<   | j                  j                  |      cddd       S # 1 sw Y   xY w# t        $ r}t        d|       |d}~ww xY w# 1 sw Y   yxY w)a  Execute a deferred callable and return the URL to the generated file.

        This method retrieves the callable registered with add_deferred(),
        executes it, stores the result, and returns a URL to access it.

        Safe to call from any thread.

        Parameters
        ----------
        file_id : str
            The placeholder file_id returned by add_deferred().

        Returns
        -------
        str
            The URL that can be used to download the generated file.

        Raises
        ------
        MediaFileStorageError
            If the file_id is not found or if the callable execution fails.
        zDeferred file z
 not foundNr   zCallable execution failed: z$Callable returned unsupported type: )unsupported_errorr   r   rh   )rL   rI   r   	Exceptionr   typerC   ri   r   rY   r*   rD   rj   )
r/   r[   deferreddataedata_as_bytesinferred_mime_type	mime_typeactual_file_idrn   s
             r!   execute_deferredz!MediaFileManager.execute_deferredV  sR   0 ZZ 	9d666+nWIZ,PQQ//8H		9	R'8J')D
 -Q36tDzlC-
)) "*-C1C	 ZZ 	9!]]::**$	N )m.H.HIH2:D/ ==((8'	9 	91	9 	9  	R'*EaS(IJPQQ	R	9 	9s0   -D
D A3D0D	D-D((D-0D9)rM   r   r:   r;   )r:   zset[str]r=   )r[   r   r:   r;   r3   )r&   r   r:   r;   r,   )rk   zbytes | strr   r   r   r   rl   r   rm   r<   r:   r   )
rt   r   r   r   r   r   rl   r   r:   r   )r[   r   r:   r   )r   r   r   r   r1   rU   r]   rZ   rX   rf   ro   ru   r   r   r    r!   rA   rA   R   s    $&( 7*2,)
L !%',>2!>2 >2 	>2
 >2 !%>2 
>2J !%5S5 5 	5
 5 
5nC9r    rA   )r:   r   )r   
__future__r   rE   rJ   rq   typingr   r   r   r   r   r	   streamlit.loggerr
   $streamlit.runtime.download_data_utilr   $streamlit.runtime.media_file_storager   r   r   iocollections.abcr   r   r   r   r   r(   r*   rA   r   r    r!   <module>r      sn    G "    J J ' U  (H% %I * *&G9 G9r    