B
    d                @   sn  d dl mZmZmZ d dlZd dlZd dlZd dlZd dlZd dl	Z	d dl
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mZ d dlmZ d dlmZ d dlmZ d dlmZ d d	lmZ yd dlZW n ek
r   dZY nX yd dlZW n ek
r   dZY nX ejZ ej!Z"d
# Z$dddZ%dd Z&dddZ'dddZ(dddZ)dd Z*dd Z+dd Z,dddZ-dd  Z.d!d" Z/d#d$ Z0g dfd%d&Z1dd(d)Z2d*d+ Z3dd-d.Z4d/d0 Z5dd1d2Z6dd3d4Z7dd6d7Z8dd8d9Z9d:d; Z:dd=d>Z;d?d@ Z<dAdB Z=ddCdDZ>G dEdF dFe?Z@e@ ZAG dGdH dHeBZCdIejDkZEejFZGdJdK ZHeHe_FG dLdM dMeCZIG dNdO dOeCZJG dPdQ dQeCZKdRdS ZLdTdU ZMdVdW ZNdXdY ZOdd[d\ZPdd]d^ZQddadbZRdcdd ZSG dedf dfe?ZTG dgdh dheTZUG didj djeTZVG dkdl dle?ZWdmdn ZXdodp ZYddrdsZZddtduZ[eZZ\ddvdwZ]ddxdyZ^ddzd{Z_G d|d} d}Z`dd~dZaG dd dZbdd Zcdd ZdG dd de?ZeG dd deeZfG dd de?ZgG dd de?ZhG dd de?Zidd ZjG dd dZkG dd de?Zldd ZmG dd de?ZndddZoG dd de?ZpG dd depZqdddZrdd ZsdddZtdddZudd ZvdddZwdddZxG dd de?ZyejzfddZ{dddZ|dd Z}dd Z~dadddZdd ZdddZG dd de?ZG ddÄ de?Zddń ZddǄ ZdddɄZejdkr(eZddd̈́ZdddτZdddфZddӄ Zd'ZddՄ Zddׄ Zddل ZdS )    )absolute_importdivisionprint_functionN)	cStringIO)	pbs_utils	sge_utils)round2)show_string)range)zip)inputziCON PRN AUX NUL COM1 COM2 COM3 COM4 COM5 COM6 COM7 COM8 COM9
LPT1 LPT2 LPT3 LPT4 LPT5 LPT6 LPT7 LPT8 LPT9c             c   s   |dkr| d }d} n| d7 } |dkr,d}n|dks8t tt||  | }|dk	r~t| ||  | t|| k r~|d7 }xt|D ]}| ||  V  qW dS )z
  A float range generator.

  Parameters
  ----------
  start : float
  stop : float, optional
      If empty, start at 0 and stop at the start parameter.
  step : float, optional
  tolerance : float, optional

  Returns
  -------
  generator of float
  Ng        g      ?   )AssertionErrorintmathceilabsr
   )startstopstep	tolerancecounti r   k/mnt/filia/a/genomebrowser/www/genomebrowser/fleming/tools/molprobity/modules/cctbx_project/libtbx/utils.pyxfrange%   s     r   c             C   s   t |dk rdS | | S d S )Ng:0yE>r   )r   )abr   r   r   safe_divF   s    r   c             C   s   t t| ||dS )a  
  Non-generator version of xfrange.

  Parameters
  ----------
  start : float
  stop : float, optional
      If empty, start at 0 and stop at the start parameter.
  step : float, optional

  Returns
  -------
  list of float

  See Also
  --------
  libtbx.utils.xfrange
  )r   r   )listr   )r   r   r   r   r   r   frangeL   s    r    ư>c             C   s   t | |||S )a5  
  Wraps xfrange, acts identically.

  Parameters
  ----------
  start : float
  stop : float, optional
      If empty, start at 0 and stop at the start parameter.
  step : float, optional
  tolerance : float, optional

  Returns
  -------
  generator of float

  See Also
  --------
  libtbx.utils.xfrange
  )r   )r   r   r   r   r   r   r   xsamplesa   s    r"   c             C   s   t t| |||S )aI  
  Non-generator version of xsamples.

  Parameters
  ----------
  start : float
  stop : float, optional
      If empty, start at 0 and stop at the start parameter.
  step : float, optional
  tolerance : float, optional

  Returns
  -------
  list of float

  See Also
  --------
  libtbx.utils.xfrange, libtbx.utils.xsamples
  )r   r"   )r   r   r   r   r   r   r   samplesw   s    r#   c             C   s    | dkrdS |  dd ddS )zC
  The result is supposed to be double-quoted when passed to sh.
  N\z\\"z\")replace)sr   r   r   escape_sh_double_quoted   s     r(   c             C   s   | dkr| S t | S )z
  Returns the length of a sequence or None.

  Parameters
  ----------
  seq : iterable or None

  Returns
  -------
  int or None
  N)len)seqr   r   r   xlen   s     r+   c             C   s,   d}x"| D ]}|dkr|}q
||9 }q
W |S )z{
  Calculates the result of multiplying all elements of a sequence together.

  Parameters
  ----------
  seq : iterable
  Nr   )r*   resultvalr   r   r   product   s    
r.   Tc             C   s6   i }x,t | D ] \}}|r&||ks&t|||< qW |S )a6  
  Builds a dictionary for each element in seq mapped to its index in the sequence.

  Parameters
  ----------
  seq : iterable of object
  must_be_unique : bool, optional

  Returns
  -------
  dict of object, int

  Examples
  --------
  >>> libtbx.utils.sequence_index_dict(['a', 'b'])
  {'a': 0, 'b': 1}
  )	enumerater   )r*   must_be_uniquer,   r   elemr   r   r   sequence_index_dict   s    r2   c             C   s   |   dkrtd|  yt| S  tk
r4   Y nX yt| tji S  tk
rZ    Y n& tk
r~   td| t f Y nX dS )z
  Tries to covert a string into an integer, using builtin int() as well as eval().

  Parameters
  ----------
  string : str

  Returns
  -------
  int

  Raises
  ------
  ValueError
      If string cannot be converted into an integer.
  )truefalsez0Error interpreting "%s" as a numeric expression.z3Error interpreting "%s" as a numeric expression: %sN)	lower
ValueErrorr   evalr   __dict__KeyboardInterrupt	Exceptionformat_exception)stringr   r   r   number_from_string   s    
    r=   c             C   sH   |dkst tdkr<d}|d dkr(d}td|t| f t| |S )z
  Wraps gzip.open to open a .gz file.

  Parameters
  ----------
  file_name : str
  mode : str

  Returns
  -------
  file

  Raises
  ------
  RuntimeError
      If gzip is not available.
  )rrbZrtwwbZwtr   abN r   r>   unz4gzip module not available: cannot %scompress file %s)r   gzipRuntimeErrorr	   open)	file_namemoderD   r   r   r   	gzip_open   s     rJ   c             C   s:   |dkst tdkr.tdddd| | f t| |S )z
  Wraps bz2.open to open a .bz2 file.

  Parameters
  ----------
  file_name : str
  mode : str

  Returns
  -------
  file

  Raises
  ------
  RuntimeError
      If bz2 is not available.
  )r>   r@   Nz2bz2 module not available: cannot %compress file %srD   rC   )r   bz2rF   BZ2File)rH   rI   r   r   r   bz2_open  s
    rM   c             C   s   t  }|dt|   d | }| |krBdS d}dt	|  }d|  }t
dd |||gD }	|d	krtj}td
|	 |d t||d t||d t||d x|D ]}
t|
|d qW td
|	 |d dS )a:  
  Checks the md5 hash of a file to see if it matches the expected hash.

  Parameters
  ----------
  path : str
  expected_md5_hexdigests : list of str
  hints : list of str, optional
  out : file, optional

  Returns
  -------
  bool
      False if md5 hash of file does not appear in expected_md5_hexdigests.
  
zutf-8Fz"Warning: unexpected md5 hexdigest:z
  File: %sz  New md5 hexdigest: %sc             S   s   g | ]}t |qS r   )r)   ).0r'   r   r   r   
