
                         2   S r SSKrSSKrSSKrSSKrSSKrSSKrSSKrSSK	r	SSK
r
SSKrSSKrSSKrSSKrSSKrSSKJrJrJrJrJrJrJrJrJrJrJrJr  SSKr\\S4   r\R>                  RA                  S5      r!\!b  \!RD                  (       a  SSK#r#OSr#\RH                  RJ                  =(       d?    \
RL                  RA                  SS5      =(       d    \
RL                  RA                  SS5      r'Sr(\
RR                  S	-   \
RR                  -   r*\r+S
\SS4S jr,\RZ                  " SS9SYS j5       r.S\SS4S jr/\R`                  S:  a  C/\Rb                     SZS\S\S   S\\   S\\   S\24
S jj5       r3\Rb                     S[S\S\S   S\\   S\\   S\4
S jj5       r3\Rb                     SZS\S\S\\   S\\   S\\2\4   4
S jj5       r3   SZS\S\S\\   S\\   S\\2\4   4
S jjr3\Rb                     SZS\S\S   S\\   S\\   S\4
S jj5       r4\Rb                     S[S\S\S   S\\   S\\   S\4
S jj5       r4\Rb                     SZS\S\S\\   S\\   S\\\4   4
S  jj5       r4   SZS\S\S\\   S\\   S\\\4   4
S! jjr40 r5\Rl                  " 5       r7S\S\S\S\4S" jjr8Sq9\Rt                  " 5       r;/ r<S\4S# jr=S\S\S\S\4S$ jjr>S\S%\\2\4   S\4S& jr?S'\S(\S\@4S) jrAS\+4S* jrBS+\+S\@4S, jrCS+\+S\@4S- jrDS+\+S\@4S. jrES\@4S/ jrFSqGS+\+S\@4S0 jrHS\R                  4S1 jrJS2\S3\S\4S4 jrKS5\R                  S6\\/\@4   S7\SS4S8 jrLS\S\\M   4S9 jrN\Rt                  " 5       rOS:\S7\S\@4S; jrP\Rb                     S]S\S\S   S\\   S\\   S\\\S4   \S\4   4   4
S< jj5       rQ\Rb                     SZS\S\S   S\\   S\\   S\\\S4   \S\24   4   4
S= jj5       rQ\Rb                     S]S\S\S\\   S\\   S\\\S4   \S\24   4   4
S> jj5       rQ   S]S\S\S\\   S\\   S\\\S4   \S\\2\4   4   4   4
S? jjrQ " S@ SA5      rRSqSSB\SC\\\\\   \\   4      4SD jrTS7\S\\\\\   \\   4      4SE jrUSF\S\\\   \\   4   4SG jrVS\\   4SH jrWSI\S\\   4SJ jrXSqYS\@4SK jrZS\\   4SL jr[SM SN4SO\\\\/\@4   4   SP\@S\4SQ jjr\\]" 5       r^\^q_S\\   4SR jr`SqaSqb\Rb                   S^S7\S\S   S\4SS jj5       rc\Rb                   S\S7\S\S   S\4ST jj5       rc\Rb                   S^S7\S\S\\\4   4SU jj5       rc S^S7\S\S\\\4   4SV jjrcS_SW jrdS_SX jreg)`a	  API for accessing data files from the Google codebase.

Provide a consistent API for accessing data files from the Google
codebase, whether the program is being run from a PAR file, a
Google3 module-space, or whatever.

A "resource" is simply the contents of a named file, and can be made available
by adding a data dependency in the BUILD file, e.g.:

    data = ["//foo/bar:filename.txt"],

The name of a resource is something like
`google3/tools/includes/IMPORTMAP`.  Formally, it's a relative path
name, and it's relative to the root of the Google code base (the
directory immediately above the google, google2, google3
directories).

Path components are separated by forward slashes on all platforms
regardless of the native filesystem conventions.

Search order for resources:
 1) If this module was loaded from a parfile, look in the parfile.
 2) Look relative to this module's `__file__` attribute, outside of READONLY
    to give files that are opened in the P4 client preference.
 3) Look relative to this module's `__file__` attribute, if available
 4) Look relative to `sitecustomize.GOOGLEBASE`, if available
 5) Look relative to `os.environ["GOOGLEBASE"]`, if available
 6) Check for a READONLY symlink for srcfs

