
    Dj$                       d Z ddlmZ ddlZddlmZ ddlmZ ddlm	Z	 ddl
mZmZmZ  ed	           G d
 d                      Ze G d de                      Z G d d          Z G d d          ZddddZdS )z4Persistent sync state for the modern Photos service.    )annotationsN)	dataclass)Path)TracebackType)IteratorProtocolruntime_checkableT)slotsc                  \    e Zd ZU dZded<   ded<   ded<   dZded<   dZd	ed
<   dZd	ed<   dS )SyncedPhotoResourcez=One locally materialized resource tracked by the sync engine.strasset_idresource_keyrelative_pathNz
int | Nonesize
str | Nonechecksumdownloaded_at)__name__
__module____qualname____doc____annotations__r   r   r        b/home/thesage/.hermes/venv/lib/python3.11/site-packages/pyicloud/services/photos_cloudkit/state.pyr   r      sl         GGMMMDH $M$$$$$$r   r   c                  Z    e Zd ZdZddZd dZd!dZd"dZd#dZd$dZ	d%dZ
d&dZd'dZdS )(PhotoSyncStatez>Backend interface for persisted or ephemeral photo sync state.return'PhotoSyncState'c                    dS )z4Open the backend and return the active state object.Nr   selfs    r   	__enter__zPhotoSyncState.__enter__         r   exc_typetype[BaseException] | NoneexcBaseException | NonetbTracebackType | NoneNonec                    dS )zClose the backend if needed.Nr   r#   r&   r(   r*   s       r   __exit__zPhotoSyncState.__exit__   r%   r   r   c                    dS )7Return the last successful sync cursor for this target.Nr   r"   s    r   get_sync_cursorzPhotoSyncState.get_sync_cursor'   r%   r   valuec                    dS )8Persist the last successful sync cursor for this target.Nr   r#   r3   s     r   set_sync_cursorzPhotoSyncState.set_sync_cursor*   r%   r   r   r   r   SyncedPhotoResource | Nonec                    dS )zLook up one tracked resource.Nr   r#   r   r   s      r   get_resourcezPhotoSyncState.get_resource-   r%   r   resourcer   c                    dS )z'Insert or replace one tracked resource.Nr   r#   r<   s     r   upsert_resourcezPhotoSyncState.upsert_resource2   r%   r   c                    dS )z.Delete one tracked resource from the manifest.Nr   r:   s      r   delete_resourcezPhotoSyncState.delete_resource5   r%   r   Iterator[SyncedPhotoResource]c                    dS )zIterate all tracked resources.Nr   r"   s    r   iter_resourceszPhotoSyncState.iter_resources8   r%   r   intc                    dS )z'Return the number of tracked resources.Nr   r"   s    r   resource_countzPhotoSyncState.resource_count;   r%   r   N)r   r    )r&   r'   r(   r)   r*   r+   r   r,   r   r   r3   r   r   r,   r   r   r   r   r   r8   r<   r   r   r,   r   r   r   r   r   r,   r   rB   r   rE   )r   r   r   r   r$   r/   r2   r7   r;   r?   rA   rD   rG   r   r   r   r   r      s        HHC C C C+ + + +F F F FG G G G, , , ,
6 6 6 6= = = =- - - -6 6 6 6 6 6r   r   c                      e Zd ZdZd dZd!dZd"d	Zd"d
Zd"dZe	d#d            Z
d$dZd%dZd&dZd'dZd(dZd)dZd*dZdS )+SQLitePhotoSyncStatezDSQLite-backed manifest and sync-token store for a photo sync target.db_pathr   r   r,   c                "    || _         d | _        d S N)rQ   _conn)r#   rQ   s     r   __init__zSQLitePhotoSyncState.__init__B   s    04


r   'SQLitePhotoSyncState'c                .    |                                   | S rS   )openr"   s    r   r$   zSQLitePhotoSyncState.__enter__F   s    		r   c                .    |                                   d S rS   )closer.   s       r   r/   zSQLitePhotoSyncState.__exit__J   s    