<listcomp>9  s    z4warn_if_unexpected_md5_hexdigest.<locals>.<listcomp>N*)fileT)hashlibmd5updatejoinrG   read
splitlinesencode	hexdigestr	   maxsysstdoutprint)pathZexpected_md5_hexdigestsZhintsoutmZcurrent_md5_hexdigestZwarningrH   Znew_hexdigestwidthZhintr   r   r    warn_if_unexpected_md5_hexdigest  s&    "  
rc      c          	   C   sV   |d9 }t  }t| d.}||}x|rB|| ||}q(W W dQ R X | S )z Compute the MD5 hexdigest of the content of the given file,
      efficiently even for files much larger than the available RAM.

      The file is read by chunks of `blocksize` MB.
  i   r?   N)rS   rT   rG   rW   rU   rZ   )filenameZ	blocksizera   fbufr   r   r   md5_hexdigestD  s    

rh   c          	   C   s"  t | t dt dgkr| S | dd  } | dkr<dS d}xtddd	d
dddgD ]\}}d}| d |kr|| dd }| d| t| d kr| dd }|dk	ryt|}W n  tk
r   t	d|  Y nX P |d9 }qXW yt
| }W n" tk
r   t	d|  Y nX d}|| S )a\  
  Converts a string of a memory or file size (i.e. "10G") into a number.

  Parameters
  ----------
  mem_str : int or float

  Returns
  -------
  int or float

  Examples
  --------
  >>> libtbx.utils.get_memory_from_string("10G")
  10737418240.0
  >>> libtbx.utils.get_memory_from_string("10M")
  10485760.0

  Raises
  ------
  RuntimeError
  r   g      ? rC   r   i   KMGTEZYNz%sB   z5
   The numerical portion of %s is not a valid float
z1
   There is no memory unit or valid float in %s
)typer&   stripupperr/   findr)   floatr6   rF   r   )Zmem_strZfactorr   greekZnum_strnumr   r   r   get_memory_from_stringS  s6       r{   Fc             C   sB   t j| d}|dkr|S | }|dkr:td| |f |dkS )z
  Checks the environment variables for variable, returning it as a boolean.

  Parameters
  ----------
  variable_name : str
  default : bool, optional
      Returned if variable_name is not found.

  Returns
  -------
  bool
  N)r4   r3   01zSEnvironment variable %s must be "True", "False", "0", or "1" (current value: "%s").)r3   r}   )osenvirongetr5   Sorry)Zvariable_namedefaultvalueZvalue_lowerr   r   r   getenv_bool  s     r   c             C   s   t | jS )z
  Wraps os.stat to calculate a file's size.

  Parameters
  ----------
  file_name : str

  Returns
  -------
  int : size of file, in bytes
  )r~   statst_size)rH   r   r   r   	file_size  s    r   c          	   C   s   t | stt |r*t |t | }|dkr>t|d}n|dksJtt|| dd}t| d}||	  W dQ R X |
  dS )a,  
  Copies a file from source to target, optionally compressing it before writing
  it out.

  Parameters
  ----------
  source : str
  target : str
  compress : str, optional
      The compression algorithm to use. Currently only ".gz" is supported. If
      set, target becomes target + compress.
  NrA   z.gz)rH   rI   r?   )opisfiler   isdirrV   basenamerG   rJ   writerW   close)sourcetargetcompresstrf   r   r   r   	copy_file  s    
r   c             C   s   | |g ddkst|dkr(t| }xT|D ]L}|rft|rzt| t|rztdt| q.t	|r.t| q.W dS )z
  Removes a file from disk.

  Parameters
  ----------
  pattern : str, optional
  paths : iterable of str, optional
  ensure_success : bool, optional
  Nr   zCannot remove file: %s)
r   r   globr   existsr~   removerF   r	   r   )patternpathsZensure_successr_   r   r   r   remove_files  s    






r   rQ   c             C   sz   t j| r|dk	stt|}t | }g }xD|D ]<}t j| |}|rZt j|sZq6|	|dk	r6|
| q6W |S )z
  Find files matching a pattern in a directory.

  Parameters
  ----------
  dir_name : str
  pattern: str, optional
  files_only : bool, optional

  Returns
  -------
  list of str
  N)r~   r_   r   r   recompilelistdirrV   r   searchappend)dir_namer   Z
files_onlyregexfilesZmatching_filesrH   	full_pathr   r   r   
find_files  s    


r   c                s   |  g ddkst dk	rFtj s.t fddt D } g }x"| D ]}||tj|f qPW |jdd d |r|	  dd |D S )	z
  Sorts a list of file names by when they were last modified, ascending.

  Parameters
  ----------
  file_names : iterable of str, optional
  dir_name : str, optional
  reverse : bool, optional

  Returns
  -------
  list of str
  Nr   c                s   g | ]}t j |qS r   )r~   r_   rV   )rO   fn)r   r   r   rP     s    z'sort_files_by_mtime.<locals>.<listcomp>c             S   s   | d S )Nr   r   )xr   r   r   <lambda>      z%sort_files_by_mtime.<locals>.<lambda>)keyc             S   s   g | ]\}}|qS r   r   )rO   rH   mtimer   r   r   rP     s    )
r   r   r~   r_   r   r   r   getmtimesortreverse)
file_namesr   r   Zfiles_and_mtimesrH   r   )r   r   sort_files_by_mtime  s    
r   c             C   s$   yt | S  tk
r   | fS X dS )z
  Coverts x into a tuple, either as a direct cast or by making it the sole
  element of a tuple.

  Parameters
  ----------
  x : object

  Returns
  -------
  tuple
  N)tuple	TypeError)r   r   r   r   tupleize  s    r   r'   c             C   s   | dkr| dfS | |fS )z
  Returns a suffix if n != 1.

  Parameters
  ----------
  n : int
  suffix : str, optional

  Returns
  -------
  int
  str
  r   rC   r   )nsuffixr   r   r   plural_s"  s     r   c             C   sT   t |dkstg }x2t|D ]&}|dks.t|| |  | | } qW |  |S )Nr   )r)   r   reversedr   r   )Zi1dZsizesr,   szr   r   r   n_dim_index_from_one_dim3  s    r   c             C   s:   g }t | dr,x&| D ]}|t| qW n
||  |S )N__len__)hasattrextend	flat_listr   )Znested_listr,   Zsub_listr   r   r   r   =  s    


r   c             C   s.   x(|D ] \}}t || }|dk	r|S qW |S )z
  Selects a value from choices where its key pattern matches key.

  Parameters
  ----------
  key : str
  choices : iterable of str, object
  default : object, optional
      Returned if no pattern matches key.

  Returns
  -------
  object
  N)r   r   )r   choicesr   Zkey_patternr   ra   r   r   r   select_matchingF  s
     r   c               @   s4   e Zd Zdd Zdd Zdd Zdd Zd	d
 ZdS )KeepTypec             C   s   dS )NKeepr   )selfr   r   r   __str__[  s    zKeepType.__str__c             C   s   dS )Nr   r   )r   r   r   r   __repr__]  s    zKeepType.__repr__c             C   s   t || jS )N)
isinstance	__class__)r   otherr   r   r   __eq___  s    zKeepType.__eq__c             C   s   |  | S )N)r   )r   r   r   r   r   __ne__a  s    zKeepType.__ne__c             C   s   t tS )N)hashr   )r   r   r   r   __hash__c  s    zKeepType.__hash__N)__name__
__module____qualname__r   r   r   r   r   r   r   r   r   r   Z  s
   r   c               @   s"   e Zd ZdZeZejZdd ZdS )r   zM
  Basic exception type for user errors; the traceback will be suppressed.
  c             C   s   | j j| j _dS )z@
    Reset the class module on an instance to libtbx.utils.
    N)r   __orig_module__r   )r   r   r   r   reset_modulep  s    zSorry.reset_moduleN)r   r   r   __doc__r   r:   r   r   r   r   r   r   h  s   r   ZLIBTBX_DISABLE_TRACEBACKLIMITc             C   s^   t  ot|t}|r6G dd dt}ttd|}dt_t| ||}|rZ||krTt`n|t_|S )z
  Intercepts exception tracebacks, removing tracebacks for Sorry exceptions.

  Parameters
  ----------
  type : type
  value : Exception
  traceback : traceback

  Returns
  -------
  str
  c               @   s   e Zd ZdS )z#sorry_excepthook.<locals>.__not_setN)r   r   r   r   r   r   r   	__not_set  s    r   tracebacklimitr   )disable_tracebacklimitr   r   objectgetattrr\   r   __prev_excepthook)rt   r   	tracebackZtb_offr   Zprev_tracebacklimitr,   r   r   r   sorry_excepthookz  s    r   c               @   s   e Zd ZdZejZdS )Usagez{
  Subclass of Sorry, for printing out usage instructions upon program
  invocation without arguments (or --help, etc.).
  N)r   r   r   r   r:   r   r   r   r   r     s   r   c               @   s   e Zd ZdZejZdS )AbortzV
  Subclass of Sorry, primarily used in the Phenix GUI in response to user
  input.
  N)r   r   r   r   r:   r   r   r   r   r     s   r   c               @   s   e Zd ZdZejZdS )Failurez
  Subclass of Sorry.
  N)r   r   r   r   r:   r   r   r   r   r     s   r   c             C   s4   t  }tj}|t_z|   W d|t_X |  S )a  
  Take an object which has a show method which we shall assume will by default
  write it's output to stdout - capture this with cStringIO and return the
  string. Allows objects which have show() but not __repr__ or __str__ methods
  to add without much code changes.

  Returns
  -------
  str - output

  Raises
  ------
  AttrbuteError if object does not have callable show() method
  N)StringIOr\   r]   showgetvaluerstrip)objr`   r]   r   r   r   kludge_show_to_str  s    r   c           
   C   s   t jdd } | dk rd|  S ddl}|jdrHddl}|jdk	rHdS d}d}zhy,ddl}|jdd	}|j	t
