o
    bO                     @   sj  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 dl
Z
G dd deZG dd deZdd	 Zd
d Zdd Zdd Zdd Zdd Zdd Zed=ddZed>ddZdd Zdd ZedZed Zd!d" Zd#d$ Zd%d& Zd'd( Z d)d* Z!d+d, Z"d-d. Z#d/d0 Z$i fd1d2Z%d>d3d4Z&G d5d6 d6eZ'G d7d8 d8eZ(d9d: Z)d;d< Z*dS )?    )with_statement)
MutableSetNc                   @   s   e Zd Zdd Zdd ZdS )memoizec                 C   s   || _ i | _d S N)funccache)selfr    r	   ,/usr/lib/python3/dist-packages/gyp/common.py__init__   s   
zmemoize.__init__c                 G   s8   z| j | W S  ty   | j| }|| j |< | Y S w r   )r   KeyErrorr   )r   argsresultr	   r	   r
   __call__   s   

zmemoize.__call__N)__name__
__module____qualname__r   r   r	   r	   r	   r
   r      s    r   c                   @   s   e Zd ZdZdS )GypErrorzError class representing an error, which is to be presented
  to the user.  The main entry point will catch and display this.
  N)r   r   r   __doc__r	   r	   r	   r
   r      s    r   c                 C   sj   | j s	|f| _ dS t| j dkrt| j d d | f| _ dS t| j d d | f| j dd  | _ dS )z2Append a message to the given exception's message.   r    N)r   lenstr)emsgr	   r	   r
   ExceptionAppend&   s
   ,r   c                    s    fdd|D S )zc
  Given a list of qualified targets, return the qualified targets for the
  specified |target|.
  c                    s    g | ]}t |d   kr|qS )r   ParseQualifiedTarget).0ttargetr	   r
   
<listcomp>5   s     z(FindQualifiedTargets.<locals>.<listcomp>r	   )r!   qualified_listr	   r    r
   FindQualifiedTargets0   s   r$   c                 C   sV   |  dd}t|dkr|\}} nd }|  dd}t|dkr$|\} }nd }|| |gS )N:r      #)rsplitr   )r!   target_split
build_filetoolsetr	   r	   r
   r   8   s   


r   c                 C   sb   t |\}}}|r(| r&tjtjtj| |} tj| s%t| d} n|} |r,|}| ||gS )N.)r   ospathnormpathjoindirnameisabsRelativePath)r*   r!   r+   parsed_build_fileparsed_toolsetr	   r	   r
   ResolveTargetK   s   


r6   c                 C   s   t | d S Nr   r   )fully_qualified_targetr	   r	   r
   	BuildFilem      r9   c                 C   s&   | D ]}|t jv rt j|   S q|S )zpLook up a key in the environment, with fallback to secondary keys
  and finally falling back to a default value.)r-   environ)var_listdefaultvarr	   r	   r
   GetEnvironFallbackr   s
   
r?   c                 C   s    | d | }|r|d | }|S )Nr%   r'   r	   )r*   r!   r+   fully_qualifiedr	   r	   r
   QualifiedTarget{   s   rA   Tc                 C   s   |r	t j| } nt j| } t j|}tjdkr0t j| d  t j|d  kr0| S | t jj	}|t jj	}t
t j||g}t jjgt
||  ||d   }t
|dkradS t jj| S )Nwin32r    )r-   r.   realpathabspathsysplatform
splitdrivelowersplitsepr   commonprefixpardirr0   )r.   relative_tofollow_path_symlink
path_splitrelative_to_split
prefix_lenrelative_splitr	   r	   r
   r3      s$   

r3   c                 C   s,   | s| S |du r
dn|}t |tj|| S )a  Given a path like foo/bar that is relative to toplevel_dir, return
  the inverse relative path back to the toplevel_dir.

  E.g. os.path.normpath(os.path.join(path, InvertRelativePath(path)))
  should always produce the empty string, unless the path contains symlinks.
  Nr,   )r3   r-   r.   r0   )r.   toplevel_dirr	   r	   r
   InvertRelativePath   s   rU   c                 C   s   t j| r| S t| |S r   )r-   r.   r2   r3   )r.   rN   r	   r	   r
   FixIfRelativePath   s   
rV   c                 C   s"   t j|}t jt j|| S r   )r-   r.   r1   r/   r0   )r.   rN   rel_dirr	   r	   r
   UnrelativePath   s   rX   z[	
 #$%&'()*;<=>?[{|}~]|^$z(["\\`])c                 C   s@   t | ts	t| } t| rd}nd}|ttd|  | }|S )a  Encodes |argument| suitably for consumption by POSIX shells.

  argument may be quoted and escaped as necessary to ensure that POSIX shells
  treat the returned value as a literal representing the argument passed to
  this function.  Parameter (variable) expansions beginning with $ are allowed
  to remain intact without escaping the $, to allow the argument to contain
  references to variables to be expanded by the shell.
  "rC   z\\\1)
isinstancer   _quotesearchresub_escape)argumentquoteencodedr	   r	   r
   EncodePOSIXShellArgument  s   