r   c                   | j         dS | j        j                            dd           t	          j        | j                  | _         t          j        | j         _        | j                             d           | j                             d           | j         	                    d           | j         
                                 dS )z3Open the SQLite database and initialize the schema.NT)parentsexist_okzPRAGMA journal_mode=WALzPRAGMA foreign_keys=ONa  
            CREATE TABLE IF NOT EXISTS sync_meta (
                key TEXT PRIMARY KEY,
                value TEXT
            );

            CREATE TABLE IF NOT EXISTS synced_resources (
                asset_id TEXT NOT NULL,
                resource_key TEXT NOT NULL,
                relative_path TEXT NOT NULL,
                size INTEGER,
                checksum TEXT,
                downloaded_at TEXT,
                PRIMARY KEY (asset_id, resource_key)
            );
            )rT   rQ   parentmkdirsqlite3connectRowrow_factoryexecuteexecutescriptcommitr"   s    r   rX   zSQLitePhotoSyncState.openM   s     :!F!!$!>>>_T\22
!(

4555
3444
  	
 	
 	
$ 	
r   c                X    | j         dS | j                                          d| _         dS )z*Close the SQLite connection if it is open.N)rT   rZ   r"   s    r   rZ   zSQLitePhotoSyncState.closek   s0     :F



r   sqlite3.Connectionc                X    | j         |                                  | j         J | j         S )z$Return the active SQLite connection.)rT   rX   r"   s    r   connzSQLitePhotoSyncState.conns   s/     :IIKKKz%%%zr   r   c                t    | j                             dd                                          }|dn|d         S )r1   z)SELECT value FROM sync_meta WHERE key = ?sync_cursorNr3   )rj   rd   fetchoner#   rows     r   r2   z$SQLitePhotoSyncState.get_sync_cursor|   sC     i7
 
 (** 	 {ttG4r   r3   c                    || j                             dd           n| j                             dd|f           | j                                          dS )r5   Nz#DELETE FROM sync_meta WHERE key = ?rl   z
                INSERT INTO sync_meta(key, value)
                VALUES(?, ?)
                ON CONFLICT(key) DO UPDATE SET value = excluded.value
                rm   rj   rd   rf   r6   s     r   r7   z$SQLitePhotoSyncState.set_sync_cursor   sk     =ICEUVVVVI
 &   		r   r   r   r   r8   c           	         | j                             d||f                                          }|dS t          |d         |d         |d         |d         |d         |d         	          S )
z:Look up a previously synced resource by asset/version key.z
            SELECT asset_id, resource_key, relative_path, size, checksum, downloaded_at
            FROM synced_resources
            WHERE asset_id = ? AND resource_key = ?
            Nr   r   r   r   r   r   r   r   r   r   r   r   )rj   rd   rn   r   )r#   r   r   rp   s       r   r;   z!SQLitePhotoSyncState.get_resource   s    
 i
 |$
 
 (** 	 ;4"_^,o.V_o.
 
 
 	
r   r<   r   c           	         | j                             d|j        |j        |j        |j        |j        |j        f           | j                                          dS )z=Persist the latest known local state for one synced resource.a  
            INSERT INTO synced_resources(
                asset_id, resource_key, relative_path, size, checksum, downloaded_at
            )
            VALUES(?, ?, ?, ?, ?, ?)
            ON CONFLICT(asset_id, resource_key) DO UPDATE SET
                relative_path = excluded.relative_path,
                size = excluded.size,
                checksum = excluded.checksum,
                downloaded_at = excluded.downloaded_at
            N)	rj   rd   r   r   r   r   r   r   rf   r>   s     r   r?   z$SQLitePhotoSyncState.upsert_resource   si     		
 !%&!&	
 	
 	
* 		r   c                r    | j                             d||f           | j                                          dS )z-Forget one synced resource from the manifest.zj
            DELETE FROM synced_resources
            WHERE asset_id = ? AND resource_key = ?
            Nrr   r:   s      r   rA   z$SQLitePhotoSyncState.delete_resource   sI     		 |$	
 	
 	
 		r   rB   c           
   #     K   | j                             d          }|D ]=}t          |d         |d         |d         |d         |d         |d                   V  >d	S )