tdd
d W n6 tk
r } zt||s d| S d}~X Y nX W d|dk	r|  |  X dS )z
  Checks python and library versions and availability to diagnose why
  multiprocessing fails to work.

  Returns
  -------
  str or None
      String indicating why multiprocessing is not working.
  Nrr   )rr      zhmultiprocessing module not available: Python 2.6 or higher is required (version currently in use: %d.%d)r   omptbxz-multiprocessing is not compatible with OpenMPz9This platform lacks a functioning sem_open implementation)Z	processesr   )funciterable	chunksizezmultiprocessing import error: )r\   version_infolibtbx.load_envenv
has_moduler   Zomp_versionmultiprocessingZPoolmapr   r
   ImportErrorstr
startswithr   rV   )Z	vers_infolibtbxr   Zsem_open_msgZpoolr   er   r   r   detect_multiprocessing_problem  s0    


r   c             C   s   | dkr|S | S )z0
  Returns value or default if value is None.
  Nr   )r   r   r   r   r   if_none  s     r   c              C   s   t  } | d j}t| d }|dkr4|dd}nHtt  d dd dd \}}|dk	rh|d }|dk	r||d	| 7 }d
||f  S )z$
  Formats an Exception object...
  r   r   rC   z (<string>, line z (line rr   Nri   zline %dz%s: %s)r\   exc_infor   r   r&   r   
extract_tbr   )ZeiZtype_r   rH   liner   r   r   r;     s    
$r;   EXCEPTION_INFO: c       	         s  ddl }|jjstsdS ddlm} ddlm} | }|j|d t	j
|d dfdd	|  D d }~g  xtjtjtjtjgD ]p fd
d}| rq| tdd}|dk	ry
|  W n" tk
r } zW dd}~X Y nX   qW |S )z
  Shows information about an exception.

  Parameters
  ----------
  prefix : str, optional

  Returns
  -------
  str or None
  r   N)introspection)r   )r`   )rR   rN   c                s   g | ]} | qS r   r   )rO   r   )prefixr   r   rP     s    z7show_exception_info_if_full_testing.<locals>.<listcomp>c                 s   x D ]} | krdS qW dS )NTFr   )o)doner`   r   r   is_done  s    
 z4show_exception_info_if_full_testing.<locals>.is_doneflush)r   r   full_testingr   r   r   	six.movesr   Z
show_stackr   	print_excrV   r   rX   r\   r]   stderr
__stdout__
__stderr__r   r   r:   r   )	r   r   r   r   Zsiomsgr   r   r   r   )r   r`   r   r   #show_exception_info_if_full_testing  s2    $ 

r  c             C   sh   d}g }x(| dkr0t | d\} }|||  q
W |dk	rVxt||k rT|d q<W |  d|S )z
  Encodes integer as a string in base 36, prepending 0's until string is of
  length equal to width.

  Parameters
  ----------
  integer : int
  width : int, optional

  Returns
  -------
  str
  Z$0123456789abcdefghijklmnopqrstuvwxyzr   $   Nr|   rC   )divmodr   r)   r   rV   )integerrb   Z	digit_setdigitsr   r   r   r   base36_encode,  s    
r    
   c             C   s,   | }|dkrt   }tt|| d |dS )z
  Encodes the number of seconds since the epoch in base 36.

  Parameters
  ----------
  seconds_since_epoch : time, optional
  multiplier : int, optional
  width : int, optional
  Ng      ?)r  rb   )timer  r   )seconds_since_epochZ
multiplierrb   r'   r   r   r   base36_timestampE  s    
r  c              C   sr   t   } t | }t jr8|d dkr8t jd }t j }nt jd }t j }t d|d||d |d d | f  S )zI
  Converts the current time into a string.

  Returns
  -------
  str
     r   r   zDate %Y-%m-%d Time %H:%M:%Sz %s %+03d%02d (%.2f s)i  <   )r  	localtimedaylighttznamealtzonetimezonestrftime)r  r  r  Zoffsr   r   r   date_and_timeT  s    




r  c               @   s<   e Zd ZdZdd Zdd Zdd Zdd
dZdddZd	S )
timer_basezP
  Base timer class used to calculate the time elapsed by various operations.
  c             C   s   |   | _d S )N)r   r   )r   r   r   r   __init__m  s    ztimer_base.__init__c             C   s   |   }|| j }|S )zb
    Returns the time elapsed since object was initialized.

    Returns
    -------
    time
    )r   r   )r   r   dr   r   r   elapsedp  s    
ztimer_base.elapsedc             C   s   |   }|| j }|| _|S )zT
    Returns time since last call of delta().

    Returns
    -------
    time
    )r   r   )r   r   r  r   r   r   delta|  s    
ztimer_base.deltarC   Nc             C   s*   |dkrt j}t|d|    |d dS )z
    Prints the time since object was initialized.

    Parameters
    ----------
    prefix : str, optional
    out : file, optional
    Nz%.2f s)rR   )r\   r]   r^   r  )r   r   r`   r   r   r   show_elapsed  s    	 ztimer_base.show_elapsedc             C   s*   |dkrt j}t|d|    |d dS )z
    Prints the time since last call of delta() or show_delta().

    Parameters
    ----------
    prefix : str, optional
    out : file, optional
    Nz%.2f s)rR   )r\   r]   r^   r  )r   r   r`   r   r   r   
show_delta  s    	 ztimer_base.show_delta)rC   N)rC   N)	r   r   r   r   r  r  r  r  r  r   r   r   r   r  h  s   
r  c               @   s   e Zd ZdZdd ZdS )user_plus_sys_timezg
  Timer class using os.times() to calculate time. Subclasses timer_base.

  Methods
  -------
  get
  c             C   s   t  }|d |d  S )z0
    Uses os.times() to calculate the time.
    r   r   )r~   times)r   r   r   r   r   r     s    zuser_plus_sys_time.getN)r   r   r   r   r   r   r   r   r   r    s   r  c               @   s   e Zd ZdZdd ZdS )wall_clock_timea{  
  Timer class using time.time() to calculate time. Subclasses timer_base.

  Methods
  -------
  get

  Notes
  -----
  When running multithreaded code, user_plus_sys_time would report the cumulated
  times for all threads: not very useful to analyse the scaling with the number
  of threads! Wall clock time, although it is less reliable is the only solution
  in that case.
  c             C   s   t   S )z1
    Uses time.time() to calculate the time.
    )r  )r   r   r   r   r     s    zwall_clock_time.getN)r   r   r   r   r   r   r   r   r   r     s   r   c               @   sN   e Zd ZdZdddZdd Zdd Zd	d
 Zdd Zdd Z	dZ
dd ZdS )time_logz1
  Class used to log the time that tasks take.
  Fc             C   s(   || _ || _d| _d| _d| _d | _d S )Nr   )labeluse_wall_clockaccumulationr   r  timer)r   r"  r#  r   r   r   r    s    ztime_log.__init__c             C   s   | j rt | _nt | _| S )z
    Starts the timer.
    )r#  r   r%  r  )r   r   r   r   r     s    
ztime_log.startc             C   s4   | j  | _d| _ |  j| j7  _|  jd7  _dS )z
    Stops the timer.
    Nr   )r%  r  r$  r   )r   r   r   r   r     s    ztime_log.stopc             C   s   | j td| j S )za
    Calculates the average length for runs of the timer.

    Returns
    -------
    float
    r   )r$  r[   r   )r   r   r   r   average  s    ztime_log.averagec             C   s   |    |  S )z5
    Stops the timer and runs its report method.
    )r   report)r   r   r   r   log  s    ztime_log.logc             C   s   d| j | j |f S )z
    Returns a string displaying the time elapsed since the timer was started.

    Parameters
    ----------
    local_label : str
        String appended to the end of the output

    Returns
    -------
    str
    ztime_log: %s: %.2f elapsed %s)r"  r%  r  )r   Zlocal_labelr   r   r   log_elapsed  s    ztime_log.log_elapsedz-time_log: label: n accumulation delta averagec             C   s,   | j dkstd| j| j| j| j|  f S )z
    Returns a string including the label, number of stops, accumulated time,
    delta time, and average time for runs of timer.

    Returns
    -------
    str
    Nztime_log: %s: %d %.2f %.3g %.3g)r%  r   r"  r   r$  r  r&  )r   r   r   r   r'    s    	ztime_log.reportN)F)r   r   r   r   r  r   r   r&  r(  r)  Zlegendr'  r   r   r   r   r!    s   

	
r!  c             C   sL   | }d}|dkrD|d }d}|dkrD|d }d}|dkrD|d }d}||fS )	a"  
  Rounds a time in seconds to the nearest days / hours / minutes, depending on
  what unit is appropriate.

  Parameters
  ----------
  time_in_seconds : int
      Time, in seconds.

  Returns
  -------
  int : The rounded time in some unit.
  str : The accompanying units for the time.
  secondsx   r  minuteshours0      daysr   )Ztime_in_seconds
time_units	time_unitr   r   r   human_readable_time  s    r3  c             C   sj   t | trt| } |dkr| S |dkr.| d S |dkrB| d d S |dkrZ| d d d S td| dS )	z
  Converts time_units and time_unit back into a time with units of seconds.

  Parameters
  ----------
  time_units : int
  time_unit : str

  Returns
  -------
  int
  r*  r,  r  r-  r0  r/  zUnknown time_unit: %sN)r   r   rx   rF   )r1  r2  r   r   r   human_readable_time_as_seconds5  s    
     r4  unknownc             C   s@   | dkr|S |r&t dt t| S t dt t| S dS )z
  Formats a unix_time in a 12-hour format.

  Parameters
  ----------
  unix_time : time
  short : bool, optional
  replace_with : str, optional
      Returned when unix_time is None.

  Returns
  -------
  str
  Nz%d-%m-%y %I:%M %pz%b %d %Y %I:%M %p)r  r  r  rx   )	unix_timeshortreplace_withr   r   r   format_timestamp_12_hourI  s
    r9  c             C   s@   | dkrdS |r&t dt t| S t dt t| S dS )z
  Formats a unix_time in a 24-hour format.

  Parameters
  ----------
  unix_time : time
  short : bool, optional
  replace_with : str, optional
      Returned when unix_time is None.

  Returns
  -------
  str
  Nr5  z%d-%m-%y %H:%Mz%b %d %Y %H:%M)r  r  r  rx   )r6  r7  r8  r   r   r   format_timestamp_24_hour_  s
    r:  c             C   st   t  }d|d |d  |d |d f }| rpyt }W n tk
rN   Y n"X |d|d |d  | d  7 }|S )Nzu+s,u,s: %.2f %.2f %.2fr   r   z micro-seconds/tick: %.3fg    .A)r~   r  r\   gettickeraccumulationAttributeError)Zshow_micro_seconds_per_tickr   r,   python_tickerr   r   r   format_cpu_timesw  s    "   r>  c             C   sx   | dkrt j} t  }yt  }W n tk
r8   Y n(X tdd| d td|| d  | d tdt| | d dS )	z
  Prints the total CPU time and average time for each Python bytecode
  instruction since the process was started.

  Parameters
  ----------
  out : file, optional
  show_micro_seconds_per_bytecode_instruction : bool, optional
  Nz1Time per interpreted Python bytecode instruction:ri   )endrR   z%.3f micro secondsg    .A)rR   zTotal CPU time: %.2f %s)r\   r]   r  r   r;  r<  r^   r3  )r`   Z+show_micro_seconds_per_bytecode_instructionZ
