a
    VŸ$c5  ã                   @   sŠ  d dl mZmZmZmZmZ d dlmZmZm	Z	m
Z
mZmZmZmZmZmZmZmZ d dlZd dl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 G dd„ deƒZeej_eƒ ej_ dd„ Z!i Z"d	d
„ Z#dd„ Z$dd„ Z%i Z&dd„ Z'dd„ Z(dd„ Z)e'de)ƒ e'de)ƒ e'de)ƒ e'de)ƒ dd„ Z*d a+dd„ Z,d)dd„Z-d Z.d!d"„ Z/e 0¡ Z1d#d$„ Z2G d%d&„ d&eƒZ3d*d'd(„Z4e3ej5_3e4ej5_4dS )+é    )ÚdivisionÚabsolute_importÚwith_statementÚprint_functionÚunicode_literals)ÚPY2Ú
basestringÚbchrÚbordÚchrÚopenÚpystrÚrangeÚroundÚstrÚtobytesÚunicodeN)ÚdumpÚdumpsÚloadsc                   @   s>   e Zd Zdd„ Zdd„ Zdd„ Zdd„ Zdd
d„Zdd„ ZdS )Ú
Persistentc                 C   s   |   ¡  d S ©N)Ú_update©Úself© r   úrenpy/persistent.pyÚ__init__*   s    zPersistent.__init__c                 C   s   | j  |¡ d S r   ©Ú__dict__Úupdate)r   Údatar   r   r   Ú__setstate__-   s    zPersistent.__setstate__c                 C   s   | j S r   )r   r   r   r   r   Ú__getstate__0   s    zPersistent.__getstate__c                 C   s$   |  d¡r | d¡r td| ƒ‚d S )NÚ__z%Persistent object has no attribute %r©Ú
startswithÚendswithÚAttributeError)r   Úattrr   r   r   Ú__getattr__4   s    zPersistent.__getattr__Fc                 C   sZ   t | jƒ}|D ]}|d dkr q| j|= q|rV| j ¡  | j ¡  | j ¡  | j ¡  dS )zƒ
        Resets the persistent data.

        `progress`
            If true, also resets progress data that Ren'Py keeps.
        r   Ú_N)Úlistr   Ú
_seen_everÚclearÚ_seen_imagesÚ_chosenÚ_seen_audio)r   ÚprogressÚkeysÚir   r   r   Ú_clear:   s    




zPersistent._clearc                 C   s†   | j du rtj ¡ | _ | js"i | _| js.i | _| js:i | _| jsFi | _dd„ | jD ƒ| _| jsft	ƒ | _| j
du r‚ddddddœ| _
dS )zf
        Updates the persistent data to be the latest version of
        the persistent data.
        Nc                 S   s   i | ]}t |ƒd “qS )T)r   )Ú.0r4   r   r   r   Ú
<dictcomp>h   ó    z&Persistent._update.<locals>.<dictcomp>r   )Ú_preferencesr-   r0   r1   Ú_seen_translates)r9   ÚrenpyÚpreferencesÚPreferencesr-   r/   r0   r1   r:   ÚsetÚ_changedr   r   r   r   r   P   s(    

ûzPersistent._updateN)F)	Ú__name__Ú
__module__Ú__qualname__r   r"   r#   r*   r5   r   r   r   r   r   r   (   s   
r   c                 C   s0   t  | ¡}| |ks,tjjr(td|  ƒ‚n| }|S )zÏ
    A "safe" version of deepcopy. If an object doesn't implement __eq__
    correctly, we replace it with its original.

    This tries to ensure we don't constantly find changes in the same
    field.
    z5To be persisted, %r must support equality comparison.)ÚcopyÚdeepcopyr;   ÚconfigÚ	developerÚ	Exception)ÚoÚrvr   r   r   Úsafe_deepcopy~   s    	
rJ   c                  C   s†   d} t   ¡ }tjj}t|ƒ}tt ¡ ƒt| ¡ ƒB }|D ]H}|dkrFq8t |d¡}| |d¡}||ks8||j	|< t
|ƒt|< d} q8| S )a  
    This finds changes in the persistent object. When it finds a change, it
    backs up that changed, and puts the current time for that field into
    persistent._changed.

    This returns True if there was at least one change, and False
    otherwise.
    Fr?   NT)Útimer;   ÚgameÚ