rc   c                 C   s&   g }| D ]	}| t| qd|S )zEncodes |list| suitably for consumption by POSIX shells.

  Returns EncodePOSIXShellArgument for each item in list, and joins them
  together using the space character as an argument separator.
  r   )appendrc   r0   )listencoded_argumentsr`   r	   r	   r
   EncodePOSIXShellList  s   
rg   c                 C   sv   t  }t |}|r3| }||v rq|| | | }|t |dg  |t |dg  |s	t|t | S )z2Returns the recursive list of target dependencies.dependenciesdependencies_original)setpopaddupdategetre   )target_dictsrootsrh   pendingrspecr	   r	   r
   DeepDependencyTargets(  s   
rt   c                    s    fdd| D S )zHFrom a target_list, returns the subset from the specified build_file.
  c                    s   g | ]
}t | kr|qS r	   )r9   )r   pr*   r	   r
   r"   >  s    z$BuildFileTargets.<locals>.<listcomp>r	   )target_listr*   r	   rv   r
   BuildFileTargets;  s   rx   c                 C   s   t | |}t||}|| S )zNReturns all targets (direct and dependencies) for the specified build_file.
  )rx   rt   )rw   ro   r*   	bftargets
deptargetsr	   r	   r
   
AllTargetsA  s   

r{   c                    s   G  fdddt }| S )zWrite to a file only if the new contents differ.

  Arguments:
    filename: name of the file to potentially write to.
  Returns:
    A file like object which will write to temporary file and only overwrite
    the target if it differs (on close).
  c                       s0   e Zd ZdZ fddZdd Z fddZdS )	zWriteOnDiff.<locals>.Writerz?Wrapper around file which only covers the target if it differs.c                    sd   t jdtj d d tj d d\}| _z
t|d| _W d S  ty1   t	| j  w )Nz.tmpr   z.gyp.r   )suffixprefixdirw)
tempfilemkstempr-   r.   rJ   tmp_pathfdopentmp_file	Exceptionunlink)r   tmp_fdfilenamer	   r
   r   U  s   z$WriteOnDiff.<locals>.Writer.__init__c                 S   s   t | j|S r   )getattrr   )r   attrnamer	   r	   r
   __getattr__b  r:   z'WriteOnDiff.<locals>.Writer.__getattr__c              
      s   zd| j   d}z
t| j d}W n ty+ } z|jtjkr! W Y d }~nd }~ww |r7t	| j W d S t
d}t
| t| jd| @  tjdkr[tj r[t  t| j  W d S  tyr   t	| j  w )NF?   i  rB   )r   closefilecmpcmpr   OSErrorerrnoENOENTr-   r   umaskchmodrF   rG   r.   existsremoverenamer   )r   samer   r   r   r	   r
   r   f  s.   



z!WriteOnDiff.<locals>.Writer.closeN)r   r   r   r   r   r   r   r	   r   r	   r
   WriterS  s
    r   )object)r   r   r	   r   r
   WriteOnDiffI  s   
<r   c                 C   s.   zt t j|  W dS  ty   Y dS w )z*Make sure the directory for |path| exists.N)r-   makedirsr.   r1   r   )r.   r	   r	   r
   EnsureDirExists  s
   r   c                 C   s   dddd}d| v r| d S t j|v r|t j S t jdr dS t jdr(dS t jdr0dS t jd	r8d	S t jd
r@d
S t jdrHdS t jdrPdS dS )zFReturns |params.flavor| if it's set, the system's default flavor else.winmac)cygwinrB   darwinflavorsunossolarisfreebsdopenbsdnetbsdaixzosos390linux)rF   rG   
startswith)paramsflavorsr	   r	   r
   	GetFlavor  s.   

r   c              	   C   s  ddddd | d}|sdS tjtjtjtd| }t|}| }W d   n1 s3w   Y  d}| dd}| dkrL|rL|d	| 7 }tj|d
| }	t|	d}
|
	d|d |g|dd   W d   n1 sww   Y  t
|	d dS )zRFinds (flock|mac|win)_tool.gyp in the gyp directory and copies it
  to |out_path|.flockr   r   )r   r   r   r   Nz
%s_tool.pyz!# Generated by gyp. Do not edit.
mac_toolchain_dirz,import os;
os.environ['DEVELOPER_DIR']='%s'
zgyp-%s-toolr   rC   r   r   i  )rn   r-   r.   r0   r1   rE   __file__open	readlineswriter   )r   out_pathgenerator_flagsr}   source_pathsource_filesourceheaderr   	tool_path	tool_filer	   r	   r
   CopyTool  s8   

r   c                 C   sJ   |d u rdd }i }g }| D ]}||}||v rqd||< | | q|S )Nc                 S   s   | S r   r	   )xr	   r	   r
   <lambda>  s    zuniquer.<locals>.<lambda>r   )rd   )seqidfunseenr   itemmarkerr	   r	   r
   uniquer  s   
r   c                   @   sh   e Zd ZdddZdd Zdd Zdd	 Zd
d Zdd Zdd Z	dddZ
dd Zdd Zdd ZdS )
OrderedSetNc                 C   s6   g  | _ }|d ||g7 }i | _|d ur| |O } d S d S r   )endmap)r   iterabler   r	   r	   r
   r     s   
zOrderedSet.__init__c                 C   s
   t | jS r   )r   r   r   r	   r	   r
   __len__     
zOrderedSet.__len__c                 C   s
   || j v S r   )r   )r   keyr	   r	   r
   __contains__  r   zOrderedSet.__contains__c                 C   s@   || j vr| j}|d }|||g |d<  |d< | j |< d S d S )Nr   r&   )r   r   )r   r   r   currr	   r	   r
   rl     s
   
$zOrderedSet.addc                 C   s4   || j v r| j |\}}}||d< ||d< d S d S )Nr&   r   )r   rk   )r   r   	prev_item	next_itemr	   r	   r
   discard  s
   
zOrderedSet.discardc                 c   :    | j }|d }||ur|d V  |d }||usd S d S )Nr&   r   r   r   r   r   r	   r	   r
   __iter__     
zOrderedSet.__iter__c                 c   r   )Nr   r   r   r   r	   r	   r
   __reversed__  r   zOrderedSet.__reversed__Tc                 C   s:   | st d|r| jd d n| jd d }| | |S )Nzset is emptyr   r   r&   )r   r   r   )r   lastr   r	   r	   r
   rk     s
    
zOrderedSet.popc                 C   s&   | s	d| j jf S d| j jt| f S )Nz%s()z%s(%r))	__class__r   re   r   r	   r	   r
   __repr__!  s   zOrderedSet.__repr__c                 C   s:   t |trt| t|kot| t|kS t| t|kS r   )rZ   r   r   re   rj   )r   otherr	   r	   r
   __eq__&  s   
 zOrderedSet.__eq__c                 C   s    |D ]}|| vr|  | qd S r   )rl   )r   r   ir	   r	   r
   rm   ,  s
   
zOrderedSet.updater   T)r   r   r   r   r   r   rl   r   r   r   rk   r   r   rm   r	   r	   r	   r
   r     s    

r   c                   @   s    e Zd ZdZdd Zdd ZdS )
CycleErrorz9An exception raised when an unexpected cycle is detected.c                 C   s
   || _ d S r   )nodes)r   r   r	   r	   r
   r   4  r   zCycleError.__init__c                 C   s   dt | j S )NzCycleError: cycle involving: )r   r   r   r	   r	   r
   __str__6  s   zCycleError.__str__N)r   r   r   r   r   r   r	   r	   r	   r
   r   2  s    r   c                    sF   t t t g  fdd t| D ]} | qS )a  Topologically sort based on a user provided edge definition.

  Args:
    graph: A list of node names.
    get_edges: A function mapping from node name to a hashable collection
               of node names which this node has outgoing edges to.
  Returns:
    A list containing all of the node in graph in topological order.
    It is assumed that calling get_edges once for each node and caching is
    cheaper than repeatedly calling get_edges.
  Raises:
    CycleError in the event of a cycle.
  Example:
    graph = {'a': '$(b) $(c)', 'b': 'hi', 'c': '$(b)'}
    def GetEdges(node):
      return re.findall(r'\$\(([^))]\)', graph[node])
    print(TopologicallySorted(graph.keys(), GetEdges))
    ==>
    ['a', 'c', b']
  c                    s`   | v rt | v rd S |  |  | D ]} | q|  d|  d S r7   )r   rl   r   insert)nodeneighborVisit	get_edgesordered_nodesvisitedvisitingr	   r
   r   S  s   



z"TopologicallySorted.<locals>.Visit)r   rj   sorted)graphr   r   r	   r   r
   TopologicallySorted:  s   
r   c                   C   sT   t jdp)t jdp)t jdp)t jdp)t jdp)t jdp)t jdS )NGYP_CROSSCOMPILEAR_hostCC_hostCXX_host	AR_target	CC_target
CXX_target)r-   r;   rn   r	   r	   r	   r
   CrossCompileRequestedb  s   





r   r   r   )+
__future__r   collections.abcr   r   r   os.pathr-   r]   r   rF   r   r   r   r   r   r$   r   r6   r9   r?   rA   r3   rU   rV   rX   compiler[   r_   rc   rg   rt   rx   r{   r   r   r   r   r   r   r   r   r   r	   r	   r	   r
   <module>   sN   
"	
+
"
I
+A(