z3Iterate all tracked resources for this sync target.z
            SELECT asset_id, resource_key, relative_path, size, checksum, downloaded_at
            FROM synced_resources
            ORDER BY relative_path
            r   r   r   r   r   r   rt   N)rj   rd   r   )r#   rowsrp   s      r   rD   z#SQLitePhotoSyncState.iter_resources   s       y  
 
  	 	C%Z 0!/2[Z!/2      	 	r   rE   c                    | j                             d                                          }|dnt          |d                   S )z7Return the number of tracked resources in the manifest.z.SELECT COUNT(*) AS count FROM synced_resourcesNr   count)rj   rd   rn   rE   ro   s     r   rG   z#SQLitePhotoSyncState.resource_count   sF     i<
 

(** 	 KqqSW%6%66r   N)rQ   r   r   r,   )r   rV   r   r,   )r   rh   rH   rI   rJ   rK   rL   rM   rN   )r   r   r   r   rU   r$   r/   rX   rZ   propertyrj   r2   r7   r;   r?   rA   rD   rG   r   r   r   rP   rP   ?   s*       NN5 5 5 5         <       X5 5 5 5    
 
 
 
0   4
 
 
 
   (7 7 7 7 7 7r   rP   c                  b    e Zd ZdZddZddZddZdd	ZddZddZ	ddZ
d dZd!dZd"dZdS )#MemoryPhotoSyncStatez3Ephemeral manifest used for preview-only sync runs.r   r,   c                "    d | _         i | _        d S rS   )_cursor
_resourcesr"   s    r   rU   zMemoryPhotoSyncState.__init__   s    #'FHr   'MemoryPhotoSyncState'c                    | S rS   r   r"   s    r   r$   zMemoryPhotoSyncState.__enter__   s    r   c                    d S rS   r   r.   s       r   r/   zMemoryPhotoSyncState.__exit__   s    tr   r   c                    | j         S )z)Return the stored preview cursor, if any.r   r"   s    r   r2   z$MemoryPhotoSyncState.get_sync_cursor   s     |r   r3   c                    || _         dS )z!Store a preview cursor in memory.Nr   r6   s     r   r7   z$MemoryPhotoSyncState.set_sync_cursor  s     r   r   r   r   r8   c                :    | j                             ||f          S )zLook up a preview resource row.)r   getr:   s      r   r;   z!MemoryPhotoSyncState.get_resource  s    
 ""Hl#;<<<r   r<   r   c                2    || j         |j        |j        f<   dS )zStore a preview resource row.N)r   r   r   r>   s     r   r?   z$MemoryPhotoSyncState.upsert_resource  s#     GO*H,ABCCCr   c                @    | j                             ||fd           dS )zDelete a preview resource row.N)r   popr:   s      r   rA   z$MemoryPhotoSyncState.delete_resource  s'     	X|4d;;;;;r   rB   c              #  H   K   | j                                         E d{V  dS )zIterate preview resource rows.N)r   valuesr"   s    r   rD   z#MemoryPhotoSyncState.iter_resources  s4       ?))+++++++++++r   rE   c                *    t          | j                  S )z+Return the number of preview manifest rows.)lenr   r"   s    r   rG   z#MemoryPhotoSyncState.resource_count  s     4?###r   Nr{   )r   r   rH   rI   rJ   rK   rL   rM   rN   )r   r   r   r   rU   r$   r/   r2   r7   r;   r?   rA   rD   rG   r   r   r   r~   r~      s        ==I I I I         
   
= = = =O O O O
< < < <
, , , ,
$ $ $ $ $ $r   r~   F)	ephemeralrQ   r   r   boolr   c               @    |rt                      S t          |           S )z>Return the appropriate sync-state backend for one sync target.)r~   rP   )rQ   r   s     r   create_photo_sync_stater   #  s&      &#%%%(((r   )rQ   r   r   r   r   r   )r   
__future__r   r`   dataclassesr   pathlibr   typesr   typingr   r   r	   r   r   rP   r~   r   r   r   r   <module>r      s{   : : " " " " " "  ! ! ! ! ! !             8 8 8 8 8 8 8 8 8 8 % % % % % % % % #6 #6 #6 #6 #6X #6 #6 #6Ln7 n7 n7 n7 n7 n7 n7 n7b0$ 0$ 0$ 0$ 0$ 0$ 0$ 0$l 	) 	) 	) 	) 	) 	) 	) 	)r   