
    	]j;%                        d Z ddlZddlZddlZddlZddlmZmZ 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 dd	lmZmZ dd
lmZ ddlmZ ddlmZmZmZmZmZ ddlm Z  ddl!m"Z"m#Z# ddl$m%Z%  ejL                  e'      Z( G d dejR                        Z* G d de*e      Z+ G d dee+      Z, G d de*e      Z- G d de      Z. G d de      Z/ eee%      d        Z0 eee%      d        Z1y)zThis file and its contents are licensed under the Apache License 2.0. Please see the included NOTICE for copyright information and LICENSE for a copy of the license.
    N)datetimetimezone)Path)quote)settings)ValidationError)models)	post_save
pre_delete)receiver)gettext_lazy)ExportStorageExportStorageLinkImportStorageImportStorageLinkProjectStorageMixin)normalize_storage_path)StorageObjectload_tasks_json)
Annotationc                        e Zd Z ej                   ed      ddd      Z ej                   ed      ddd      Z ej                   ed      dd	
      Z	 fdZ
 fdZefdefdZed        Zd Z xZS )LocalFilesMixinpathTz
Local path)nullblank	help_textregex_filterzRegex for filtering objectsuse_blob_urlsFz,Interpret objects as BLOBs and generate URLs)defaultr   c                 p    t         |           | j                  t        | j                        | _        y y N)supercleanr   r   )self	__class__s    T/root/env/lib/python3.12/site-packages/label_studio/io_storages/localfiles/models.pyr#   zLocalFilesMixin.clean.   s+    99 .tyy9DI !    c                 p    | j                   t        | j                         | _         t        |   |i | y r!   )r   r   r"   save)r$   argskwargsr%   s      r&   r)   zLocalFilesMixin.save3   s.    99 .tyy9DId%f%r'   returnc                 D    t        | j                        }|s |d      |S )a  Return a sanitized storage path or raise a caller-provided exception type.

        All downstream filesystem operations eventually need an absolute path without
        trailing slashes or mixed separators. Centralizing that logic here keeps the
        normalization rules consistent and allows callers to decide what exception
        class (ValidationError vs ValueError) should be raised when the path is
        missing or invalid.
        z(Path must be set for Local Files storage)r   r   )r$   exception_cls
normalizeds      r&   _get_storage_path_or_raisez*LocalFilesMixin._get_storage_path_or_raise8   s'     ,DII6
 JKKr'   c                  .    t         j                  dk(  r	 yy)N	Communityz Community tip: create a "mydata" or "label-studio-data" directory next to the Label Studio command to auto-enable LOCAL_FILES_DOCUMENT_ROOT when the environment variables are unset. )r   VERSION_EDITION r'   r&   community_auto_hintz#LocalFilesMixin.community_auto_hintF   s     ##{2m r'   c           	      D   | j                  t              }|| _        t        |      }t        t        j
                        }t        t        j
                        dz  }|j                         st        d| j                   d      ||k(  r-t        d| j                   dt        j
                   d| d      ||j                  vr-t        d| j                   dt        j
                   d| d      t        j                  d	u rt        d
| j                                y )Ndataset1zAbsolute local path "z" does not existz3" cannot be the same as LOCAL_FILES_DOCUMENT_ROOT="z@" by security reasons. Please add a subdirectory. For example: "z".z7" must be a subdirectory of LOCAL_FILES_DOCUMENT_ROOT="z%" by security reasons. For example: "Fa@  Serving local files from the host filesystem can be a security risk, so LOCAL_FILES_SERVING_ENABLED is disabled by default. To enable Local Files storage, set the LOCAL_FILES_SERVING_ENABLED environment variable to "true" and restart Label Studio. See https://labelstud.io/guide/storage.html#Local-storage for details.

)
r0   r   r   r   r   LOCAL_FILES_DOCUMENT_ROOTexistsparentsLOCAL_FILES_SERVING_ENABLEDr6   )r$   normalized_pathr   document_rootexample_paths        r&   validate_connectionz#LocalFilesMixin.validate_connectionO   s4   99/J#	O$X??@H>>?*L{{}!$9$))DT"UVVD !'		{ 3..6.P.P-Q R!!-b2 
 ,!'		{ 3..6.P.P-Q R!!-b2 
 //58! ++-.0  9r'   )__name__