total_timer=  r   r   r   show_total_time  s     
  r@  c             C   s   |dkrt j}tdd|d | dk r6td|  |d n2t| d d	 }| |d  }td
||| f |d t|dd}|dk	r|  dS )a.  
  Prints seconds in a human-readable format.

  Parameters
  ----------
  seconds : float
  out : file, optional

  Examples
  --------
  >>> show_wall_clock_time(750)
  wall clock time: 12 minutes 30.00 seconds (750.00 seconds total)
  >>> show_wall_clock_time(20)
  wall clock time: 20.00 seconds
  Nzwall clock time:ri   )r?  rR   r+  z%.2f seconds)rR   r  gư>z,%d minutes %.2f seconds (%.2f seconds total)r   )r\   r]   r^   r   r   )r*  r`   ra   r'   Z	out_flushr   r   r   show_wall_clock_time  s     rA  c               @   s"   e Zd ZdZdddZdd ZdS )
show_timesz@
  Class to track the time past an instance's initialization.
  Nc             C   sV   |dkr,t  }t |d |d   | _n |dkr@t | _nd|  | _|| _dS )zc
    Parameters
    ----------
    time_start : time or str, optional
    out : file, optional
    Nr   r   Znow)r~   r  r  
time_startr`   )r   rC  r`   r   r   r   r   r    s    zshow_times.__init__c             C   s   | j }|d krtj}t }|d |d  }yt }W n tk
rP   d }Y nX d| }|d k	r|d| 7 }|dkr|d|d |  7 }t||d tt		 | j
 |d d S )	Nr   r   zusr+sys time: %.2f secondsz, ticks: %dz, micro-seconds/tick: %.3fg    .A)rR   )r*  r`   )r`   r\   r]   r~   r  r;  r<  r^   rA  r  rC  )r   r`   r   Zusr_plus_sysZticksr'   r   r   r   __call__  s        
zshow_times.__call__)NN)r   r   r   r   r  rD  r   r   r   r   rB    s   
rB  c             C   s   t t| |d dS )z
  Shows the time since time_start at exit.

  Parameters
  ----------
  time_start : time, optional
  out : file, optional

  See Also
  --------
  libtbx.utils.show_times
  )rC  r`   N)atexitregisterrB  )rC  r`   r   r   r   show_times_at_exit  s    rG  c               @   s.   e Zd Zdd Zdd Zdd Zdd	d
ZdS )host_and_userc             C   s  t jd| _t jd| _t jd| _t jd| _t jd| _t jd| _t jd| _	t jd| _
t jd	| _t jd
| _d | _t jdkrt jd}t jd}d ||gkrt j||| _nt jd| _tt dd }|d krd | _n| | _t | _t | _d S )NZHOSTZHOSTNAMEZCOMPUTERNAMEZHOSTTYPEPROCESSOR_ARCHITECTUREZMACHTYPEZOSTYPEZVENDORZUSERZUSERNAMEnt	HOMEDRIVEHOMEPATHHOMEgetpid)r~   r   r   hosthostnamecomputernamehosttypeprocessor_architecturemachtypeostypevendoruserusernamehomedirnamer_   rV   r   pidr   infosge_infor   Z
chunk_infopbs_info)r   Z	homedriveZhomepathrN  r   r   r   r    s.    

zhost_and_user.__init__c             C   s   | j d k	r| j S | jS d S )N)rW  rX  )r   r   r   r   get_user_name  s    
zhost_and_user.get_user_namec             C   s4   | j d k	r| j S | jd k	r | jS | jd k	r0| jS d S )N)rO  rP  rQ  )r   r   r   r   get_host_name	  s    


zhost_and_user.get_host_nameNrC   c             C   s  |d krt j}| jd k	r,t|d | j|d | jd k	rV| j| jkrVt|d | j|d | jd k	r| j| jkrt|d | j|d | jd k	rt|d | j|d | jd k	rt|d | j|d | jd ks| jd ks| j	d ksd
| j| j	g| jkr4| jd k	rt|d | j|d | j	d k	r4t|d	 | j	|d | jd k	r`| jd
kr`t|d | j|d | jd k	rt|d | j|d | jd k	r| j| jkrt|d | j|d | jd k	rt|d | j|d | jj||d | jj||d d S )NzHOST =)rR   z
HOSTNAME =zCOMPUTERNAME =z
HOSTTYPE =zPROCESSOR_ARCHITECTURE =-z
MACHTYPE =zOSTYPE =r5  zVENDOR =zUSER =z
USERNAME =zPID =)r`   r   )r\   r]   rO  r^   rP  rQ  rR  rS  rT  rU  rV   rV  rW  rX  r[  r]  r   r^  )r   r`   r   r   r   r   r     sJ     







