
;\c           @  s  d  d l  m Z d  d l Z d  d l Z d  d l m 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 j d  d   Z y d  d l Z e j j d d  Z e d k	 re d	 e  e j j d
 e d d  e j j d
 e d d  g Z e d g Z nA e d  e j j d d  e j j d d  g Z e d g Z Wn e k
 r~g  Z g  Z n Xg  a d a i  Z d   Z d   Z  g  a! g  a" i  Z# d   Z$ d   Z% e& d  Z' d e( f d     YZ) e* Z+ d e j k r
d   Z+ n  d   Z, d   Z- e& d  Z. e& d  Z/ d   Z0 d   Z1 d   Z2 e3   Z4 d    Z5 d! e( f d"     YZ6 g  Z7 d#   Z8 d$   Z9 d%   Z: e; a< i  Z= d a> e& a? e j@   ZA e j( jB d&  ZC d'   ZD e; d(  ZE d)   ZF d*   ZG d+   ZH d S(,   i(   t   print_functionN(   t   loads(   t   StringIOu    s   utf-8c         C  sa   t  j j t j j |   }  t  j j |   } y& t  j j |  sR t  j |  n  Wn n X|  S(   s   
    Returns the path to `fn` relative to the gamedir. If any of the directories
    leading to `fn` do not exist, tries to create them.

    This always returns a path, but the path may or may not be writable.
    (	   t   ost   patht   joint   renpyt   configt   gamedirt   dirnamet   existst   makedirs(   t   fnt   dn(    (    s   renpy/loader.pyt   get_path(   s    t   ANDROID_EXPANSIONs   Using expansion filet   apkt   prefixs   assets/x-game/s   assets/x-renpy/x-common/i    s   Not using expansion file.c          C  s  t  t j j k r d St j j a  t j   t   g  a x8t j j D]*}  yt |  d  } t | d  } | j	   } | j
 d  rt | d d !d  } t | d d	 !d  } | j |  t | j   j d
   } x | j   D] } t | | d  d k rCg  | | D]  \ } } | | A| | Af ^ q| | <q g  | | D]& \ } } }	 | | A| | A|	 f ^ qN| | <q Wt j |  | f  | j   wG n  | j
 d  rt | d d  } | j |  t | j   j d
   } t j |  | f  | j   wG n  | j   t |  d  } t t | d  j   j d
   } t j |  | f  WqG   qG XqG Wx' t   D] \ }
 } | t | j   <qWd S(   sQ   
    Loads in the indexes for the archive files. Also updates the lower_map.
    Ns   .rpat   rbs   RPA-3.0 i   i   i   i   i!   t   zlibi    i   s   RPA-2.0 s   .rpi(   t   old_config_archivesR   R   t   archivest	   lower_mapt   cleart   cleardirfilest   transfnt   filet   readlinet
   startswitht   intt   seekR   t   readt   decodet   keyst   lent   appendt   closet   listdirfilest   lower(   R   R   t   ft   lt   offsett   keyt   indext   kt   dlent   startt   dir(    (    s   renpy/loader.pyt   index_archivesf   sL    	
8?


$c         C  s   g  } t  j j |   r* t j j r* | Sx t  j |   D] } | d d k rV q: n  y t j j |  } Wn
 q: n Xt  j j	 |  d |  r xA t
 |  d |  D] } | j | d |  q Wq: | j |  q: W| S(   Ni    t   .t   /(   R   R   R
   R   R   t	   developert   listdirt   exportst   fsdecodet   isdirt   walkdirR#   (   R/   t   rvt   iR   (    (    s   renpy/loader.pyR8      s     c           C  s   g  a  g  a d S(   s;   
    Clears the lists above when the game has changed.
    N(   t
   game_filest   common_files(    (    (    s   renpy/loader.pyR      s    c            sU  t        f d   }  xo t D]g } | t k r= t   n t   xC | j   D]5 } d j d   | j d  D  } |  d |  qP Wq" Wx t	 j
 j D]r } t	 j
 j r | t	 j
 j k r t   n t   t j j t	 j
 j |  } x! t |  D] } |  | |  q Wq Wt   x8 t D]0 \ } } x! | j   D] } |  d |  q6WqWd S(   s^   
    Scans directories, archives, and apks and fills out game_files and
    common_files.
    c           sj   |  k r d  S| j  d  r# d  S| j  d  r6 d  S  j |  | f   j |  t t | j   <d  S(   Ns   cache/s   saves/(   R   R#   t   addt   Truet   loadable_cacheR&   (   R   R   (   t   filest   seen(    s   renpy/loader.pyR=      s    R2   c         s  s   |  ] } | d  Vq d S(   i   N(    (   t   .0R:   (    (    s   renpy/loader.pys	   <genexpr>   s    N(   t   sett   apkst	   game_apksR<   R;   t   listR   t   splitt   NoneR   R   t
   searchpatht	   commondirR   R   t   basedirR8   R   t   iterkeys(   R=   R   R'   R:   t   jt   _prefixR+   (    (   R@   RA   s   renpy/loader.pyt   scandirfiles   s(    		"	c         C  s4   t  r t r t   n  |  r& t  t St t   Sd S(   s   
    Returns a list of directory, file tuples known to the system. If
    the file is in an archive, the directory is None.
    N(   R;   R<   RO   RF   (   t   common(    (    s   renpy/loader.pyR%     s
    
t   SubFilec           B  s   e  Z d    Z d   Z d   Z d   Z d d  Z d d  Z d d  Z	 d   Z
 d   Z d	   Z d
   Z d d  Z d   Z d   Z d   Z RS(   c         C  sX   | |  _  d  |  _ | |  _ d |  _ | |  _ | |  _ |  j sK | |  _ n	 d  |  _ d  S(   Ni    (   R   RH   R'   t   baseR)   t   lengthR.   t   name(   t   selfR   RR   RS   R.   (    (    s   renpy/loader.pyt   __init__$  s    							c         C  s,   t  |  j d  |  _ |  j j |  j  d  S(   NR   (   t   openR   R'   R   RR   (   RU   (    (    s   renpy/loader.pyRW   3  s    c         C  s   |  S(   N(    (   RU   (    (    s   renpy/loader.pyt	   __enter__7  s    c         C  s   |  j    t S(   N(   R$   t   False(   RU   t   _typet   valuet   tb(    (    s   renpy/loader.pyt   __exit__:  s    
c         C  s   |  j  d  k r |  j   n  |  j |  j } | d  k	 rJ t | |  } n | } |  j |  j |  j | !} | t |  8} |  j t |  7_ | r |  j  j |  } |  j t |  7_ n d } | | S(   Nt    (	   R'   RH   RW   RS   R)   t   minR.   R"   R   (   RU   RS   t	   maxlengtht   rv1t   rv2(    (    s   renpy/loader.pyR   >  s    c         C  s   |  j  d  k r |  j   n  |  j |  j } | d  k	 rJ t | |  } n | } |  j t |  j  k  r d } x= | r |  j d  } | | 7} | d k r Pn  | d 8} qq W| S|  j  j	 |  } |  j t |  7_ | S(   NR^   i   s   
(
   R'   RH   RW   RS   R)   R_   R"   R.   R   R   (   RU   RS   R`   R9   t   c(    (    s   renpy/loader.pyR   V  s$    	
c         C  sl   g  } x_ t  rg |  j |  } | s( Pn  | d  k	 rW | t |  8} | d k  rW PqW n  | j |  q	 W| S(   Ni    (   R>   R   RH   R"   R#   (   RU   RS   R9   R(   (    (    s   renpy/loader.pyt	   readlinesu  s    	c         C  s   |  S(   N(    (   RU   (    (    s   renpy/loader.pyt
   xreadlines  s    c         C  s   |  S(   N(    (   RU   (    (    s   renpy/loader.pyt   __iter__  s    c         C  s"   |  j    } | s t    n  | S(   N(   R   t   StopIteration(   RU   R9   (    (    s   renpy/loader.pyt   next  s    c         C  s   d  S(   N(    (   RU   (    (    s   renpy/loader.pyt   flush  s    i    c         C  s   |  j  d  k r |  j   n  | d k r1 | } n8 | d k rM |  j | } n | d k ri |  j | } n  | |  j k r |  j } n  | |  _ | t |  j  } | d k  r d } n  |  j  j | |  j  d  S(   Ni    i   i   (	   R'   RH   RW   R)   RS   R"   R.   R   RR   (   RU   R)   t   whence(    (    s   renpy/loader.pyR     s    			c         C  s   |  j  S(   N(   R)   (   RU   (    (    s   renpy/loader.pyt   tell  s    c         C  s,   |  j  d  k	 r( |  j  j   d  |  _  n  d  S(   N(   R'   RH   R$   (   RU   (    (    s   renpy/loader.pyR$     s    c         C  s   t  d   d  S(   Ns   Write not supported by SubFile(   t	   Exception(   RU   t   s(    (    s   renpy/loader.pyt   write  s    N(   t   __name__t
   __module__RV   RW   RX   R]   RH   R   R   Rd   Re   Rf   Rh   Ri   R   Rk   R$   Rn   (    (    (    s   renpy/loader.pyRQ   "  s   										t   RENPY_FORCE_SUBFILEc         C  sN   t  |  |  } | j d d  | j   } | j d d  t | d | d  S(   Ni    i   R^   (   RW   R   Rk   RQ   (   RT   t   modeR'   RS   (    (    s   renpy/loader.pyt	   open_file  s
    c         C  s  t  j |  j   |   }  t j j rI t j j |   } | d	 k	 rI | Sn  t j j s y t |   } t	 | d  SWq q Xn  xU t
 D]M } d j d   |  j d  D  } y | j |  SWq t k
 r q Xq Wxt D]\ } } |  | k r q n  t | d  } g  } t | |   d k r| |  d }	 t |	  d k r]|	 \ }
 } d } n |	 \ }
 } } t | |
 | |  } nl t | d  } x; | |  D]/ \ }
 } | j |
  | j | j |   qWt d j |   } | j   | SWd	 S(
   s?   
    Returns an open python file object of the given type.
    R   R2   c         s  s   |  ] } d  | Vq d S(   s   x-N(    (   RB   R:   (    (    s   renpy/loader.pys	   <genexpr>  s    s   .rpai   i    i   R^   N(   R   t   getR&   R   R   t   file_open_callbackRH   t   force_archivesR   Rs   RD   R   RG   RW   t   IOErrorR   R"   RQ   R   R   R#   R   R   R$   (   RT   R9   R   R   t   prefixed_nameR   R+   t   afnt   datat   tR)   R-   R.   R'   (    (    s   renpy/loader.pyt	   load_core  sJ    "	
c         C  sx   t  j j r+ d |  k r+ t d |    n  t  j j rt |  j d  } d | k s^ d | k rt t d |    qt n  d S(   sF   
    Checks the name to see if it violates any of Ren'Py's rules.
    s   \s*   Backslash in filename, use '/' instead: %rR2   R1   s   ..sD   Filenames may not contain relative directories like '.' and '..': %rN(   R   R   t   reject_backslashRl   t   reject_relativeRG   (   RT   RG   (    (    s   renpy/loader.pyt
   check_name
  s    c         C  s~   g  } |  r t  j j j } n d } xS t  j j D]E } | d k	 ri | j t  j j d | d |  n  | j |  q1 W| S(   s9   
    Returns a list of prefixes to search for files.
    R2   N(	   R   t   gamet   preferencest   languageRH   R   t   search_prefixesR#   t   tl_directory(   t   tlR9   R   R   (    (    s   renpy/loader.pyt   get_prefixes  s    &c         C  s   t  j j j r? t j   j d k r? t d j |     q? n  t  j	 j
 rj d |  k rj t d |    n  t j d d |   j d  }  x4 t |  D]& } t | |   } | d  k	 r | Sq Wt d |    d  S(   Nt
   MainThreads%   Refusing to open {} while predicting.s   \s*   Backslash in filename, use '/' instead: %rs   /+R2   s   Couldn't find file '%s'.(   R   t   displayt   predictt
   predictingt	   threadingt   current_threadRT   Rl   t   formatR   R}   t   ret   subt   lstripR   R|   RH   Rw   (   RT   R   t   pR9   (    (    s   renpy/loader.pyt   load0  s    c         C  s   t  j |  j   |   }  |  t k r, t |  Sy t |   t t |  <t SWn n XxM t D]E } d j d   |  j d  D  } | | j	 k rY t t |  <t SqY Wx. t
 D]& \ } } |  | k r t t |  <t Sq Wt t |  <t S(   sM   
    Returns True if the name is loadable with load, False if it is not.
    R2   c         s  s   |  ] } d  | Vq d S(   s   x-N(    (   RB   R:   (    (    s   renpy/loader.pys	   <genexpr>U  s    (   R   Rt   R&   R?   R   R>   RD   R   RG   t   infoR   RY   (   RT   R   Rx   RN   R+   (    (    s   renpy/loader.pyt   loadable_coreC  s(    

"


c         C  sc   |  j  d  }  t j j d  k	 r7 t j j |   r7 t Sx% t   D] } t | |   rA t SqA Wt S(   NR2   (	   R   R   R   t   loadable_callbackRH   R>   R   R   RY   (   RT   R   (    (    s   renpy/loader.pyt   loadablec  s    $c         C  s   |  j  d  }  t j j r: d |  k r: t d |    n  t j |  j   |   }  t |  t	  rs |  j
 d  }  n  xR t j j D]D } t j j t j j | |   } t |  t j j |  r | Sq Wt d |    d S(   sc   
    Tries to translate the name to a file that exists in one of the
    searched directories.
    R2   s   \s*   Backslash in filename, use '/' instead: %rs   utf-8s   Couldn't find file '%s'.N(   R   R   R   R}   Rl   R   Rt   R&   t
   isinstancet   strR    RI   R   R   R   RK   t   add_autoR
   (   RT   t   dR   (    (    s   renpy/loader.pyR   q  s    
c         C  s   t  j |  d  } | d k	 r" | Sd } yH t |   } x5 t rn | j d  } | sY Pn  t j | |  } q: WWn n X| t  |  <| S(   se   
    Returns the time the file m was last modified, or 0 if it
    doesn't exist or is archived.
    i    i   Ni   (   t
   hash_cacheRt   RH   R   R>   R   R   t   adler32(   RT   R9   R'   Rz   (    (    s   renpy/loader.pyt   get_hash  s    	
t   RenpyImporterc           B  sD   e  Z d  Z d d  Z d d  Z d d  Z d   Z d   Z RS(   sk   
    An importer, that tries to load modules from the places where Ren'Py
    searches for data files.
    R^   c         C  s   | |  _  d  S(   N(   R   (   RU   R   (    (    s   renpy/loader.pyRV     s    c         C  sz   | d  k r |  j } n  y# | | j d d  j d  } Wn d  SXt | d  r^ | d St | d  rv | d Sd  S(   NR1   R2   t   utf8s   .pys   /__init__.py(   RH   R   t   replaceR    R   (   RU   t   fullnameR   R   (    (    s   renpy/loader.pyt	   translate  s    #c         C  sS   | d  k	 r< x- | D]" } |  j | |  r t |  Sq Wn  |  j |  rO |  Sd  S(   N(   RH   R   R   (   RU   R   R   R:   (    (    s   renpy/loader.pyt   find_module  s    c         B  s
  |  j  | |  j  } e j j | e j |   } | | _ | | _ |  | _	 | j
 d  rw | e d   g | _ n  e |  j   j d  } | r | d d k r | d } n  | j d  } | j d d  } e | | d	 e j j d  } | | j Ue j | S(
   Ns   __init__.pyR   i    u   ﻿i   t   raw_unicode_escapes   R^   t   exec(   R   R   t   syst   modulest
   setdefaultt   typest
   ModuleTypeRo   t   __file__t
   __loader__t   endswithR"   t   __path__R   R   R    t   encodeR   t   compileR   t   pythont   old_compile_flagst   __dict__(   RU   R   t   filenamet   modt   sourcet   code(    (    s   renpy/loader.pyt   load_module  s    			c         C  s   t  |  j   S(   N(   R   R   (   RU   R   (    (    s   renpy/loader.pyt   get_data  s    N(	   Ro   Rp   t   __doc__RV   RH   R   R   R   R   (    (    (    s   renpy/loader.pyR     s   		c         C  s@   |  r# |  j  d  r# |  d }  n  t j j d t |    d S(   s   
    :doc: other

    Adds `path` to the list of paths searched for Python modules and packages.
    The path should be a string relative to the game directory. This must be
    called before an import statement.
    R2   i    N(   R   R   t	   meta_patht   insertR   (   R   (    (    s   renpy/loader.pyt   add_python_directory  s    	c           C  s"   t  j t (t d  t d  d  S(   Ns   python-packages/R^   (   R   R   t   meta_backupR   (    (    (    s   renpy/loader.pyt   init_importer  s    

c           C  s   t  t j (d  S(   N(   R   R   R   (    (    (    s   renpy/loader.pyt   quit_importer
  s    t   auto_blacklistedc         C  s#   y t  j j |   SWn d SXd S(   sC   
    Gets the mtime of fn, or None if the file does not exist.
    N(   R   R   t   getmtimeRH   (   R   (    (    s   renpy/loader.pyt
   auto_mtime$  s    c         C  s   |  j  d d  }  t j s d S|  t k r6 | r6 d Sx> t j j D]0 } |  j |  rC t  t t |  <Wd QXd SqC Wt	 |   } t  | t |  <Wd QXd S(   s   
    Adds fn as a file we watch for changes. If it's mtime changes or the file
    starts/stops existing, we trigger a reload.
    s   \R2   N(
   R   R   t
   autoreloadt   auto_mtimesR   t   autoreload_blacklistR   t	   auto_lockR   R   (   R   t   forcet   et   mtime(    (    s   renpy/loader.pyR   /  s    	c       	   C  s   x t  r t ( t j d  t r' d St j   }  Wd QXxg |  D]_ \ } } | t k r^ q@ n  t |  | k r@ t $ t |  t | k r t  a n  Wd QXq@ q@ Wq Wd S(   s:   
    This thread sets need_autoreload when necessary.
    g      ?N(	   R>   R   t   waitt   auto_quit_flagR   t   itemsR   R   t   needs_autoreload(   R   R   R   (    (    s   renpy/loader.pyt   auto_thread_functionI  s    	c           C  sB   t  a t j s d St  a t j d t  a t	 t _
 t j   d S(   s'   
    Starts the autoreload thread.
    Nt   target(   RY   R   R   R   R   R   t   ThreadR   t   auto_threadR>   t   daemonR.   (    (    (    s   renpy/loader.pyt	   auto_initg  s    			c           C  s;   t  d k r d St a t  t j   Wd QXt  j   d S(   s+   
    Terminates the autoreload thread.
    N(   R   RH   R>   R   R   t
   notify_allR   (    (    (    s   renpy/loader.pyt	   auto_quit|  s    (I   t
   __future__R    R   t   os.pathR   t   pickleR   t	   cStringIOR   R   R   R   R   R   R   R   t   android.apkt   androidt   environRt   RH   t	   expansiont   printR   t   APKRD   RE   t   ImportErrorR   R   R   R0   R8   R;   R<   R?   R   RO   R>   R%   t   objectRQ   RW   Rs   R|   R   R   R   R   R   R   t   dictR   R   R   R   R   R   R   RY   R   R   R   R   t	   ConditionR   t   SentinelR   R   R   R   R   R   (    (    (    s   renpy/loader.pyt   <module>   s   	

	H			7
	B		 				!A						