Unless otherwise noted, these functions are NOT thread-safe.
    N)AnyBinaryIOCallableDictIterableIteratorListLiteralOptionalTextIOTupleUnionzos.PathLike[str]_launcher_infoPYTHONVERBOSERESOURCESVERBOSEi  google3msgreturnc           	          [         (       aQ  [        R                  R                  S[        R
                  " 5       < S[        R                  S   < SU < S35        g g )Nz[pid:z] r    
)
_verbositysysstderrwriteosgetpidargv)r   s    +platform/bq/third_party/pyglib/resources.py_Logr    S   s3    ZJJ299;SIJ     )maxsizeimportlib.abc.Traversablec                  T    [         R                  R                  S5      R                  $ )Nr   )	importlib	resourcesfilesparent r!   r   	_Runfilesr*   X   s!     
			"	"9	-	4	44r!   pathsc                  0    [        5       R                  " U 6 $ )a  Provide a pathlib-style access to files inside the google3 runfiles directory.

This is a read-only view of data dependencies of your build rule. It is
preferred over GetResource() or GetResourceFilename(). The functionality
is thread-safe, and it does not trigger a .par file extraction to disk.

Unlike other methods here, there is no filesystem resolution order: only
one location: Either runfiles or the par file, will be observed.

The return value of a Get('filename') call is an object that implements
the methods of go/importlib.abc.Traversable.

The important methods are:

  * resources.Get(path).open() -> IO[str]
  * resources.Get(path).open(mode='rb') -> IO[bytes]
  * resources.Get(path).read_bytes() -> bytes
  * resources.Get(path).read_text() -> str
  * resources.Get(path).joinpath(name) -> Traversable

In a .par file context, the concrete class of the Traversable will be
zipfile.Path, and in a runfiles context (such as a Python unit test) it will
be pathlib.Path.

Example usage:

    from pyglib import resources

    with resources.Get('google3/project/testdata/input.txt').open() as f:
      for line in f:
        process(line)

    testdata_dir = resources.Get('google3/project/testdata')
    inputs = [testdata_dir.joinpath(filename).read_text()
              for filename in filenames]

Supported on Python 3.10 or later.

Args:
  *paths: The path segements to join together to find the file under the
    runfiles directory. For example: ('google3/pyglib/build_data.txt') or
    ('google3/pyglib/testdata', 'gfile_test.txt')

Returns:
  An go/importlib.abc.Traversable instance, which gives important methods
  like: is_dir(), is_file(), joinpath(child), open(mode=...), read_bytes()
  and read_text(). If the path does not exist, then no error will be raised.
)r*   joinpath)r+   s    r   Getr.   _   s    b 
		u	%%r!   )   
   rbnamemodeencodingerrorsc                     g Nr)   r2   r3   r4   r5   s       r   GetResourcer9           r!   )rrtc                     g r7   r)   r8   s       r   r9   r9      r:   r!   c                     g r7   r)   r8   s       r   r9   r9      r:   r!   c                     US;  a  [        SU-  5      e[        XX#5      u  pEUc=  U(       d   eSU;  a	  U(       d  Sn[        XAX#S9 nUR                  5       nSSS5        U$ U$ ! , (       d  f       U$ = f)a  Get the file contents of the named resource.

Defaults to returning bytes, if you want str, then pass 'r' or 'rt' as the
mode argument. This function is thread-safe.

See also: WalkResources(), for finding what resources are available. e.g.
from a directory.

Args:
  name: The name of the resource. Example: google3/pyglib/resources.py
  mode: The file mode. GetResource only supports text read-only ('r' or 'rt')
    and binary read-only ('rb').
  encoding: The name of the encoding that the data will be decoded with if
    necessary. Defaults to locale.getpreferredencoding.
  errors: Optional string specifying how decoding errors are to be handled.
          https://docs.python.org/3/library/codecs.html#error-handlers

Returns:
  The contents of the named resource as a bytes object OR when text mode is
  specified (mode='r' or mode='rt') it is returned as a str.
Raises:
  IOError: if the name is not found, or the resource cannot be opened.
  ValueError: If the mode is not supported.
r;   r1   r<   Invalid mode: %rNbstrictr4   r5   )
ValueErrorFindResourceopenread)r2   r3   r4   r5   filenamedata	data_files          r   r9   r9      s}    > 
""
'$.
//!$h?8	\O8
$vf	hx	?9^^d 
@	++ 
@	?	+s   A%%
A4c                     g r7   r)   r8   s       r   GetResourceAsFilerM      r:   r!   )r<   r;   c                     g r7   r)   r8   s       r   rM   rM      r:   r!   c                     g r7   r)   r8   s       r   rM   rM      r:   r!   c                    US;  a  [        SU-  5      e[        XX#5      u  pEU=(       d    Uc   eU(       a  US:w  a	  U(       d  Sn[        XAX#S9$ US:X  a  [        R                  " U5      $ [        R
                  " U5      $ )a  Get the open file object to the named resource.

Defaults to returning BinaryIO, if you want TextIO, then pass 'r' or 'rt' as
the mode argument. This function is thread-safe.

See also: WalkResources(), for finding what resources are available. e.g.
from a directory.

Args:
  name: The name of the resource. Example: google3/pyglib/resources.py
  mode: The file mode. GetResource only supports text read-only ('r' or 'rt')
    and binary read-only ('rb').
  encoding: The name of the encoding that the data will be decoded with if
    necessary. Defaults to locale.getpreferredencoding.
  errors: Optional string specifying how decoding errors are to be handled.
          https://docs.python.org/3/library/codecs.html#error-handlers

Returns:
  The open file object to the named resource.
Raises:
  IOError: if the name is not found, or the resource cannot be opened.
  ValueError: If the mode is not supported.
r@   rA   r1   rC   rD   )rE   rF   rG   ioBytesIOStringIO)r2   r3   r4   r5   rI   rJ   s         r   rM   rM      s    : 
""
'$.
//!$h?8

d	''	't|FfAAt|::d;;tr!   c                    A[            [        R                  U 5      nU(       a#   [        R                  " US5        UsSSS5        $ [        U S5      u  p$U(       dH  Uc   e[        X5      n[        SU < SU< S35        [        U 5      nUb  [        R                  " X%5        SSS5        U$ ! [
         a)  nUR                  [        R                  :w  a  e  SnAOSnAff = f[        U 	 N! , (       d  f       W$ = f)aP  Get file name of the named resource within a par file.

Don't use this function if you can use one of the above functions
instead, because it's less efficient for resources in PAR files.

It may return the name of a temporary file if the resource doesn't
natively exist in the filesystem (i.e. part of a PAR file).

This function is thread-safe.

NOTE: This method might fail on diskless machines. See
go/borg-python-howto#resources_apis_that_write.

See also: WalkResources(), for finding what resources are available. e.g.
from a directory.

Args:
  name: The name of the resource. Example: google3/pyglib/resources.py. Must
    point to a file, not a directory.
  mode: Unused; only present for API compatibility.

Returns:
  The absolute path to the temporary file.
Raises:
  IOError if the name is not found, or the resource cannot be opened.
Nr1   z	Resource z1 does not already exist, writing it to temp file r   )_temporaries_lock_temporariesgetr   utimeOSErrorerrnoENOENTrF   _CreateTemporaryFiler    _ParGetPermissionschmod)r2   r3   rI   erJ   permissionss         r   GetResourceFilenamera   0  s    8 %H 	4  $ $D$/X%d1h
8 't,k		 
'9 < 
/+  77ell"
 #
 t
 < 