zhost_and_user.show)NrC   )r   r   r   r  r_  r`  r   r   r   r   r   rH    s   	rH  c          
   C   s   t  j}|tj|dtj|dtj|dtj|dtj|dtj|dddd	g
}tj| } x|D ]}| |krnd
S qnW dS )z
  Check for specified reserved directories which are standard on many systems;
  these should never be deleted as part of any program.

  Parameters
  ----------
  target_dir : str

  Returns
  -------
  bool
  Z	DocumentsZDesktopZ	DownloadsLibraryZMoviesdata/z/homez/UsersFT)rH  rY  r~   r_   rV   abspath)
target_dirrY  Z	safe_dirsZsafe_dirr   r   r   allow_delete_directory8  s     
rg  c             C   sN   xH|D ]@}t |dkrd}n"|r.| | d}n| | | | | d qW d S )Nr   FrN   )r)   )write_methodindentincomplete_linelinesr   r   r   r   _indentor_write_loopX  s    
rl  c               @   s0   e Zd ZdddZdd Zdd Zdd
dZdS )indentorNrC   c             C   sN   |d kr|d krt j}n|j}|| _t| jdr8| j| _|| _|| _d| _d S )Nr   F)	r\   r]   file_objectr   _flushr   ri  parentrj  )r   rn  ri  rp  r   r   r   r  f  s    zindentor.__init__c             C   s   t |dkrd S |dr>t| jj| j| j| d d| _n| }t |dkr| jrv| jd | j|d  q| j| j|d   n6t| jj| j| j|d d d | j| j|d   d| _d S )	Nr   rN   )rh  ri  rj  rk  Fr   ri   rq   T)r)   endswithrl  rn  r   ri  rj  rX   )r   blockrk  r   r   r   r   s  s,     
zindentor.writec             C   s   | j   d S )N)rn  r   )r   r   r   r   ro    s    zindentor._flush  c             C   s   | j | j| | dS )N)ri  rp  )r   ri  )r   ri  r   r   r   shift_right  s    zindentor.shift_right)NrC   N)rs  )r   r   r   r  r   ro  rt  r   r   r   r   rm  d  s   
rm  c               @   s&   e Zd Zd	ddZdd Zdd ZdS )
buffered_indentorNrC   c             C   s   t | ||| g | _d S )N)rm  r  buffer)r   rn  ri  rp  r   r   r   r    s    zbuffered_indentor.__init__c             C   s   | j | d S )N)rv  r   )r   rr  r   r   r   r     s    zbuffered_indentor.writec             C   s:   | j d k	r| j   x| jD ]}t| | qW g | _d S )N)rp  write_bufferrv  rm  r   )r   rr  r   r   r   rw    s
    

zbuffered_indentor.write_buffer)NrC   N)r   r   r   r  r   rw  r   r   r   r   ru    s   
ru  c               @   s8   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d ZdS )null_outz7
  Pseudo-filehandle for suppressing printed output.
  c             C   s   dS )NFr   )r   r   r   r   isatty  r   znull_out.isattyc             C   s   d S )Nr   )r   r   r   r   r     r   znull_out.closec             C   s   d S )Nr   )r   r   r   r   r     r   znull_out.flushc             C   s   d S )Nr   )r   r   r   r   r   r     r   znull_out.writec             C   s   d S )Nr   )r   sequencer   r   r   
writelines  r   znull_out.writelinesN)	r   r   r   r   ry  r   r   r   r{  r   r   r   r   rx    s   rx  c               @   s8   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d ZdS )raise_if_outputz
  Raises an exception when written to.

  Examples
  --------
  >>> import sys
  >>> sys.stdout = libtbx.utils.raise_if_output()
  >>> print
  RuntimeError
  c             C   s   dS )NFr   )r   r   r   r   ry    s    zraise_if_output.isattyc             C   s   d S )Nr   )r   r   r   r   r     s    zraise_if_output.closec             C   s   d S )Nr   )r   r   r   r   r     s    zraise_if_output.flushc             C   s   t dS )z,
    Raises
    ------
    RuntimeError
    N)rF   )r   r   r   r   r   r     s    zraise_if_output.writec             C   s   t dS )z,
    Raises
    ------
    RuntimeError
    N)rF   )r   rz  r   r   r   r{    s    zraise_if_output.writelinesN)	r   r   r   r   ry  r   r   r   r{  r   r   r   r   r|    s   
r|  c               @   s\   e Zd ZdZdd Zdd ZdddZdd
dZdd Zdd Z	dd Z
dd Zdd ZdS )	multi_outz]
  Multiplexing output stream, e.g. for simultaneously printing to stdout
  and a logfile.
  c             C   s.   g | _ g | _g | _d| _d| _t| j d S )NFr   )labelsfile_objectsatexit_send_toclosed	softspacerE  rF  _atexit)r   r   r   r   r    s    zmulti_out.__init__c             C   s<   | j s8x0t| j| jD ]\}}|d k	r||  qW d S )N)r  r   r  r  r   r   )r   rf   r   r   r   r   r    s     zmulti_out._atexitNc             C   s2   | j r
t| j| | j| | j| | S )z
    Adds an output stream to the list.

    Parameters
    ----------
    label : str
        Label for replacing the stream later
    file_object : file
    atexit_send_to : file, optional
    )r  r   r~  r   r  r  )r   r"  rn  r  r   r   r   rF    s
    
zmulti_out.registerTc             C   s\   | j |}| j| }t|dr.||  |r:|  || j |< || j|< || j|< dS )a  
    Replaces a registered stream with a new file. Dumps everything accumulated
    in stream to the file.
    Useful when at the time of init of this object file name is not known.
    Allows to use StringIO buffer to accumulate output and then dump it to
    file and continue with it.

    Parameters
    ----------
    old_label : str
    new_label : str
    new_file_object : file
    new_atexit_send_to : file, optional
    close_old_stream :  bool, close existing stream
    r   N)r~  indexr  r   r   r   r   r  )r   Z	old_labelZ	new_labelZnew_file_objectZnew_atexit_send_toZclose_old_streamr   Zold_file_objectr   r   r   replace_stringio  s    



zmulti_out.replace_stringioc             C   s   dS )NFr   )r   r   r   r   ry    s    zmulti_out.isattyc             C   s:   x.| j D ]$}|tjkrq|tjkr$q|  qW d| _d S )NT)r  r\   r   r  r   r  )r   rn  r   r   r   r     s    
 
 zmulti_out.closec             C   sV   xP| j D ]F}t|dd }|d k	ry
|  W q tk
rL } zW d d }~X Y qX qW d S )Nr   )r  r   r:   )r   rn  r   r   r   r   r   r     s    
zmulti_out.flushc             C   s   x| j D ]}|| qW d S )N)r  r   )r   r   rn  r   r   r   r   (  s    zmulti_out.writec             C   s   x| j D ]}|| qW d S )N)r  r{  )r   rz  rn  r   r   r   r{  ,  s    zmulti_out.writelines)N)NT)r   r   r   r   r  r  rF  r  ry  r   r   r   r{  r   r   r   r   r}    s   
 
	r}  c             C   s   t d| | d dS )z
  Writes a C header to a file indicating it was generated automatically.

  Parameters
  ----------
  f : file
  file_name_generator : str
      Name of source generator.
  z/* *****************************************************
   THIS IS AN AUTOMATICALLY GENERATED FILE. DO NOT EDIT.
   *****************************************************

   Generated by:
     %s
 */
)rR   N)r^   )rf   Zfile_name_generatorr   r   r   write_this_is_auto_generated0  s    
r  c               @   s   e Zd Zdd ZdS )import_python_objectc       	   	   C   s   | d}t|dk r*td||||f d|d d }yt|}W n( tk
rp   td||||f Y nX x|dd D ]}t||}qW yt||d | _W n, tk
r   td||d ||f Y nX || _	|| _
|| _d S )N.rr   z#%simport path "%s" is too short%s%srq   z7%sno module %s%s or possibly import errors in module %sr   z(%sobject "%s" not found in module "%s"%s)splitr)   r6   rV   
__import__r   r   r   r<  path_elementsmodule_pathmodule)	r   Zimport_pathZerror_prefixZtarget_must_beZ	where_strr  r  r  attrr   r   r   r  F  s,    
  zimport_python_object.__init__N)r   r   r   r  r   r   r   r   r  D  s   r  c               @   s   e Zd ZdddZdd ZdS )input_with_promptr   c             C   sf   ydd l }W n tk
r    Y nX ytj| _W n tk
rH   d | _Y nX |d k	rX|t_t|| _d S )Nr   )readliner:   r\   r   previous_tracebacklimitr   )r   promptr   r  r   r   r   r  _  s        zinput_with_prompt.__init__c             C   s   | j d krt`n| j t_d S )N)r  r\   r   )r   r   r   r   __del__h  s    
zinput_with_prompt.__del__N)r   )r   r   r   r  r  r   r   r   r   r  ]  s   
	r  c             c   s(   d}xdV  |d7 }|| k st qW dS )a3  
  Counts the number of times its generator is called, raising an exception if
  called too many times.

  Parameters
  ----------
  assert_less_than : int

  Returns
  -------
  generator of None

  Raises
  ------
  AssertionError
      If .next() is called more than assert_less_than on the generator.
  r   Nr   )r   )Zassert_less_thanr   r   r   r   	count_maxn  s
    r  c               @   s,   e Zd ZdddZdd Zed	ddZdS )