persistentÚvarsr>   Úbackupr3   Úgetr?   rJ   )rI   ÚnowrM   ÚpvarsÚfieldsÚfÚoldÚnewr   r   r   Úfind_changes˜   s    

rW   c                 C   s°   t j | ¡sdS zDt| dƒ}t | ¡ ¡}W d  ƒ n1 s@0    Y  t|ƒ}W nN ty¢   ddl	}z|j
j d¡ |j
j ¡  W n tyš   Y n0 Y dS 0 | ¡  |S )z•
    Loads persistence data from `filename`. Returns None if the data
    could not be loaded, or a Persistent object if it could be
    loaded.
    NÚrbr   zLoading persistent.)ÚosÚpathÚexistsr   ÚzlibÚ
decompressÚreadr   rG   Úrenpy.displayÚdisplayÚlogÚwriteÚ	exceptionr   )ÚfilenamerT   ÚsrM   r;   r   r   r   Úload½   s     ,rf   c                  C   sx   t j tjjd¡} t| ƒ}|du r<t j tjjd¡} t| ƒ}|du rJtƒ }t|ƒ}t|ƒ 	¡ D ]\}}t
|ƒt|< q^|S )z°
    Loads the persistent data from disk.

    This performs the initial load of persistent data from the local
    disk, so that we can configure the savelocation system.
    zpersistent.newNrM   )rY   rZ   Újoinr;   rE   Úsavedirrf   r   rN   ÚitemsrJ   rO   )rd   rM   ÚvÚkr   r   r   ÚinitÜ   s    rl   c                 C   s   |t | < dS )a!  
    :doc: persistent

    Registers a function that is used to merge values of a persistent field
    loaded from disk with values of current persistent object.

    `field`
        The name of a field on the persistent object.

    `function`
        A function that is called with three parameters, `old`, `new`, and
        `current`:

        `old`
            The value of the field in the older object.

        `new`
            The value of the field in the newer object.

        `current`
            The value of the field in the current persistent object. This is
            provided for cases where the identity of the object referred to
            by the field can't change.

        The function is expected to return the new value of the field in the
        persistent object.
    N)Úregistry)ÚfieldÚfuncr   r   r   Úregister_persistentû   s    rp   c                 C   s   |S r   r   ©rU   rV   Úcurrentr   r   r   Údefault_merge  s    rs   c                 C   s   |  | ¡ |  |¡ |S r   )r    rq   r   r   r   Údictset_merge  s    

rt   r-   r/   r1   r0   c                 C   sæ   t   ¡ }tjj}t|ƒ}t| ƒ}t| ¡ ƒt| ¡ ƒB }|D ]¤}| |d¡}| |d¡}||krbq<|j |d¡}	| j |d¡}
t	||
ƒ}
|	|
krž|}|}|	}n|}|}|
}t
 |t¡}||||ƒ}|||< t|ƒt|< ||j|< q<dS )zd
    Merges `other` (which must be a persistent object) into the
    current persistent object.
    Nr   )rK   r;   rL   rM   rN   r>   r3   rP   r?   Úminrm   rs   rJ   rO   )ÚotherrQ   rM   rR   ÚovarsrS   rT   ÚpvalÚovalÚptimeÚotimerV   rU   ÚtÚ
merge_funcÚvalr   r   r   Úmerge+  s2    
r   c                  C   s:   t jj ¡ D ]\} }| tkr q&qdS tƒ  t j ¡  dS )zi
    Checks to see if we need to run update. If we do, runs update and
    restarts the interaction.
    N)r;   ÚloadsaveÚlocationÚload_persistentÚpersistent_mtimer    ÚexportsÚrestart_interaction)ÚmtimeÚ_datar   r   r   Úcheck_update\  s    rˆ   Fc                 C   sj   t ƒ }|p| }tjj ¡ }|jdd„ d t}|D ]$\}}|tkrDq2|du rNq2t|ƒ q2|a|rftƒ  dS )z
    Loads the persistent data from persistent files that are newer than
    persistent_mtime, and merges it into the persistent object.
    c                 S   s   | d S )Nr   r   )Úar   r   r   Ú<lambda>z  r8   zupdate.<locals>.<lambda>)ÚkeyN)	rW   r;   r€   r   r‚   Úsortrƒ   r   Úsave)Ú