__module____qualname__r	   	TextField_r   r   BooleanFieldr   r#   r)   
ValueErrorstrr0   staticmethodr6   r@   __classcell__)r%   s   @r&   r   r       s    6AfIDUD#6##	./	L (F''	/@M:
&
 8B c   r'   r   c            	           e Zd ZdZd Z ej                   ed      ddd ed            Zd Z	d	 Z
d
 Zdee   fdZd Z G d d      Zy)LocalFilesImportStorageBasehttpsc                      y)NFr5   )r$   urls     r&   can_resolve_urlz+LocalFilesImportStorageBase.can_resolve_urls   s    r'   zrecursive scanFTz1Perform recursive scan over the directory content)r   
db_defaultr   r   c              #     K   t        | j                               }| j                  r(t        j                  t        | j                              nd }| j                  r|j                  d      n|j                  d      }t        |t        j                  j                        D ]O  }|j                         s|j                  }|r*|j                  |      st         j#                  |dz          L| Q y w)N*)keyz is skipped by regex filter)r   r0   r   recompilerH   recursive_scanrglobglobsortedosr   basenameis_filenamematchloggerdebug)r$   r   regexiteratorfilerT   s         r&   iter_objectsz(LocalFilesImportStorageBase.iter_objects~   s     D33566:6G6G

3t0012T '+&9&94::c?tyy~8)9)9: 	D||~iiS!1LL'D!DE
	s   B6C89?C8c              #   P   K   | j                         D ]  }t        |        y wr!   )re   rH   )r$   objs     r&   	iter_keysz%LocalFilesImportStorageBase.iter_keys   s'     $$& 	Cc(N	s   $&c                     |j                         }t        |      t        j                  |j                  t
        j                        |j                  dS )N)tz)rT   last_modifiedsize)statrH   r   fromtimestampst_mtimer   utcst_size)r$   rg   rm   s      r&   get_unified_metadataz0LocalFilesImportStorageBase.get_unified_metadata   s=    xxzs8%33DMMhllSLL
 	
r'   r,   c           	         t        |      }| j                  rxt        t        j                        }t	        |j                  |            }t        j                  t        j                   dt        t	        |             i}t        ||      gS 	 t        |d      5 }|j                         }t        ||      cd d d        S # 1 sw Y   y xY w# t        $ r}t        d| dt	        |             d }~ww xY w)Nz/data/local-files/?d=)rT   	task_datarbzFailed to read file z: )r   r   r   r9   rH   relative_toDATA_UNDEFINED_NAMEHOSTNAMEr   r   openreadr   OSErrorrG   )	r$   rT   r   r>   relative_pathtaskfblobes	            r&   get_dataz$LocalFilesImportStorageBase.get_data   s    Cy !!C!CDM 0 0 ?@M,,1B1B0CCXY^_bcp_qYrXs.tD "cT:;;	FdD! 2Qvvx&tS12 2 2  	F3D6CF8DEE	Fs6   C C9	C CC C 	C7C22C7c                 ,    | j                  t              S r!   )_scan_and_create_linksLocalFilesImportStorageLink)r$   s    r&   scan_and_create_linksz1LocalFilesImportStorageBase.scan_and_create_links   s    **+FGGr'   c                       e Zd ZdZy) LocalFilesImportStorageBase.MetaTNrA   rB   rC   abstractr5   r'   r&   Metar      s    r'   r   N)rA   rB   rC   
url_schemerP   r	   rF   rE   rW   re   rh   rr   listr   r   r   r   r5   r'   r&   rL   rL   p   sm    J )V((	
GHN
FtM2 F&H r'   rL   c                        e Zd Z G d d      Zy)LocalFilesImportStoragec                       e Zd ZdZy)LocalFilesImportStorage.MetaFNr   r5   r'   r&   r   r      s    r'   r   N)rA   rB   rC   r   r5   r'   r&   r   r      s     r'   r   c                       e Zd Zd Zd Zy)LocalFilesExportStoragec                    t         j                  d| j                  j                   d|  d|        | j	                  |      }t
        j                  |      }| j                         }t        j                  j                  ||       }t        |d      5 }t        j                  ||d       d d d        t
        j                  ||        y # 1 sw Y    xY w)NzCreating new object on 	 Storage  for annotation w)mode   )indent)r`   ra   r%   rA   _get_serialized_dataLocalFilesExportStorageLinkget_keyr0   r[   r   joinry   jsondumpcreate)r$   