detect_binary_fileNc             C   sB   |d krd| _ n|| _ |d kr&d| _n|| _d| _d| _d | _d S )Ni  g?r   )monitor_initialmax_fraction_non_asciin_ascii_charactersn_non_ascii_charactersstatus)r   r  r  r   r   r   r    s    zdetect_binary_file.__init__c             C   s   | j dkr|r*t|d ts*dd |D }x||D ]t}d|  k rHdk r\n n|  jd7  _n|  jd7  _|  j d8  _ | j dkr0| j| j| j krd| _nd| _P q0W | jS )Nr   c             s   s   | ]}t |V  qd S )N)ord)rO   cr   r   r   	<genexpr>  s    z4detect_binary_file.is_binary_file.<locals>.<genexpr>r      TF)r  r   r   r  r  r  r  )r   rr  r  r   r   r   is_binary_file  s    


z!detect_binary_file.is_binary_filec          	   C   sT   t ||d}t| d}||j}W d Q R X |s6dS tt||j|_|j|dS )N)r  r  r?   F)rr  )r  rG   rW   r  minr)   r  )rH   r  r  Zdetectorfhrr  r   r   r   from_initial_block  s    z%detect_binary_file.from_initial_block)NN)NN)r   r   r   r  r  staticmethodr  r   r   r   r   r    s
   
 r  c       	      C   sj  |dkst ||gddks"t |dkr:t|  }g }|j}|dkrlx|D ]}|| krR|| qRW n|dkrx|D ]}|| rz|| qzW n|dkrx|D ]}|| r|| qW n|dkrx|D ]}|| dkr|| qW nx|d	kr0ddl	}xd|D ]$}|j
| ||d
dk	r|| qW n6ddl	}x,|D ]$}|j| ||d
dk	r>|| q>W |S )a  
  Searches for a pattern in a file's contents.

  Parameters
  ----------
  pattern : str
  mode : str
      One of "==", "find", "startswith", "endswith", "re.search", "re.match"
  re_flags : int, optional
  lines : iterable of str, optional
  file_name : str, optional
  )z==rw   r   rq  z	re.searchzre.matchNr   z==r   rq  rw   r   z	re.search)r   r<   flags)r   r   rG   rW   rX   r   r   rq  rw   r   r   match)	r   rI   Zre_flagsrk  rH   r,   r   lr   r   r   r   
search_for  s@    
 

 

 
 


r  c               @   s$   e Zd Zdd Zdd Zdd ZdS )progress_displayed_as_fractionc             C   s,   || _ d| _| j dkr dd | _|   d S )Nr   r   c               S   s   d S )Nr   r   r   r   r   r     r   z9progress_displayed_as_fraction.__init__.<locals>.<lambda>)r   r   advance)r   r   r   r   r   r    s
    
 
z'progress_displayed_as_fraction.__init__c             C   sJ   | j dkrtjd tjd| j | jf  tj  |  j d7  _ d S )Nr   z%i / %ir   )r   r\   r]   r   r   r   )r   r   r   r   r    s
    
 
z&progress_displayed_as_fraction.advancec             C   s(   | j dkrd S tjd tj  d S )Nr   rN   )r   r\   r]   r   r   )r   r   r   r   r     s    
 z#progress_displayed_as_fraction.doneN)r   r   r   r  r  r   r   r   r   r   r    s   r  c               @   s   e Zd Zdd ZdS )progress_barc             C   s~   dg}| j dkr0|dg| j d   |d |d| j| j    |d tjd| tj  |  j d7  _ d S )	N|r   =r   >ri   z|rC   )	r   r   r   r   r\   r]   r   rV   r   )r   Z
charactersr   r   r   r    s    



zprogress_bar.advanceN)r   r   r   r  r   r   r   r   r    s   r  V瞯<c             C   s   ||krt | S ttt| }|dkrr|td| }t|ddk rZ|d9 }|d7 }d| }|| t|f S |d7 }tt||}d}|t| ||f S dS )ay  
  Formats a float, including the uncertainty in its value.

  Parameters
  ----------
  value : float
  standard_uncertainty : float
  minimum : float

  Returns
  -------
  str

  Examples
  --------
  >>> libtbx.utils.format_float_with_standard_uncertainty(5e-3, 1e-3)
  '0.0050(10)'
  >>> libtbx.utils.format_float_with_standard_uncertainty(5e-3, 1e-6)
  '0.0050000(10)'
  rq   r
  r   rr   z%%.%if(%%i)z%.0f(%i)N)r   r   r   r   log10pow)r   Zstandard_uncertaintyZminimumZ	precisionZsuZfmt_strr   r   r   &format_float_with_standard_uncertainty  s     r  c             C   s@   ddl }g }x(t| D ]}|d}|d|  qW d|S )z
  Creates a random string of hex characters.

  Parameters
  ----------
  number_of_digits : int

  Returns
  -------
  str
  r   N   Z0123456789abcdefrC   )randomr
   Z	randranger   rV   )number_of_digitsr  r  Zi_digitr   r   r   r   random_hex_code-  s    
r  c             C   s   d }| d kr(dd l }t|jjdd} d|  }yt|d }W n tk
rV   Y n.X t	d|rt
d|}|rt| d }|S )Nr   r   )module_namez%s/.svn/entriesr>   z(\d+)z\d+\s+dir\s+(\d+))r   r   dirnamer   	dist_pathrG   rW   IOErrorr   r  r   r   groups)r_   revr   Zentries_pathentriesZ	rev_matchr   r   r   get_svn_revision@  s    r  c             C   sN   d}| dkr(ddl }t|jjdd} d|  }t|rJt|  }|S )zt
  Returns the build tag for libtbx.

  Parameters
  ----------
  path : str, optional

  Returns
  -------
  str
  Nr   r   )r  z%s/TAG)	r   r   r  r   r  r   rG   r  ru   )r_   tagr   Ztag_file_pathr   r   r   get_build_tagU  s    
r  c           
   C   sL   yt  } W n: tk
rF } z|jdkr2tdn|W dd}~X Y nX | S )z
  Returns the current working directory, raising Sorry if it has been deleted or
  unmounted.

  Returns
  -------
  str

  Raises
  ------
  Sorry
      If the current working directory has been deleted or unmounted.
  rr   z[Could not determine the current working directory because it has been deleted or unmounted.N)r~   getcwdOSErrorerrnor   )cwdr   r   r   r   getcwd_safej  s    

r  c          
   C   s   | dkrFt jdkr8t jdd}t jdd}|| } nt jdd} yt  }W n6 tk
r } z|jd	krt| }n|W dd}~X Y nX |S )
z
  Returns the current working directory or default if it cannot be found.

  Parameters
  ----------
  default : str, optional

  Returns
  -------
  str
  NrJ  rK  zC:rL  r$   rM  rd  rr   )r~   rZ  r   r   r  r  r  )r   Z
home_driveZhome_dirr  r   r   r   r   getcwd_or_default  s    