force_saveÚ	need_saveÚpairsr†   rv   r   r   r   r    l  s    
r    Tc                  C   sx   t sdS z&t ttjjƒd¡} tjj 	| ¡ W n t
yJ   tjjrF‚ Y n0 t}tjj ¡ D ]\}}|tkr\q\q\|adS )z,
    Saves the persistent data to disk.
    Né   )Úshould_save_persistentr\   Úcompressr   r;   rL   rM   r€   r   Úsave_persistentrG   rE   rF   rƒ   r‚   )r!   r†   r‡   r   r   r   r   “  s    r   c                  C   s   t D ]} |  ¡  qd S r   )Úsave_MP_instancesr   )Úinsr   r   r   Úsave_MP·  s    r—   c                   @   s0   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
S )Ú_MultiPersistentÚ c                 C   s   | j  ¡ }|d= |S )NÚ	_filename)r   rC   ©r   Ústater   r   r   r#   À  s    
z_MultiPersistent.__getstate__c                 C   s   | j  |¡ d S r   r   r›   r   r   r   r"   Å  s    z_MultiPersistent.__setstate__c                 C   s   |  d¡r| d¡rtƒ ‚d S )Nr$   r%   )r   Únamer   r   r   r*   È  s    z_MultiPersistent.__getattr__c                 C   s„   | j }t|d dƒ}t| |ƒ W d   ƒ n1 s40    Y  zt |d |¡ W n, ty~   t |¡ t |d |¡ Y n0 d S )Nz.newÚwb)rš   r   r   rY   ÚrenamerG   Úunlink)r   ÚfnrT   r   r   r   r   Ï  s    (
z_MultiPersistent.saveN)r@   rA   rB   rš   r#   r"   r*   r   r   r   r   r   r˜   ¼  s
   r˜   c              	   C   s¬  t j | ¡} t j ¡ js tdƒ‚t js,t jr8t j	j
g}njt jrttj d¡g}dtjv r¢| t j tjd ¡d ¡ n.t jr”tj d¡tj d¡g}ntj d¡g}dtjv rÀt j tjd ¡g}zt |d ¡ W n tyä   Y n0 d	}d }|D ]N}tj || ¡}tj |¡ròzt|d
ƒ ¡ }W  qBW qò ty>   Y qò0 qòtƒ }|d ur’zt|ƒ}W n2 ty   t jj d| ¡ t jj ¡  Y n0 ||_|r¨t |¡ |S )Nz>MultiPersistent objects must be created during the init phase.z~/RenPy/PersistentÚAPPDATAz/RenPy/persistentz~/.renpy/persistentz~/Library/RenPy/persistentÚRENPY_MULTIPERSISTENTéÿÿÿÿr™   rX   zLoading MultiPersistent at %r:) r;   r„   ÚfsdecoderL   ÚcontextÚ
init_phaserG   ÚandroidÚiosrE   rh   ÚwindowsrY   rZ   Ú
expanduserÚenvironÚappendÚ	macintoshÚmakedirsrg   Úisfiler   r^   r˜   r   r`   ra   rb   rc   rš   r•   Úadd)r   Úsave_on_quitÚfilesr¡   r!   rI   r   r   r   ÚMultiPersistentÜ  sR    


ÿ


r´   )F)F)6Ú
__future__r   r   r   r   r   Úrenpy.compatr   r   r	   r
   r   r   r   r   r   r   r   r   rY   rC   rK   r\   Úweakrefr;   Úrenpy.compat.pickler   r   r   Úobjectr   rL   rM   rJ   rO   rW   rf   rl   rm   rp   rs   rt   r   rƒ   rˆ   r    r’   r   ÚWeakSetr•   r—   r˜   r´   r€   r   r   r   r   Ú<module>   sH   8R
% 



.
$! 
A