
T\c           @  sp  d  d l  m Z d  d l Z d  d l 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
 Z
 d  d l Z d  d l Z d  d l Z d  d l m Z d  d l m Z d   Z d   Z d   Z e j Z d	   Z d
   Z d e f d     YZ d   Z d e f d     YZ d e d  Z e j   Z e j    d a! d   Z" d   Z# e e d  Z$ d   Z% d e d  Z& d d  Z( i  Z) d d  Z* d   Z+ d   Z, d   Z- e d  Z. d   Z/ d    Z0 d!   Z1 d"   Z2 d#   Z3 e j j4 d$  Z5 d% e f d&     YZ6 i  Z7 d'   Z8 d(   Z9 d)   Z: d*   Z; d Z< e rle j= j> d+  Z< n  d S(,   i(   t   print_functionN(   t   StringIO(   t   six(   t   dumpsc         C  s?   t  j j r% t j |  | t j  n t j |  | t j  d  S(   N(   t   renpyt   configt   use_cpicklet   cPicklet   dumpt   HIGHEST_PROTOCOLt   pickle(   t   ot   f(    (    s   renpy/loadsave.pyR   /   s    c         C  s6   t  j j r t j |  t j  St j |  t j  Sd  S(   N(   R   R   R   R   R   R	   R
   (   R   (    (    s   renpy/loadsave.pyR   6   s    c         C  s*   t  j j r t j |   St j |   Sd  S(   N(   R   R   R   R   t   loadsR
   (   t   s(    (    s   renpy/loadsave.pyR   =   s    c           s^   i       f d    t  j j d d  \   }  |  d   | d    j   d S(   s   
    Dumps information about the save to save_dump.txt. We dump the size
    of the object (including unique children), the path to the object,
    and the type or repr of the object.
    c           s  t  |   } |  k r<  j d j d |  |   d St |  t t t j t j t j	 f  rr t
 |   } n&t |  t t f  r t |   d k r t
 |   j d  } qt
 |  d  d  j d  } n t |  t t f  r d |  j j d } n t |  t  r#d |  j j d } nu t |  t j  rVd j |  j j |  j j  } nB t |  t  rd	 j t |   j  } n d
 j t |   j  } |  | <t |  t t t j t j t j	 f  rd } nt |  t t f  rt |   d d } nct |  t t f  rbd } xEt |   D]5 \ } } | d 7} |  | d j | |   7} q&Wnt |  t  rd } x|  j   D]5 \ } } | d 7} |  | d j | |   7} qWnt |  t j  rd  |  j | d  } nry |  j d    Wn g    d | } n X  f d   }	 d } |	 d i   }
 t |
 t  rxY |
 j   D]1 \ } } | d 7} |  | | d |  7} q\Wn |  |
 | d  7} xL t |	 d g    D]5 \ } } | d 7} |  | d j | |   7} qWxd |	 d g   D]S } t |  d k r(q
n  | \ } } | d 7} |  | d j | |   7} q
W j d j | |  |   | S(   Ns   {0: 7d} {1} = alias {2}
i    iP   s   utf-8s   ...t   <t   >s   <method {0}.{1}>s   <{0}>s   BAD TYPE <{0}>i   i(   s
   {0}[{1!r}]i   s   .im_selfs   BAD REDUCTION c           s2   |  t     k  r*   |  d  k	 r*   |  S| Sd  S(   N(   t   lent   None(   t   idxt   default(   t	   reduction(    s   renpy/loadsave.pyt   get   s    "t   .s   .__getstate__()i   s   {0}[{1}]i   s   {0: 7d} {1} = {2}
(   t   idt   writet   formatt
   isinstancet   intt   floatt   typest   NoneTypet
   ModuleTypet	   ClassTypet   reprt   strt   unicodeR   t   encodet   tuplet   listt	   __class__t   __name__t   dictt
   MethodTypet   im_classt   im_funct   objectt   typet	   enumeratet	   iteritemst   im_selft   __reduce_ex__(   R   t   patht   idot   o_reprt   sizet   it   oot   kt   vR   t   state(   R   t   o_repr_cachet   visit(   R   s   renpy/loadsave.pyR>   R   sx     ' !
'	
&
&
""
#
# s   save_dump.txtt   wt   rootst   logN(   R   t   errort   open_error_filet   close(   R@   RA   t   _(    (   R   R=   R>   s   renpy/loadsave.pyt	   save_dumpI   s    dc           sd   t         f d    x9 |  j   D]+ \ } }  | |  } | d k	 r( | Sq( W | d  S(   s7   
    Finds objects that can't be reduced properly.
    c           s  t  |   } |  k r d  S j |  t |  t t t j t j f  rN d  St |  t t	 f  r xt
 |   D]7 \ } }  | d j | |   } | d  k	 rp | Sqp Wn\t |  t  rxJ|  j   D]7 \ } }  | d j | |   } | d  k	 r | Sq Wnt |  t j  r. |  j | d  St |  t j  rZd j | t |   d   Sy |  j d    WnI d d  l } y | j |   d  SWn n Xd j | t |   d   SX  f d   }	 |	 d i   }
 t |
 t  r-xg |
 j   D]3 \ } }  | | d |  } | d  k	 r| SqWn#  |
 | d	  } | d  k	 rP| SxN t
 |	 d
 g    D]7 \ } }  | d j | |   } | d  k	 rf| SqfWxf |	 d g   D]U } t |  d k rqn  | \ } }  | d j | |   } | d  k	 r| SqWd  S(   Ns
   {0}[{1!r}]s   .im_selfs   {} = {}i   i   ic           s2   |  t     k  r*   |  d  k	 r*   |  S| Sd  S(   N(   R   R   (   R   R   (   R   (    s   renpy/loadsave.pyR      s    "R   s   .__getstate__()i   s   {0}[{1}]i   (   R   t   addR   R   R   R   R   R!   R&   R'   R0   R   R   R*   R1   R+   R2   R    R"   R3   t   copyR   (   R   R4   R5   R8   R9   t   rvR:   R;   RH   R   R<   (   t   seenR>   (   R   s   renpy/loadsave.pyR>      sh    !"s   renpy.game.logN(   t   sett   itemsR   (   R@   RA   R:   R;   RI   (    (   RJ   R>   s   renpy/loadsave.pyt   find_bad_reduction   s    	St	   SaveAbortc           B  s   e  Z RS(    (   R)   t
   __module__(    (    (    s   renpy/loadsave.pyRN   (  s   c         C  s   t  j j |  r" t  j |  n  y t  j |  |  WnM y! t  j |  t  j |  |  Wq y t  j |   Wq q Xq Xn Xd S(   s#   
    Safely rename old to new.
    N(   t   osR4   t   existst   unlinkt   rename(   t   oldt   new(    (    s   renpy/loadsave.pyt   safe_rename,  s    t
   SaveRecordc           B  s    e  Z d  Z d   Z d   Z RS(   s   
    This is passed to the save locations. It contains the information that
    goes into a save file in uncompressed form, and the logic to save that
    information to a Ren'Py-standard format save file.
    c         C  s1   | |  _  | |  _ | |  _ | |  _ d  |  _ d  S(   N(   t
   screenshott
   extra_infot   jsonRA   R   t   first_filename(   t   selfRX   RY   RZ   RA   (    (    s   renpy/loadsave.pyt   __init__L  s
    				c         C  s   | d } |  j  d k	 r= t j |  j  |  t | |  d St j | d t j  } | j d |  j	  | j d |  j
 j d   | j d |  j  | j d t j  | j d	 |  j  | j   t | |  | |  _  d S(
   sG   
        This writes a standard-format savefile to `filename`.
        s   .newNR?   s   screenshot.pngRY   s   utf-8RZ   t   renpy_versionRA   (   R[   R   t   shutilt   copyfileRV   t   zipfilet   ZipFilet   ZIP_DEFLATEDt   writestrRX   RY   R%   RZ   R   t   versionRA   RD   (   R\   t   filenamet   filename_newt   zf(    (    s   renpy/loadsave.pyt
   write_fileT  s    

(   R)   RO   t   __doc__R]   Ri   (    (    (    s   renpy/loadsave.pyRW   E  s   	t    c         C  s  | r t  t j _ n  t j j j d  } t j j	 rL t	 | t j j  n  t
   } y t | t j j f |  Wn t j   \ } } } | r t j | | |  n  y t | t j j  } Wn t j | | |  n X| d k rt j | | |  n  | j d d j |  f | j d | _ t j | | |  n X| rat j j rat    n  t j j j   }	 i | d 6t t j  d 6t j j d 6}
 x t j j D] } | |
  qWt |
  }
 t |	 | |
 | j    } t j |  |  t j   t  |   d S(   s  
    :doc: loadsave
    :args: (filename, extra_info='')

    Saves the game state to a save slot.

    `filename`
        A string giving the name of a save slot. Despite the variable name,
        this corresponds only loosely to filenames.

    `extra_info`
        An additional string that should be saved to the save file. Usually,
        this is the value of :var:`save_name`.

    :func:`renpy.take_screenshot` should be called before this function.
    i    s    (perhaps {})i   t
   _save_namet   _renpy_versiont   _versionN(!   t   FalseR   t   pythont   mutate_flagt   gameRA   t   freezeR   R   RF   R   R   t   syst   exc_infoR   t   reraiseRM   t   argsR   RN   t	   interfacet   get_screenshotR'   t   version_tupleRe   t   save_json_callbackst
   json_dumpsRW   t   getvaluet   locationt   savet   scant
   clear_slot(   t   slotnameRY   Rq   R@   t   logft   tt   et   tbt   badRX   RZ   R8   t   sr(    (    s   renpy/loadsave.pyR   y  s>    	+*
i    c         C  s   z ys t  d t j j  t j j r7 t j j   } n d } |  rY t j j d t  n  t d d t d | d a	 Wn n XWd  t
 j   t j r d d  l } | j   n  Xd  S(	   Ns   auto-Rk   t
   backgrounds   auto-1Rq   RY   i    i(   t   cycle_savesR   R   t   autosave_slotst   auto_save_extra_infot   exportst   take_screenshott   TrueR   t   autosave_countert   autosave_not_runningRK   t
   emscriptent   syncfs(   R   RY   R   (    (    s   renpy/loadsave.pyt   autosave_thread  s     

	c           C  s   t  j j s d  St j   s  d  St  j j r0 d  St t  j j  d k rL d  St	 d 7a	 t	 t  j j k  rl d  St  j
 j r| d  St t  d  S(   Ni   (   R   R   t   autosave_frequencyR   t   isSett   skippingR   Rr   t   contextsR   t   storet	   main_menut   force_autosaveR   (    (    (    s   renpy/loadsave.pyt   autosave  s    
c         C  s  t  j j s t  j j   r d St j   s/ d St  j j r? d St  j j	 rO d S| r t  j
 j rs t  j
 j   } n d } t d t  j
 j  |  r t  j j   n  t d d | d St j   t  j s t j d t d |  f  } t | _ | j   n d d l } | j t |  d  d S(	   s  
    :doc: other

    Forces a background autosave to occur.

    `take_screenshot`
        If True, a new screenshot will be taken. If False, the existing
        screenshot will be used.

    `block`
        If True, blocks until the autosave completes.
    NRk   s   auto-s   auto-1RY   t   targetRw   i(   R   Rr   t   after_rollbackR   t   in_rollbackR   R   R   R   t
   _in_replayR   R   R   R   R   R   t   clearR   t	   threadingt   ThreadR   R   t   daemont   startt
   async_call(   R   t   blockRY   R   R   (    (    s   renpy/loadsave.pyR     s0    
		c         C  s   t  |   } | j   } | d  k r( d  S| j   } | d  k rD d  S| j d d  } | j   } | d  k rr d  S| | | f S(   NRl   Rk   (   t	   get_cachet	   get_mtimeR   t   get_jsonR   Ry   (   R   t   ct   mtimeRZ   RY   RX   (    (    s   renpy/loadsave.pyt   scan_saved_game:  s    R   c         C  s   t  j   } |  d k	 rF g  | D] } t j |  |  r | ^ q } n  | j   | rZ | Sg  } x | D] } t |  } | d k	 rg | j   } | d k	 r | j d d  } n d } | j	   }	 | j
   }
 | j | | |	 |
 f  qg qg W| S(   s3  
    :doc: loadsave

    Lists the save games. For each save game, returns a tuple containing:

    * The filename of the save.
    * The extra_info that was passed in.
    * A displayable that, when displayed, shows the screenshot that was
      used when saving the game.
    * The time the game was stayed at, in seconds since the UNIX epoch.

    `regexp`
        A regular expression that is matched against the start of the
        filename to filter the list.

    `fast`
        If fast is true, the filename is returned instead of the
        tuple.
    Rl   Rk   N(   R~   R'   R   t   ret   matcht   sortR   R   R   Ry   R   t   append(   t   regexpt   fastt   slotsR8   RI   R   R   RZ   RY   RX   R   (    (    s   renpy/loadsave.pyt   list_saved_gamesQ  s$    .
 c         C  sT   t  j   } |  d k	 rF g  | D] } t j |  |  r | ^ q } n  | j   | S(   s   
    :doc: loadsave

    Returns a list of non-empty save slots. If `regexp` exists, only slots
    that begin with `regexp` are returned. The slots are sorted in
    string-order.
    N(   R~   R'   R   R   R   R   (   R   R   R8   (    (    s   renpy/loadsave.pyt
   list_slots  s
    
.
c         C  s   t  j |  t  } | t k r d } d } t j   } xu | D]j } |  d k	 rh t j |  |  rh q= n  t |  j	   } | d k r q= n  | | k r= | } | } q= q= Wn  | t  |  <| S(   s   
    :doc: loadsave

    Returns the name of the newest save slot (the save slot with the most
    recent modification time), or None if there are no (matching) saves.

    If `regexp` exists, only slots that begin with `regexp` are returned.
    i    N(
   t   newest_slot_cacheR   t   unknownR   R~   R'   R   R   R   R   (   R   RI   t	   max_mtimeR   R8   R   (    (    s   renpy/loadsave.pyt   newest_slot  s     

c         C  s   t  |   j   S(   se   
    :doc: loadsave

    Returns the modification time for `slot`, or None if the slot is empty.
    (   R   R   (   R   (    (    s   renpy/loadsave.pyt
   slot_mtime  s    c         C  s   t  |   j   S(   sl   
    :doc: loadsave

    Returns the json information for `slotname`, or None if the slot is
    empty.
    (   R   R   (   R   (    (    s   renpy/loadsave.pyt	   slot_json  s    c         C  s   t  |   j   S(   s   
    :doc: loadsave

    Returns a display that can be used as the screenshot for `slotname`,
    or None if the slot is empty.
    (   R   Ry   (   R   (    (    s   renpy/loadsave.pyt   slot_screenshot  s    c         C  s$   t  |   } | j   r t St Sd S(   sd   
    :doc: loadsave

    Returns true if `filename` exists as a save slot, and False otherwise.
    N(   R   R   R   Ro   (   Rf   t   testR   (    (    s   renpy/loadsave.pyt   can_load  s    c         C  s2   t  t j |    \ } } | j | d d d S(   s   
    :doc: loadsave

    Loads the game state from the save slot `filename`. If the file is loaded
    successfully, this function never returns.
    t   labelt   _after_loadN(   R   R~   t   loadt   unfreeze(   Rf   R@   RA   (    (    s   renpy/loadsave.pyR     s    c         C  s   t  j |   t |   d S(   sH   
    :doc: loadsave

    Deletes the save slot with the given name.
    N(   R~   RR   R   (   Rf   (    (    s   renpy/loadsave.pyt   unlink_save  s    c         C  s(   t  j |  |  t |   t |  d S(   sm   
    :doc: loadsave

    Renames a save from `old` to `new`. (Does nothing if `old` does not
    exist.)
    N(   R~   RS   R   (   RT   RU   (    (    s   renpy/loadsave.pyt   rename_save  s    
c         C  s   t  j |  |  t |  d S(   sl   
    :doc: loadsave

    Copies the save at `old` to `new`. (Does nothing if `old` does not
    exist.)
    N(   R~   RH   R   (   RT   RU   (    (    s   renpy/loadsave.pyt	   copy_save  s    c         C  sJ   xC t  | d d d  D]+ } t |  t |  |  t | d   q Wd S(   s  
    :doc: loadsave

    Rotates the first `count` saves beginning with `name`.

    For example, if the name is auto- and the count is 10, then
    auto-9 will be renamed to auto-10, auto-8 will be renamed to auto-9,
    and so on until auto-1 is renamed to auto-2.
    i   i    iN(   t   rangeR   R#   (   t   namet   countR8   (    (    s   renpy/loadsave.pyR   !  s    R   t   Cachec           B  sD   e  Z d  Z d   Z d   Z d   Z d   Z d   Z d   Z RS(   s?   
    This represents cached information about a save slot.
    c         C  s   | |  _  |  j   d  S(   N(   R   R   (   R\   R   (    (    s   renpy/loadsave.pyR]   =  s    	c         C  s   t  |  _ t  |  _ t  |  _ d  S(   N(   R   R   RZ   RX   (   R\   (    (    s   renpy/loadsave.pyR   A  s    		c         C  s5   |  j  } | t k r1 t j  |  j  } |  _  n  | S(   N(   R   R   R~   R   (   R\   RI   (    (    s   renpy/loadsave.pyR   K  s    	c         C  s5   |  j  } | t k r1 t j  |  j  } |  _  n  | S(   N(   RZ   R   R~   R   (   R\   RI   (    (    s   renpy/loadsave.pyR   T  s    	c         C  s8   |  j  } | t k r1 t j  |  j  } |  _  n  |  j  S(   N(   RX   R   R~   R   (   R\   RI   (    (    s   renpy/loadsave.pyRy   ]  s    	c         C  s"   |  j    |  j   |  j   d S(   sR   
        Preloads all the save data (that won't take up a ton of memory).
        N(   R   R   Ry   (   R\   (    (    s   renpy/loadsave.pyt   preloadf  s    

(	   R)   RO   Rj   R]   R   R   R   Ry   R   (    (    (    s   renpy/loadsave.pyR   8  s   		
						c         C  s9   t  j |  d   } | d  k r5 t |   } t  |  <n  | S(   N(   t   cacheR   R   R   (   R   RI   (    (    s   renpy/loadsave.pyR   v  s    c         C  s+   t  |   j   t j   t j j   d S(   s,   
    Clears a single slot in the cache.
    N(   R   R   R   R   R   t   restart_interaction(   R   (    (    s   renpy/loadsave.pyR     s    
c          C  s<   x t  j   D] }  |  j   q Wt j   t j j   d S(   s"   
    Clears the entire cache.
    N(   R   t   valuesR   R   R   R   R   (   R   (    (    s   renpy/loadsave.pyt   clear_cache  s    
c          C  s:   x3 t    D]( }  |  j d  s
 t |   j   q
 q
 Wd S(   s:   
    Scans all the metadata from the save slot cache.
    RE   N(   R   t
   startswithR   R   (   R8   (    (    s   renpy/loadsave.pyt   init  s    t   blah(?   t
   __future__R    R
   R   t	   cStringIOR   Ra   R   R   R   R_   RP   Rt   R   R   RZ   R   R|   R   R   t   savegame_suffixRF   RM   t	   ExceptionRN   RV   R.   RW   Ro   R   t   EventR   RK   R   R   R   R   R   R   R   R   R   R   R   R   R   R   R   R   R   R   R   t   SentinelR   R   R   R   R   R   R   R~   t   savelocationt   FileLocation(    (    (    s   renpy/loadsave.pyt   <module>   sj   						u	j	4C
		<	5#	
							;	
			