r  c             C   s   |}|dkrg }xPt t  D ]>}t j|r || r |dd }| r |t	| q W t
|dkrtt|d d}nd}| d t| }t j|rtdt j| n
t | t j|S )a  
  Create a program output directory using sequential numbering, picking the
  highest run ID.  In other words, if the prefix is 'Refine' and the current
  directory contains subdirectories named Refine_2 and Refine_9, the new
  directory will be Refine_10.
  N_rq   r   r   z The directory %s already exists.)r~   r   r  r_   r   r   r  isdigitr   r   r)   r[   r   r  re  makedirs)r   Zdefault_directory_numberZ
dir_numberZdir_idsrH   Zdir_idr   r   r   r   create_run_directory  s     
r  c               @   s.   e Zd ZdZdejfddZejfddZdS )tmp_dir_wrapperaL  
  Convenience methods for running in a (presumably empty) temporary directory
  and copying all files to another directory.  Can be used whether or not the
  temporary directory is actually defined; if None, no action will be taken.
  Otherwise, both tmp_dir and dest_dir (default is current directory) must be
  existing paths.
  Nc             C   s   |d krt  }|| _|| _|d kr&n\t j|s@td| nBt j|sXtd| td| |d td| |d t | d S )Nz*The temporary directory %s does not exist.z,The destination directory %s does not exist.z Changing working directory to %s)rR   zUltimate destination is %s)	r~   r  tmp_dirdest_dirr_   r   r   r^   chdir)r   r  r  r`   r   r   r   r    s    ztmp_dir_wrapper.__init__c             C   s   | j d krdS tj| js tt| j }td| j |d x6|D ].}td| |d t	tj
| j || j qDW td|d dS )NFzCopying all output files to %s)rR   z  ... %srC   T)r  r~   r_   r   r  r   r   r^   shutilcopyrV   )r   r`   r   rH   r   r   r   transfer_files  s    
 
ztmp_dir_wrapper.transfer_files)r   r   r   r   r\   r]   r  r  r   r   r   r   r    s   r  c             C   s   t d| d dS )zm
  Shows a warning when running an experimental program.

  Parameters
  ----------
  out : file, optional
  a*  
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  !!                  WARNING - EXPERIMENTAL PROGRAM                        !!
  !!                                                                        !!
  !! This program is still in development - some functionality may be       !!
  !! missing and/or untested.  Use at your own risk!  For bug reports, etc. !!
  !! email help@phenix-online.org.                                          !!
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
)rR   N)r^   )r`   r   r   r   show_development_warning  s    r  c             C   s   | d k	r |d kst tj| }|dkr,d S |d kr<tdt|sTtd| nBtj|\}}x0|dkr|dkrt	dt
 tj|\}}qfW d S )NrC   zNo output directory specified.zIThe specified output directory (%s) does not exist or is not a directory.ZDropboxzYou are directing output to a Dropbox directory.  Please note that this is not guaranteed to work in all cases; use at your own risk.)r   r~   r_   r  r   r   r   r  warningswarnUserWarning)rH   r   headtailr   r   r    check_if_output_directory_exists  s"     


r  c          	   C   s   t |d}| }W dQ R X td| d tdtj| | d x*| D ]}|dr^qLqLt|| d qLW td| d td| d dS )z
  Insert a Python script into an existing file, removing any __future__
  import to prevent syntax errors.  (This could be dangerous in most contexts
  but is required for some of our Coot-related scripts to work.)
  r>   NrC   )rR   z#--- script copied from %szfrom __future__z#--- end)rG   rW   r^   r~   r_   r   rX   r   )r`   rH   rf   rc  r   r   r   r   concatenate_python_script  s    
r  c             C   s(   xdD ]}| dkrP | d9 } qW | |fS )a  
  Converts seconds into its closest form in greek units.

  Parameters
  ----------
  secs : float

  Returns
  -------
  float
  str

  Examples
  --------
  >>> libtbx.utils.greek_time(1e-3)
  (1, "milli")
  >>> libtbx.utils.greek_time(1e-6)
  (1, "micro")
  )rC   ZmillimicroZnanor   i  r   )Zsecsry   r   r   r   
greek_time  s
    
r  P   c             C   s   ddl m} |d kr:|jdd| |f i}|j|}n:|jdd||| |f i}|j }|j|||jj}|a|j| t	d| |f  |S )Nr   )urllibZhttpz%s:%dzhttp://%s:%s@%s:%szInstalled urllib proxy at %s:%d)
r   r  requestProxyHandlerbuild_openerHTTPBasicAuthHandlerHTTPHandlerlibtbx_urllib_proxyinstall_openerr^   )serverportrW  passwordr  proxyopenerZauthr   r   r   install_urllib_http_proxy3  s    
r  c              O   s   dt jkrntdkrnt jd }t jdd}t jdd}t jdd}|dk	r^tdkr^tdt|||td	 d
dlm} |j	j
| |S )z
  Substitute for urllib.request.urlopen, with automatic HTTP proxy configuration
  if specific environment variables are defined.
  ZCCTBX_HTTP_PROXYNZCCTBX_HTTP_PROXY_SERVERZCCTBX_HTTP_PROXY_PORTr  ZCCTBX_HTTP_PROXY_USERZCCTBX_HTTP_PROXY_PASSWORDzYou have defined a user name for the HTTP proxy, but no password was specified.  Please set the environment variable CCTBX_HTTP_PROXY_PASSWORD.)r  r  rW  r  r   )r  )r~   r   r  r   r  r   r  r   r  r  urlopen)argskwdsr  r  rW  Zpasswdr  r   r   r   r  D  s    
r  c             C   s   ddl }ddlm} ddlm} |dkr4|| d}tdd |j|D }tj	| | j}tj
|r~t||| kr|j| | dS d	S dS )
a-   Download the file at the given url to the given local filename,
      unless that file is already here. This is asserted by computed a digest
      and comparing it to the entries in the file at the url digests. The latter
      shall have the following format:

      some-file.txt      xxxxxxxxxx
      another-file.txt   yyyyyyyyyy

      If url is ..../some-file.txt, then the expected digest is xxxxxxxxxx.

      If digests is None, then the url of the digest file is expected to be
      named 'digests.txt' and to be next to the downloaded file.
  r   N)r_   )r  zdigests.txtc             s   s   | ]}t | V  qd S )N)r   r  )rO   Zlir   r   r   r  m  s    z)retrieve_unless_exists.<locals>.<genexpr>Z
DownloadedZCached)urlparser~   r_   r   r  urljoindictr  r  r   r   rh   urlretrieve)urlre   Zdigestsr  r_   r  Z	digest_ofZsrc_namer   r   r   retrieve_unless_existsZ  s    r  c               @   sJ   e Zd 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S )download_progressz
  Simple proxy for displaying download status - here with methods for
  writing to the console, but can be subclassed and used for graphical display.
  Nc             C   s$   |d krt  }|| _|| _d| _d S )Nr   )rx  r(  
n_kb_totaln_kb_elapsed)r   r(  r  r   r   r   r  ~  s
    zdownload_progress.__init__c             C   s   || _ d| _dS )z
    Updates the total number of bytes to download and resets the number of bytes
    downloaded.

    Parameters
    ----------
    n_kb_total : int
        Total size of download, in kilobytes.
    r   N)r  r  )r   r  r   r   r   set_total_size  s    
z download_progress.set_total_sizec             C   s$   | j dk	st|  j|7  _|  S )z
    Increments the number of bytes downloaded.

    Parameters
    ----------
    n_kb : int

    Returns
    -------
    bool
    N)r  r   r  show_progress)r   n_kbr   r   r   	increment  s    zdownload_progress.incrementc             C   s&   | j d| j| jf  | j   dS )zc
    Prints the number of bytes downloaded out of the total.

    Returns
    -------
    bool
    z%d/%d KB downloadedT)r(  r   r  r  r   )r   r   r   r   r    s    
zdownload_progress.show_progressc             C   s$   | j dk	stdtd| j| j   S )z[
    Calculates the percent completion of download.

    Returns
    -------
    float
    Nd   g      ?)r  r   r  r  )r   r   r   r   percent_finished  s    z"download_progress.percent_finishedc             C   s   | j d dS )z@
    Prints a final message indicating download completion.
    zDownload completeN)r(  r   )r   r   r   r   complete  s    zdownload_progress.completec             C   s   dS )zS
    Placeholder for cases where the download is not being run asynchronously.
    Nr   )r   r   r   r   run_continuously  s    z"download_progress.run_continuously)NN)r   r   r   r   r  r  r  r  r  r  r  r   r   r   r   r  y  s   