/s5   C-B/AC-/
C"9CC-C""
C--
C<c                  8   [         R                  5          [        (       a  [        [         R                  5         $ [        R
                  " 5       q[         R                  5         [        R                  [        R                  R                  4S[        S[        S[        [        /S4   S[        [        /[        [        [        4   4   4S jjn S[        [        /S4   S[        [        /[        4   S[        [        [        /S4   S	[        S
[        S[        [           4S jn[        R                   " U[        R"                  [        R                  R$                  U [&        R(                  [        [*        S9  [        $ ! [         R                  5         f = f)a+  Get the base temp directory used by GetResourceFilenameInDirectoryTree.

All files from a par file extract their files to a temporary directory,
depending on how you access a resource, the temp directory it ends up in
will differ.

GetResourceFilename files are extracted individually
GetARootDirWithAllResources are extracted to a different temp directory

This function is thread-safe.

NOTE: This method might fail on diskless machines. See
go/borg-python-howto#resources_apis_that_write.

Returns:
  The absolute path to the base temporary directory.
pathdirnamermdirNsplitc                     U" U 5        U R                  US-   5      (       d  g  U" U R                  S5      5      u  pU (       a  U R                  U5      (       d  g  U" U 5        MB  ! [         a     g f = fN/)
startswithrstriprY   )rc   rd   re   rf   unused_subdirs        r   SafeRemovedirs,GetResourceDirectory.<locals>.SafeRemovedirs  su     
$K??7S=)) 
!$++c"23d11d   s   A& &
A32A3unlink
removedirsenoent_error	directoryr'   c           
      
   U H  n U " U5        [        SU-  5        M     [        [        U Vs/ s H
  o" U5      PM     sn5      SS9 H  n	 U" X5        M      U" XD5        [        S	U-  5        g! [         a  n[        SU< SU< S35         SnAM  SnAff = fs  snf ! [         a*  nXs:w  a  [        SU	< SU< S35         SnAM   SnAM  SnAff = f! [         a  n[        SU< SU< S35         SnAgSnAff = f)
z.Deleted the directory from resource directory.# deleted resource tmpfile %s
# error deleting tmpfile : r   NT)reversez# error deleting tmpfile path z## deleted resource tmpdirectory %s
)r    EnvironmentErrorsortedset)
ro   rd   rp   rq   rr   r'   rI   r_   frc   s
             r   "DeleteResourceDirectoryresourceDir@GetResourceDirectory.<locals>.DeleteResourceDirectoryresourceDir  s     Bx.9:  s61GAJ67FE4# GA&
1I=>  BHa@AAB6  E
4C
D
D E  A
)Q?@@AsL   A2BB#C 2
B<BB#
C-CC
D$C==D)ro   rd   rp   rq   rr   r'   )_resource_directory_lockacquire_resource_directoryreleasetempfilemkdtempr   re   rc   rf   strr   r   	Exceptionr	   atexitregisterro   rd   rZ   r[   _resource_directory_files)rm   r|   s     r   GetResourceDirectoryr   t  s]   & ""$'  $$& #**,$$&$ &(XX02	 seTk" seU38_,-	(Aud{#As
#A C:t+,A 	A
 A #YA6 	//(YYggoo<<#% 
O $$&s   F F Fc                 B   A[         R                  R                  [        5       U 5      n[         R                  R	                  U5      (       a  U$ [         R                  R                  U5      n[         R                  R	                  U5      (       d   [         R                  " U5        [        U S5      u  pVUcP  U(       d   e[        US5       nUR                  5       nSSS5         [         R                  " U5      R                  nO[!        U 5      n["        R$                  " [         R                  R'                  U5      S9u  p[         R(                  " U	S5      n UR+                  U5        UR-                  5         Ub  [         R.                  " X5         [         R                  R	                  U5      (       a  [         R2                  " U
5        U$ [         R4                  " X5        [6        R9                  U5         U$ ! [         aN  nUR                  [        R                  :w  d$  [         R                  R                  U5      (       d  e  SnAGNSnAff = f! , (       d  f       GN= f! [         a    Sn GNlf = f! [0        [        4 a    [         R2                  " U
5        e f = f! [         ac    [         R                  R	                  U
5      (       a  [         R2                  " U
5        [         R                  R	                  U5      (       d  e  U$ f = f)a  Get the name of a file that contains the named resource.

The file is guaranteed to have the same name as the resource and be in the
same directory tree as the resource requested.

All files will be created under the directory returned by
GetResourceDirectory().

This function is thread-safe.

NOTE: This method might fail on diskless machines. See
go/borg-python-howto#resources_apis_that_write.

Args:
  name: The name of the resource. Example: google3/pyglib/resources.py
  mode: Unused; only present for API compatibility.

Returns:
  The absolute path to a file that contains the named resource.
Raises:
  IOError: If the name is not found, or the resource cannot be opened.
Nr1   suffixwb)r   rc   joinr   existsrd   makedirsrY   rZ   EEXISTisdirrF   rG   rH   statst_moder]   r   mkstempbasenamefdopenr   closer^   IOErrorremoverenamer   append)r2   r3   rI   rr   r_   resourcefilenamerJ   r{   r`   fdtmp_pathtmp_files               r   "GetResourceFilenameInDirectoryTreer     sQ   0 WW\\.0$7(WW^^HOggooh')			"	"kk) *$5	\		%VVXd 
&GG,-55k %T*K ##277+;+;H+EF.2YYr4 (
NN4NNhhx%
	ww~~hii 
/ 	ii#  &&x0 
/a  	
ELL	 i(@(@ )A 
&	%  k 7	 
IIh	
 
 	ww~~hii77>>(## $ 
/s\   H I!* I3 !:J :J1 +J1 
IAII!
I03JJ(J.1A)LLrJ   c           	         [            U [        ;  d   e[        R                  R	                  [        R                  R                  U 5      5      u  p#[        R                  R	                  [        R                  R                  [        R                  S   5      5      S   nSR                  X$5      n[        U[        5      (       a  SOSn[        R                  " XSSUS9 n UR                  U5        UR                  n S
S
S
5        W[        U '   S
S
S
5        [        R&                  W4S jn
[(        R*                  " U
5        U$ ! [         aQ  n	U	R!                  S[#        U5      S S	UR                   35        [        R$                  " UR                  5        e S
n	A	ff = f! , (       d  f       N= f! , (       d  f       N= f)a"  Create a temporary file with the specified contents.

The temporary file will be deleted at program finish.
This function is thread-safe.

Args:
  name: A name string to base the temporary file's name on.
  data: Bytes to be written to the temporary file.

Returns:
  An absolute filename.
r   z{}__py_binary_resource_{}__r   wF)prefixr   deleter3   zFailed to write ,z bytes to temporary file Nc                      U " U5        [        SU-  5        g! [         a  n[        SU< SU< S35         SnAgSnAff = f)zDelete file at program exit.rt   ru   rv   r   N)r    rx   )ro   rI   r_   s      r   Delete$_CreateTemporaryFile.<locals>.DeleteT  s@    @X
,x78 @
(A>??@s    
A<A)rU   rV   r   rc   splitextr   r   r   format
isinstancebytesr   NamedTemporaryFiler   r2   rx   add_notelenr   ro   r   r   )r2   rJ   	file_namer   py_binary_namer   r3   r{   rI   r_   r   s              r   r\   r\   0  s[    |###(()9)9$)?@IWW%%bgg&6&6sxx{&CDQGN*11)LFdE**4D		$	$U
	
	66
 "L' , II @ 	//&	/'  	

s4ym+DQVVHM	
 			!&&
 
 sC   CF7"F&$EF7
F#AFF##F&&
F4	0F77
Gscope	attributec                     [        XS5      SL$ )zAChecks that a given attribute exists and is initialized properly.N)getattr)r   r   s     r   _AttributeIsInUser   a  s    	4	(	44r!   c                  6    [        5       R                  SS5      $ )z;Returns the python module __loader__ active for this scope.
__loader__N)globalsrW   r)   r!   r   
_GetLoaderr   f  s    	|T	**r!   loaderc                 ,    U =(       a    [        U S5      $ )N_parr   r   s    r   _IsClassicBootstrapr   k  s    		5%ff55r!   c                 ,    U =(       a    [        U S5      $ )Nparr   r   s    r   _IsModernBootstrapr   o  s    		4%fe44r!   c                     [        U 5      =(       d2    [        U 5      =(       d     [        U 5      =(       d    S[        U 5      ;   $ )N
FakeLoader)r   r   _IsHermeticParLoaderr   r   s    r   _IsParLoaderr   s  s<    &! %	F	#%	f	%% 
V	$	r!   c                  :    [         (       a  [         R                  $ g)z5Returns True if we are running under Hermetic Python.F)r   is_google3_python_launcherr)   r!   r   UsingPythonLauncherr     s    ^444	r!   c                 ^    U (       d  g[         (       d  g[        U [         R                  5      $ )NF)_elfzipimportr   ElfZipImporterr   s    r   r   r     s#    			FM88	99r!   c                  t    [         c,  [        5       n [        U 5      (       d   eU R                  5       q [         $ r7   )_hermetic_par_zipfiler   r   get_zipfiler   s    r   _GetHermeticParZipFiler     s5    "\F''''"..0	r!   parfilepathlikec                     [         R                  " U5      nU S-  n UR                  U 5      (       a  U[        U 5      S  nU$ rh   )r   fspathrj   r   )r   r   rc   s      r   _NormalizeFilenamer     s=    	8	$	S.'	__WGD	+r!   zip_file	predicaterc   c                     U R                  5        HY  nU" UR                  5      (       d  M  U R                  X2S9nUR                  S-	  nU(       d  MC  [        R
                  " XE5        M[     g)zGExtract predicate-defined files to the path, and set permissions right.)rc      N)infolistrI   extractexternal_attrr   r^   )r   r   rc   inforI   r3   s         r   _ExtractZipFiler     s_     !dT]]##0H #Dthhx "r!   c                    [        5       n[        R                  " U 5      n U(       Ga  [        U5      (       aK  UR	                  U 5      n  UR
                  R                  R                  U 5      R                  S-	  [        -  $ [        U5      (       aD  UR	                  U 5      n UR                  R                  U 5      nUb  UR                  [        -  $  g[        U5      (       aF  [	        UR                   U 5      n [#        5       n UR                  U 5      R                  S-	  [        -  $ g! [         a     gf = f! [         a     gf = f)af  Get the file permissions of the given file.

Returns an integer containing the permissions or None if they can't be
acquired.

This function does not modify global state, so it is thread-safe.

Args:
  name: The name of the resource. Example: google3/pyglib/resources.py

Returns:
  An integer containing the permissions or None if they can't be
  acquired.
r   N)r   r   r   r   r   r   	_zip_filegetinfor   
_OCTAL_777KeyErrorr   r   StoredResourcer`   r   archiver   )r2   r   resourcer   s       r   r]   r]     s8    <&	4$6"" &&t,d KK!!))$/==C 	 
F	#	#&&t,d**40h		##j00 
 
 
f	%	%5d')h%33r9JFF 
!    s$   8D/ 	$D? /
D<;D<?
EErootc                 J   [         R                  R                  U 5      n [         R                  R                  U5      (       d  [         R                  R	                  X5      n[         R                  R                  U5      n[         R                  R                  X/5      U :H  $ )a{  Determine whether resource path is contained within root.

This purposefully ignores symbolic links as resources are typically
symlinked into /build/cas/... which is outside "root".

Args:
  root: The path in which the resource is expected to be found.
  path: A resource path.

Returns:
  True if "path" is a relative path or if it is an absolute path
  pointing within "root".
)r   rc   abspathisabsr   normpathcommonprefix)r   rc   s     r   
_IsSubPathr     sk     
	$	t		77<<#D			$	$			tl	+t	33r!   c                     g r7   r)   r8   s       r   rF   rF     r:   r!   c                     g r7   r)   r8   s       r   rF   rF     r:   r!   c                     g r7   r)   r8   s       r   rF   rF     r:   r!   c           	      p
   [         R                  R                  U 5      n [        5       n[        R
                  S:X  a  SnO[        U5      nU(       a  [        US5      (       a  U(       a   [           UR                  U 5      nSSS5        [        W[        5      (       a>  SU;  a8  UR                  U=(       d    [        R                  " S5      U=(       d    S5      n[        SU -  5        SU4$ [#        [$        5      u  pU(       ak  ['        X5      (       a[  [         R                  R)                  X5      n
[         R                  R+                  U
5      (       a  [        SU < SU
< S35        U
S4$ U	(       ak  ['        X5      (       a[  [         R                  R)                  X5      n
[         R                  R+                  U
5      (       a  [        SU < SU
< S35        U
S4$ S[        R,                  ;   a  [        R,                  S   n[/        USS5      nU(       a~  ['        X5      (       an  [         R                  R)                  X5      n
[         R                  R+                  U
5      (       a  [        SU < SU
< S35        U
S4$ [        S	U < SU< 35        [         R0                  R3                  SS5      nU(       a~  ['        X5      (       an  [         R                  R)                  X5      n
[         R                  R+                  U
5      (       a  [        SU < SU
< S35        U
S4$ [        S	U < SU< 35        U R5                  S5      (       a  U S4$ SnSnU nUc  U(       d  UR7                  S5      (       d  [         R                  R9                  U5      u  pUb   [         R                  R)                  X5      nOUnUS:X  a   [         R                  R)                  US5      nUc  U(       d  UR7                  S5      (       d  M  Ubk  ['        X5      (       a[  [         R                  R)                  X5      n
[         R                  R+                  U
5      (       a  [        SU < SU
< S35        U
S4$ [         R                  R;                  U 5      (       a8  U [<        R?                  5       ;   a  [        SU -  5        U S4$ [        SU -  5        [!        [@        RB                  SU 5      e! , (       d  f       GNz= f! [          a"  n[        S	U < S
U< SU< 35         SnAGN?SnAff = f)ax  Search for a named resource.

Returns a tuple of (filename, file contents as string), where at
least one element is not None, depending on the abilities of the
entity where the resource was found.  E.g. resources from PAR files
don't have independent filenames.

This function is thread-safe.

Args:
  name: The name of the resource. Example: google3/pyglib/resources.py
  mode: The mode to use for opening the file. This behaves the same way as the
    'mode' argument of __builtins__.open(), where 'b' must be supplied to get
    bytes.
  encoding: The name of the encoding that the data will be decoded with if
    necessary. Defaults to locale.getpreferredencoding.
  errors: Optional string specifying how decoding errors are to be handled.
          https://docs.python.org/3/library/codecs.html#error-handlers

Returns:
  A tuple of (filename, file contents as string/bytes), where at
  least one element is not None, depending on the abilities of the
  entity where the resource was found.  E.g. resources from PAR files
  don't have independent filenames.
Raises:
  IOError: If the name is not found, or the resource cannot be opened.
win32Tget_dataNrB   FrC   z%# loading resource %s via __loader__
z# resource z not found by loader rv   z# loading resource z from z via __file__ (non-READONLY)
z via __file__ (READONLY)
sitecustomize
GOOGLEBASEz via sitecustomize
z not found via sitecustomize z via GOOGLEBASE
z not found in GOOGLEBASE z../READONLYri   r   READONLYz via srcfs READONLY
z# UNSUPPORTED LEGACY USAGE: loading resource from previously extracted file. resources.py is only expected to handle google3 resource paths. That is an absolute path you should open with gfile instead: %s
z># discarding absolute path not pointing to known resource: %s
zResource not found)"r   rc   r   r   r   platformr   r   _RESOURCE_LOCKr   r   r   decodelocalegetpreferredencodingr    r   _DeriveRootPathFromThisFile__file__r   r   isfilemodulesr   environrW   rj   endswithrf   r   rV   valuesrZ   r[   )r2   r3   r4   r5   r   is_parrJ   r_   r   readonly_rootrI   r   readonly_pathresource_nameheadtails                   r   rF   rF   #  s   D 
		$	$ <&\\W F&!F!&*55&
Kt$ 	D%	 	 S_{{:33E:F<Nh
 3d:;D\ 4H=$ 
j$$ww||D'H	ww~~h
8  z-66ww||M0H	ww~~h
8  #KK0M=,5D
4&&d)h		!	!X	
 $tTJK 
d	+$	j$$ww||D'H	ww~~h
tXNO
tDE 
__]##$< --	$ 	d4==3E3E77==&LT ggll47mmyggll44m 	d4==3E3E :m#K#Kww||M9H	ww~~h
8  WW]]4 |""$$
  #'' D\

K
 	2D99u >  K
vqIJJKs1   ,T	 2S7A,T	 7
TT	 	
T5T00T5c            	           \ rS rSrSrS\\   SS4S jrS\S\\	\\\   \\   4      4S jr
S	\S\\\\4      4S
 jrSrg)
_FileIndexi  zA structure for holding a tree of files.

This index is used internally by resources.py to help implement an os.walk
style API.
	filenamesr   Nc                     0 U l         U Hc  nUR                  S5      R                  S5      nU(       d  M,  U R                   nUSS  H  nXT;  a  0 XE'   XE   nM     US   nU(       d  M_  SXB'   Me     g)zCreates a file index from a list of file paths.

Args:
  filenames: A list of strings like 'dir1/dir2/somefile'. An empty directory
    can be expressed as 'dir1/dir2/'. This is the same as the output of
    ZipFile.namelist().
ri   N)_dictlstriprf   )selfr  rI   
componentsd	components         r   __init___FileIndex.__init__  sx     "$DJ??3'--c2jzza!#2)!,L ' Bh	 r!   topc           	   #     ^#    S[         [        [        4   S[        [        [        [
        [           [
        [           4      4U4S jjmU R                  U5      nUb$  T" UR                  S5      U5       H  nUv   M	     gg7f)z&Walks the directory tree like os.walk.r  r   c              3   :  >#    / n/ n[        UR                  5       5      nU H,  u  pVUb  UR                  U5        M  UR                  U5        M.     XU4v   U H;  u  pVUc  M
  T" [        R                  R                  X5      U5       H  nUv   M	     M=     g7f)zYield 3-tuples for a directory.N)ry   itemsr   r   rc   r   )	r   r  dirnamesr  r  kventry
ProcessDirs	           r   r   #_FileIndex.Walk.<locals>.ProcessDir  s      hiQWWYe$!=
//!



1
	 
 y))$!=!"'',,v"91=eK > s   AB%6BNri   )r   r   r   r   r   r	   _LookupPathstrip)r  r  r  r  r   s       @r   Walk_FileIndex.Walk  sv     S>	%T#YS	12	3$ 	A}ciina0% 1 s   BBrc   c                     UR                  S5      nUS   (       d  USS nU R                  nU H  nXC;  a    gX4   nM     U$ )z5Returns a directory entry from self._dict for a path.ri   r  N)rf   r  )r  rc   r  r  r  s        r   r"  _FileIndex._LookupPath	  sM    CJ b>cr?j

A			
,a   Hr!   )r  )__name__
__module____qualname____firstlineno____doc__r	   r   r  r   r   r$  r   r   r   r"  __static_attributes__r)   r!   r   r  r    sj    S	 d 4c huS$s)T#Y-F'GH 4c htCH~&> r!   r  path_prefixiterablec              #      #    U HA  u  p#nUR                  U 5      (       d  [        SU< SU < 35      eU[        U 5      S  X44v   MC     g 7f)Nzpath z doesn't start with prefix )rj   rE   r   )r.  r/  dirpathr  r  s        r   _TrimPathPrefixFromWalkIterabler2    sV      '/"gk**4;[
I  #k"$
%x
:: '/s   A	Ac                 2   [        5       nU(       ab  U[        R                  [        5      S   :X  aB  [        R
                  R                  X5      n[        US-   [        R                  " U5      5      $ [           [        (       dF  [        5       R                  SS5      nU(       a%  [        US5      (       a  [        [        U5      5      q
SSS5        [        (       a  [        R!                  [#        U 5      5      $ [%        / 5      $ ! , (       d  f       NB= f)au  Walks the directory tree of resources similar to os.walk.

This can be useful for finding files within a directory when they aren't
all known ahead of time (e.g., a glob(testdata/*) situation).

Args:
  path: A string like 'google3/pyglib'.

Returns:
  An iterator of 3-tuples (dirpath, dirnames, filenames). For example:
  ('google3/pyglib', ['tests'], ['resources.py']).
r   ri   r   Nr   )GetRunfilesDirr   
rpartition_GOOGLE3_STRr   rc   r   r2  walkr   _par_file_indexr   rW   hasattrr  _ListAllFilesr$  r   iter)rc   runfiles_dirabs_pathr   s       r   WalkResourcesr>  '  s      !, lh&9&9,&G&JJww||L/H*sBGGH- 
 ?y}}\40f	GFJ//$]6%:;  _D	**	b/ ~s   :AD
Dthis_filenamec                 (   SnSnU (       Ga  [         R                  R                  [         R                  R                  [         R                  R                  U 5      5      5      n[         R                  R                  U5      nS[         R                  R	                  U5      :X  ai  Un[         R                  R	                  U5      S:X  a$  Un[         R                  R                  U5      nX!4$ [         R                  R                  US5      nX!4$ )a@  Get the root and READONLY root path of this Piper client.

Args:
  this_filename: The complete path to this file (resources.py).

Returns:
  A tuple of the root path and READONLY root path of this Piper client,
  assuming it is a client at all.  Callers should test their presence on the
  filesystem before using them.
Nr   r   )r   rc   rd   r   r   r   )r?  r  r   google3_dirtentative_roots        r   r   r   K  s     -	$ ''//
67K WW__[1NBGG$$[11d			$	:	-wwt$ 
	 T:6		r!   c                      [         R                  S   n SU ;   d  [        5       (       a  [        5       (       d  [        n [        [        R                  R                  U 5      5      $ )a  Get the runfiles directory.

Note: this function only looks for the runfiles dir of a google3
program run from a google3/... subtree. It will not return the
similarly-named <name>.runfiles directory created by the PAR
extractor when running a PAR file. (This means that when called
from a PAR file, it might return the runfiles from a containing
google3 program. Please do not rely on this.)

Returns:
  The runfiles directory for the currently-running program.
r   z/org.python.pydev)	r   r   r   _RunningInsideParFiler   FindRunfilesDirr   rc   r   )starting_points    r   r4  r4  l  sI    B 88A;.^+$9$;$;N	8	99r!   program_filenamec                    S[         S[        [         [         4   4S jnU R                  [        5      nUS:w  a  U SU nX[	        [        5      -   S nU" U5      u  pT[
        R                  R                  U5      S   n[
        R                  R                  USXVS-   5      n[
        R                  R                  U5      (       a  U$ U$ g)	aK  Look for a runfiles directory corresponding to the given program.

We assume that program name is like one of:
 1) <root>/google3/<package>/<file>.<extension>
    - or -
    <root>/google3/bin/<package>/<file>.<extension>
    Runfiles :=  <root>/google3/bin/<package>/<file>.runfiles
 2) <root>/google3/linux-dbg/<package>/<file>.runfiles/google3/\
    <package2>/<file>.py
    Runfiles :=  <root>/google3/linux-dbg/<package>/<file>.runfiles

Args:
  program_filename: absolute path to a Google3 Python program
Returns:
  The path to the runfiles directory, or None if one wasn't found.
rI   r   c                 R   S H?  nU[         R                  -   nU R                  U5      (       d  M.  U [        U5      S n X4s  $    [         R                  R                  [        R                  S   5      R                  [         R                  5       H  nUS;   d  M  X04s  $    SU 4$ )ay  Find a match for the binary filename and its path.

If the binary directory isn't known, search the program's
filename for a binary directory.

Args:
  filename: The name of the binary file.

Returns:
  A tuple of the binary directory, and the filename relative to that
  directory.
  If the binary directory isn't known, search the program's
  filename for a binary directory
)binz	blaze-binNr    )	r   seprj   r   rc   r   r   r   rf   )rI   bindir
bindir_sepelems       r   _GetBinaryDirectoryFilename4FindRunfilesDir.<locals>._GetBinaryDirectoryFilename  s      'BFF?j			Z	(	(C
O-.	 ' ,22266:	%	%~ ; x<r!   r  Nr   r   z	.runfiles)
r   r   rfindr6  r   r   rc   r   r   r   )rG  rP  google3_idxroot_dirrel_filenamerM  rel_filename_noextrunfiless           r   rE  rE    s    $C E#s(O 8 !&&|4+B-H##l2C$C$EFL6|DF)),7:ww||)V+%EH 
ww}}XoOr!   c                      [        5       n U (       d  g[        U 5      =(       d    [        U 5      =(       d    [        U 5      $ )a  Determine if we are executing within a par file or not.

DO NOT USE, PLEASE.  You don't need it and you don't want to have your
program depend on par run context. Use the other methods in this module
to make your code work anywhere, not special modes based on this hack
to hack your own stuff.

Note that there is a public version of this in //pyglib:parinfo if you won't
be dissuaded.

Returns:
  boolean value: True if we are running inside a par file.
F)r   r   r   r   r   s    r   rD  rD    s8     <&	&! &	F	#&	f	%r!   c                 H   [        U 5      (       a  U R                  R                  5       $ [        U 5      (       a-  [	        U R
                  R                  R                  5       5      $ [        U 5      (       a  U R                  5       R                  5       $ [        SU -  5      e)z7Attempt to get a python archive from the module loader.Unknown .par module loader: %r)r   r   NameListr   ry   r   r&   keysr   r   namelistNotImplementedErrorr   s    r   r:  r:    s       ;;!!&!!&**&&++-..F##((**
>G
HHr!   c                     g)N   r)   )xs    r   <lambda>rb    s    ar!   Ffilename_predicateskip_previous_extraction_checkc                   ^ ^^ [        T [        5      (       a	  T mU4S jm O[        T 5      (       d  [        ST < 35      eS[        4U U4S jjn[        (       a  T(       d  [        $ [        5       (       a  [        (       a  T(       a  U" 5       q[        $ [        5       nU(       d  [        S5      eU[        R                  [        5      S   :X  a  Uq[        $ [        S5      e)a  Get a root directory containing all the resources matching a predicate.

Tries the following steps and returns at the first successful step
  * Returns a root dir previously found/extracted by this function and cached.
    This check can be skipped with skip_previous_extraction_check.
  * If this program is a par file, extract all files out of it into a temp
    tree and return its root. The temp tree is automatically cleaned on exit
    unless the process is terminated with an unhandled signal (i.e., SIGTERM
    or SIGKILL).
  * If this program is a google3 target built in a standard google3
    client tree, find and return the runfiles directory built with it.

NOTE: This function returns "a" root dir with all the resources and
not "the" root dir. It is not necessary that the directory returned
by this function is the one that will be used by GetResource...() functions
in this module to find resources. If the executable is a par file, the first
call to this function may lead to an expensive extraction of files from the
par file into a new directory.

NOTE: This method might fail on diskless machines. See
go/borg-python-howto#resources_apis_that_write.

Args:
  filename_predicate: Callable predicate used to filter which files are
    extracted from the par file, or a string that should be the prefix of all
    paths.
  skip_previous_extraction_check: Performs the extraction even if it has been
    done before. This is useful when using different filename_predicates in
    successive calls.

Returns:
  root: Path to root directory.

Raises:
  OSError: if an error occurs, such as disk full or unable to find the correct
    directory.
  NotImplementedError: If used with unsupported .par startup code.
c                 &   > U R                  T5      $ r7   )rj   )rc   r.  s    r   rb  -GetARootDirWithAllResources.<locals>.<lambda>)  s    dook&Br!   z1filename_predicate must be callable or str, got: r   c                    > [        5       n [           [        U 5      (       aa  [        R                  " SS9n U R
                  R                  TSU5        [        R                  " [        R                  USS9  UsSSS5        $ [        U 5      (       a#  U R                  R                  TTS9sSSS5        $ [        U 5      (       aY  [        R                  " SS9n [!        [#        5       TU5        [        R                  " [        R                  USS9  UsSSS5        $ [%        SU -  5      e! [         a    [        R                  " USS9  e f = f! [         a    [        R                  " USS9  e f = f! , (       d  f       g= f)	z*Extract the par file to a local directory.z__unpar__.runfilesr   fileT)ignore_errorsN)extraction_predicateforce_extractrZ  )r   r   r   r   r   r   _ExtractFilesrx   shutilrmtreer   r   r   r   +ExtractMultipleResourcesByPredicateIfNeededr   r   r   r^  )r   r   rc  rd  s     r   '_ExtractParFileResourcesUnconditionallyLGetARootDirWithAllResources.<locals>._ExtractParFileResourcesUnconditionally0  sS   \F		V	$	$ ';<	
++
#
# &$ 	t4@ 
  f%% zzEE!38 F 
' 
.  '' ';<	
024F
M 	t4@E 
J ""BV"KLL7   	
--D
1
	(   	
--D
1
	= 
sL   %E6D.%E6)E67$E6E1%E6 E6.!EE6!E33E66
Fz*The runfiles directory could not be found.r   z@Could not create or find the directory containing all resources.)r   r   callablerE   _extracted_root_dirrD  r4  rY   r   r5  r6  )rc  rd  rq  r<  r.  s   ``  @r   GetARootDirWithAllResourcesru    s    T "C(($KB&''
	!	# 
(M3 (M (MZ !? "@CE  !,	
>
??X((6q99&H	 r!   c                     [         [        L a  [        5       n U (       a  [        U 5      (       a:  U R                  R                  5         U R                  R                  5       q [         $ [        U 5      (       a   U R                  R                  5       q [         $ [        U 5      (       a  [        5       q [         $ Sq  [         $ Sq [         $ )aH  Extracts all files if running as par file.

WARNING: This function will fail with permission errors when run on Borg.
You should probably call resources.GetARootDirWithAllResources() instead.

This function only tries to extract files once. Subsequent calls return value
cached from previous runs.

NOTE: This method might fail on diskless machines. See
go/borg-python-howto#resources_apis_that_write.

Returns:
  a string, runfiles directory, or None if an error happened or if not
  running as par file.
Raises:
  Will raise exceptions if zipimport implementation raises something.
N)_par_extract_all_files_cache_UNINITIALIZEDr   r   r   _ExtractAllFiles_SetAndGetRunfilesRootr   r   rp  r   ru  r   s    r   ParExtractAllFilesr{  {  s    & "^3\F	V	$	$ 	$$&'-{{'I'I'K$ 
&% f%% JJBBD 	% 
&%  '' (C'D$
 
&% (,$ 
&% &*"	%%r!   c                     g r7   r)   rc   r3   argskwargss       r   _ParOpenr         r!   c                     g r7   r)   r}  s       r   r  r    r  r!   c                     g r7   r)   r}  s       r   r  r    r  r!   c                   ^ [         R                  R                  U 5      n U R                  [        5      (       d  [        U T/UQ70 UD6$ [        U4S jS 5       5      (       a  [        [        R                  SU -  5      eU [        [        5      S n[        U5      nST;   a  U$ [        R                  " XSR                  SS5      S9$ )ae  Internal method for opening a par file.

Args:
  path: Path to the par file.
  mode: file mode for opening the file.
  *args: Other argments to apply to the Open command.
  **kwargs: Keyword arguments to apply to the open command.

Returns:
  A file handle to the par file.
Raises:
  IOError: If the parfile is not writable, should write mode be specified.
c              3   ,   >#    U  H	  oT;   v   M     g 7fr7   r)   ).0write_indicatorr3   s     r   	<genexpr>_ParOpen.<locals>.<genexpr>  s     H_D	 s   )r   a+zParfiles are not writable: %rNrB   newline)r  )r   rc   r   rj   _PAR_PREFIX_BUILTIN_OPENanyr   rZ   EROFSr   rM   rQ   TextIOWrapperrW   )rc   r3   r~  r  relative_pathfps    `    r   r  r    s      
	$		%	%t5d5f55 	HHHH
%++>E
FFs;')*-'"D[I			"jjD&A	BBr!   c                     [         b  g[        5       n [        U 5      (       a  U R                  R                  nOE[        U 5      (       a  U R                  R                  nO[        U 5      (       a  U R                  nOg[        R                  R                  U5      S-   q [        R                  q[         [        l        g)a  Install an open that also works for files inside a par.

It is highly recommended that this only be called by the main file of a
py_binary and not from a py_library.

Once this method is called, you can take a path to inside your par file:

    path = os.path.join(os.path.dirname(__file__), ...)
    # path = "/path/to/my.par/google3/whatever"

and open it like any regular file:

    fp = open(path)
Nri   )r  r   r   r   r2   r   r   _zip_filenamer   r   r   rc   r   builtinsrG   r  r  )r   par_names     r   InstallParOpenr    s    " 
<&zzH6""{{((HF##~~H )C/+---(-r!   c                  ^    [         R                  [        :X  d   e[        [         l        S qS qg r7   )r  rG   r  r  r  r)   r!   r   _UninstallParOpenForTestingOnlyr    s'     
(	""	"(--+r!   )r   r#   )r1   NN)r<   NN)r1   )r;   NN)r;   )r   N)fr,  r   r  rZ   	functoolsimportlib.abcr%   importlib.resourcesrQ   r   r   rn  r   r   	threadingtypingr   r   r   r   r   r   r	   r
   r   r   r   r   zipfiler   _Pathr  rW   r   r  r   flagsverboser  r   r   rL  r6  MetaPathFinderr    	lru_cacher*   r.   version_infooverloadr   r9   rM   rV   RLockrU   ra   r   Lockr~   r   r   r   r\   boolr   r   r   r   r   r   r   r   ZipFiler   r   r   intr]   r   r   rF   r  r8  r2  r>  r   r4  rE  rt  rD  r:  ru  objectrx  rw  r{  r  r  r  r  r  r)   r!   r   <module>r     s	  F       	  	  
    s s s s 
 	c%%&
 !12."7"7-
 II -	zz~~oq)-	zz~~(!, 
 
vv	!BFF*
Kc Kd K
 T"5 #51& 1&5 1&h g	  " 	

$- sm SM	
     $" 	

)
 sm SM	
 	   " 	

 sm SM	
 5#:  " 	)
)
) sm) SM	)
 5#:)X  " 	

$- sm SM	
     $" 	

)
 sm SM	
    " 	

 sm SM	
 8V  " 	)
)
) sm) SM	)
 8V)Z OO% ;e ;3 ;# ;|  $>>+  ac aHUU U# U Up.u .E%*,= .# .b5S 5S 5T 5
+N +
6 64 65~ 5$ 5 D T   : :D :  u  oo*2C5$;*?GL	*,U ,x} ,b !4U 4% 4D 4*   #" 	

)
 sm SM	
 5dU49--.   " 	

$- sm SM	
 5dU4;//0   " 	

 sm SM	
 5dU4;//0  " 	h:
h:
h: smh: SM	h:
 5dU4ucz):#:;;<h:VH HV ;; (sDItCy/H)I J;! !(5d3ic1J+K"L !H
8C=(3-'(B&: &:R;c ;hsm ;|  t 0IT#Y I  =H+0uc8SE4K#889u$(u 	ut - )&HSM )&X  ,/
y)  '+
t}   

8V  !C
CC
8VC@#Lr!   