annotationser_annotationrT   storage_pathr~   s         r&   save_annotationz'LocalFilesExportStorage.save_annotation   s    .t~~/F/F.GyQUPVVfgqfrst22:> *11*=668ggll<C52 #C  	3AIIna2	3 	$**:t<		3 	3s   CCc                    t         j                  d| j                  j                   d|  d|        t        j                  |      }| j                         }t        j                  j                  ||       }	 t        j                  |       t        j                  j                  | |      j                          y # t        $ r t         j                  d| d|        Y Vw xY w)NzDeleting object on r   r   zExport file z# is already missing for annotation )storager   )r`   ra   r%   rA   r   r   r0   r[   r   r   removeFileNotFoundErrorwarningobjectsfilterdelete)r$   r   rT   r   	file_paths        r&   delete_annotationz)LocalFilesExportStorage.delete_annotation   s    *4>>+B+B*C9TFRbcmbnop)11*=668GGLL#8		fIIi  	$++224J2W^^` ! 	fNN\)4WXbWcde	fs   :B? ?$C&%C&N)rA   rB   rC   r   r   r5   r'   r&   r   r      s    = ar'   r   c                   J    e Zd Z ej                  eej                  d      Zy)r   links	on_deleterelated_nameN)rA   rB   rC   r	   
ForeignKeyr   CASCADEr   r5   r'   r&   r   r          f 76>>`ghGr'   r   c                   J    e Zd Z ej                  eej                  d      Zy)r   r   r   N)rA   rB   rC   r	   r   r   r   r   r5   r'   r&   r   r      r   r'   r   )senderc                     |j                   }t        |d      rL|j                  j                         D ].  }t        j                  d| d|        |j                  |       0 y y )N$io_storages_localfilesexportstorageszExport z to Local Storage )projecthasattrr   allr`   ra   r   )r   instancer+   r   r   s        r&    export_annotation_to_local_filesr      sd    Gw>?CCGGI 	.GLL78*,>wiHI##H-	. @r'   c                     t         j                  j                  |      }|D ]G  }|j                  }|j                  st
        j                  d| d|        |j                  |       I y )N)r   zDelete z from Local Storage )r   r   r   r   can_delete_objectsr`   ra   r   )r   r   r+   r   linkr   s         r&   "delete_annotation_from_local_filesr      sd    '//66(6KE 0,,%%LL78*,@	JK%%h/	0r'   )2__doc__r   loggingr[   rU   r   r   pathlibr   urllib.parser   django.confr   django.core.exceptionsr   	django.dbr	   django.db.models.signalsr
   r   django.dispatchr   django.utils.translationr   rE   io_storages.base_modelsr   r   r   r   r    io_storages.localfiles.functionsr   io_storages.utilsr   r   tasks.modelsr   	getLoggerrA   r`   Modelr   rL   r   r   r   r   r   r   r5   r'   r&   <module>r      s      	 	 '     2  : $ 6  D < #			8	$Mfll M`?/= ?D13N 
ao} a>i"3 ii"3 i 
)J'. (. 
*Z(0 )0r'   