r  c               @   s$   e Zd ZdZdddZdddZdS )	download_targetao  
  Flexible callable object for retrieving a file from a URL, with optional
  HTTPS authentication.  Designed to be runnable in a separate thread with
  graphical progress update.

  Note that in some circumstances SSL support may be missing from the socket
  module, in which case we use 'curl' to download securely.  (This will not
  work on Windows, obviously.)
  Nc             C   sx   || _ || _|| _|| _|| _|| _d | j| jgkrt| jd k	sBtdd l}| jsnt|drnt|j	drnd| _nd| _d S )Nr   sslrD  FT)
r  rH   use_curlrW  r  base_urlr   socketr   r   )r   r  rH   r  rW  r  r  r  r   r   r   r    s    zdownload_target.__init__c             C   s  |d krt  }|d kr t|d}ddlm} ddlm} | j}| js.d | j| j	gkr|j
 }|d | j| j| j	 |j
|}|j
|}|j
| |j
| j}	|	 }
t|
d d }|| t| dd}|d }t| jd	}x0|	|}|sP ||sd }P || qW |  |  n`|  d | j| j	gkrXd
| j| j	f }|d|| j| jf }|  |dkrtd| |d krd S t !| jS )N)r(  r   )easy_run)r  zContent-lengthi   
n_kb_chunki   rA   z--user %s:%szcurl %s "%s" -o %szcurl exited with code %d)"rx  r  r   r  r   r  rH   r  rW  r  r  HTTPPasswordMgrWithDefaultRealmZadd_passwordr  r  r  r  r  r  r\  r   r  r   rG   rW   r  r   r   r  r  callrF   r   re  )r   r(  Zprogress_meterr  r  rH   ZpassmanZauthhandlerr  Zreqr\  r  r  r   fpchunkZ	curl_argsrcr   r   r   rD    sT    



 


zdownload_target.__call__)NNNN)NN)r   r   r   r   r  rD  r   r   r   r   r    s   	   
r  c             C   s&   ddl }|jd|  d|j|jddkS )z\
  Test whether a command is available by checking the return code from
  subprocess.call
  r   Nztype T)shellr]   r   )
subprocessr  PIPE)cmdr  r   r   r   
cmd_exists	  s
    
r  c             C   sb   y<t | rt|  n"t | r.t|  ntd|  W n  tk
r\   td|  Y nX dS )z?
  Bypasses trash and deletes file or directory immediately.
  z!%s is not a file nor a directory.zUnable to delete %s.N)	r   r   r  rmtreer   r~   r   r   r  )	path_namer   r   r   remove_path	  s    

r  c             C   s`   |rt |  nNyddl}W n6 tk
rP   |rDtdt t |  ntdY nX ||  dS )z!
  Wrapper for deleting a path
  r   Nz3send2trash not available; will delete path instead.zIThis function not supported because the required module is not installed.)r  
send2trashr   r  r  ImportWarningr   )r  Zdelete_if_not_availableZdelete_immediatelyr  r   r   r   try_send_to_trash,	  s    

r  i   r&   c             C   s   |dkrd}t jdkrd}t| tr(| S t| trr| }z6y| ||}W n  tk
rh   td| Y nX W d|S | dk	rt| S dS dS )a  
  Function for handling text when it is first encountered

  Changes bytestring type (str or bytes in Python 2, bytes in Python 3) to
  text string type (unicode in Python 2, str in Python 3)

  The input is returned unmodified if it is already a text string
  Will convert other types (e.g. int, float) to text string
  None is returned as None, not as u'None'

  For Linux/OS X, the default filesystem encoding is utf8.
  For Windows, the default filesystem encoding is mbcs.
  This is important for handling files with basic Python functions
  With the wrong encoding, the filesystem will not recognize the file path
  import sys; sys.getfilesystemencoding()
  Nutf8win32mbcszUnable to decode text with %s)r\   platformr   unicodebytesdecodeUnicodeDecodeErrorr   )textcodecerrorsnew_textr   r   r   
to_unicodeD	  s     


r"  c             C   s   |dkrd}t jdkrd}t| tr(| S t| trr| }z6y| ||}W n  tk
rh   td| Y nX W d|S | dk	rt| S dS dS )a  
  Function for handling text when it is passed to cctbx functions that expect
  bytestrings

  Changes text string type (unicode in Python 2, str in Python 3) to
  bytestring type (str or bytes in Python 2, bytes in Python 3)

  The input is returned unmodified if it is already a bytestring
  Will convert other types (e.g. int, float) to bytestring
  None is returned as None, not as 'None'

  For Linux/OS X, the default filesystem encoding is utf8.
  For Windows, the default filesystem encoding is mbcs
  This is important for handling files with basic Python functions.
  With the wrong encoding, the filesystem will not recognize the file path
  import sys; sys.getfilesystemencoding()
  Nr  r  r  zUnable to encode text with %s)r\   r  r   r  r  rY   UnicodeEncodeErrorr   )r  r  r   r!  r   r   r   to_bytesj	  s     


r$  c             C   s&   t jdkrt| ||S t| ||S dS )ae  
  Function for handling text in a way compatible with both Python 2 and 3 and
  with Boost.

  Boost defines boost::python::str as Unicode text in Python 3 (str type) and
  as text/byte string in Python 2 (also str type, or bytes type).

  This function just calls to_unicode and to_bytes to return the appropriate
  type depending on the Python version
  i   N)r\   
hexversionr"  r$  )r  r  r   r   r   r   to_str	  s    
r&  c              C   s   ddl } |  jS )zA
  Use psutil to return the total memory on a system in bytes.
  r   N)psutilZvirtual_memorytotal)r'  r   r   r   guess_total_memory	  s    r)  c             C   s   |  ds| S t| d tkr"| S | dr0| S y"d}x|| dkrN|d }q8W W n tk
rf   | S X ||d }t|t|  }|tkr|dt|  }d|| f S )z
  Since the compiler module is removed in Python 3, this is a copy of the
  mangle function from compiler.misc.

  This function is used for name mangling in libtbx/__init__.py for the
  slots_getstate_setstate class.
  __rr   r   r  r   Nz_%s%s)r   r)   
MANGLE_LENrq  
IndexError)rZ  klassr   Ztlenr   r   r   mangle	  s"    

r.  c          	   C   s$   t | d}|ddkS Q R X dS )zl
  Test if a file is a git lfs pointer. See
  https://github.com/git-lfs/git-lfs/blob/master/docs/spec.md
  r?      s   version httpN)rG   rW   )r_   rf   r   r   r   path_is_git_lfs_pointer	  s    r0  c             C   s   t | }|rtd|   | S )z9
  Prints a skip if the lfs pointer hasn't been loaded
  z
Skipping. %s hasn't been loaded from git
Run these commands to load the data:
cd <repository name>
git lfs install --local
git lsf pull
)r0  r^   )r_   testr   r   r   check_git_lfs_pointer_is_loaded	  s
    
r2  )NNN)NN)NNr!   )NNr!   )T)Nrd   )F)N)NNT)rQ   T)NNF)r'   )N)r   )N)Nr	  r
  )Fr5  )Fr5  )T)NT)N)NN)r   NN)r  )N)N)N)N)NN)r  NN)N)FF)Nr&   )Nr&   )Nr&   )
__future__r   r   r   rE  r   rS   r   r~   r   r  r\   r  r   r  r   r   r   Zlibtbx.queuing_system_utilsr   r   libtbx.math_utilsr   libtbx.str_utilsr	   r
   r   r   rE   r   rK   rT   Zhashlib_md5r_   r   r  Zwindows_device_namesr   r   r    r"   r#   r(   r+   r.   r2   r=   rJ   rM   rc   rh   r{   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r:   r   r   r   
excepthookr   r   r   r   r   r   r   r   r;   r  r  r  r  r  r  r   r!  r3  r4  r9  r:  Zformat_timestampr>  r@  rA  rB  rG  rH  rg  rl  rm  ru  rx  r|  r}  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r]   r  r  r  r  r  r  r  r  r  r  r  r  r  r%  r   r  r"  r$  r&  r)  r+  r.  r0  r2  r   r   r   r   <module>   s    
  

!



"
4






	

%
(

:Q


 

$
R /$^4  
+
$



#


MM 

&
'
