U
    Tr`1                     @   s   d 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Zdad'ddZd(d
dZd)ddZd*ddZd+ddZd,ddZdd Zdd Zd-ddZdd Zdd  Zd!d" ZG d#d$ d$eZG d%d& d&e
jZdS ).z?
The Utils class contains many functions for project-wide use.
    N)futures)logceilF  @ c                 C   s   t | dkrt| d | ndt|dT}| D ]H}t|d*}||}|rb|| ||}qHW 5 Q R X t| q.W 5 Q R X dS )z
	Combines files.

	:param parts: Source files.
	:type parts: list of strings
	:param dest: Destination file.
	:type dest: string
    :param chunkSize: Fetching chunk size.
	:type chunkSize: int

	   r   wbrbN)lenshutilmoveopenreadwriteosremove)partsdestZ	chunkSizeoutputpartinputdata r   F/mnt/cestravail/FreezeDetection/sentSatProg_v.0.1.3/pySmartDL/utils.pycombine_files   s    

r   utf-8c                 C   sH   t j| \}}}}}t j|d}t j|d}t j|||||fS )u  
    Sometimes you get an URL by a user that just isn't a real
    URL because it contains unsafe characters like ' ' and so on.  This
    function can fix some of the problems in a similar way browsers
    handle data entered by the user:

    >>> url_fix(u'http://de.wikipedia.org/wiki/Elf (Begriffsklärung)')
    'http://de.wikipedia.org/wiki/Elf%20%28Begriffskl%C3%A4rung%29'

    :param s: Url address.
    :type s: string
    :param charset: The target charset for the URL if the url was
                    given as unicode string. Default is 'utf-8'.
    :type charset: string
    :rtype: string
                    
    (taken from `werkzeug.utils <http://werkzeug.pocoo.org/docs/utils/>`_)
    z/%z:&=)urllibparseurlsplitquote
quote_plus
urlunsplit)scharsetschemenetlocpathqsanchorr   r   r   url_fix)   s    r(   -#   c                 C   sT   |d8 }| dk rd} | dkr d} d|d t | |   |d |t | |    d S )a:  
    Returns a textual progress bar.
    
    >>> progress_bar(0.6)
    '[##########--------]'
    
    :param progress: Number between 0 and 1 describes the progress.
    :type progress: float
    :param length: The length of the progress bar in chars. Default is 20.
    :type length: int
    :rtype: string
       r   r   [])int)progress	look_feellengthr   r   r   progress_barA   s    r4      c                 C   sb   |  dd} t| }|sdS ddi}tjj| |d}tjj||d}t|jd }|  ||kS )	a_  
    Checks if a server allows `Byte serving <https://en.wikipedia.org/wiki/Byte_serving>`_,
    using the Range HTTP request header and the Accept-Ranges and Content-Range HTTP response headers.
    
    :param url: Url address.
    :type url: string
    :param timeout: Timeout in seconds. Default is 15.
    :type timeout: int
    :rtype: bool
     z%20FRangez	bytes=0-3)headerstimeoutContent-Length)	replaceget_filesizer   requestRequesturlopenr0   r8   close)urlr:   Zfullsizer8   requrlObjfilesizer   r   r   is_HTTPRange_supportedU   s    rF   c                 C   sL   t jj| f|}z t jj||d}|jd dkW S  tk
rF   Y dS X d S )Nr9   zaccept-rangesbytesF)r   r>   r?   r@   r8   	Exception)rB   r8   r:   rC   rD   r   r   r   auto_detect_HTTPRange_supportn   s    rI   c                 C   sP   z"t jj| |d}t|jd }W n( tttt jj	t jj
fk
rJ   Y dS X |S )z
    Fetches file's size of a file over HTTP.
    
    :param url: Url address.
    :type url: string
    :param timeout: Timeout in seconds. Default is 15.
    :type timeout: int
    :returns: Size in bytes.
    :rtype: int
    r9   r;   r   )r   r>   r@   r0   r8   
IndexErrorKeyError	TypeErrorerror	HTTPErrorURLError)rB   r:   rD   	file_sizer   r   r   r=   v   s     r=   c                  C   s6   ddddddddd	d
ddddddddddg} t | S )z
    Returns a random popular user-agent.
    Taken from `here <http://techblog.willshouse.com/2012/01/03/most-common-user-agents/>`_, last updated on 2019/07/26.
    
    :returns: user-agent
    :rtype: string
    zsMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36zsMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36zsMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36zyMozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36zNMozilla/5.0 (Windows NT 10.0; Win64; x64; rv:67.0) Gecko/20100101 Firefox/67.0zwMozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1.1 Safari/605.1.15zNMozilla/5.0 (Windows NT 10.0; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0zrMozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36ziMozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36zyMozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36zLMozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:67.0) Gecko/20100101 Firefox/67.0zrMozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36zRMozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:67.0) Gecko/20100101 Firefox/67.0zyMozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36zMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/17.17134zMMozilla/5.0 (Windows NT 6.1; Win64; x64; rv:67.0) Gecko/20100101 Firefox/67.0zAMozilla/5.0 (Windows NT 6.1; rv:60.0) Gecko/20100101 Firefox/60.0zMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/18.17763zRMozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:68.0) Gecko/20100101 Firefox/68.0zLMozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0)randomchoice)lr   r   r   get_random_useragent   s,    	rT   c              	   C   s   t tddddddgdddd	d	d	g}| dkrzttt| d
t|d }t| d
|  }|| \}}d| }|||S | dkrdS | dkrdS dS )a2  
    Human-readable formatting for filesizes. Taken from `here <http://stackoverflow.com/questions/1094841/reusable-library-to-get-human-readable-version-of-file-size>`_.
    
    >>> sizeof_human(175799789)
    '167.7 MB'
    
    :param num: Size in bytes.
    :type num: int
    
    :rtype: string
    BZkBMBZGBZTBZPBr   r   r-   i   z{:,.%sf} {}z0 bytesz1 byteN)listzipminr0   r   r	   floatformat)numZ	unit_listexponentquotientunitZnum_decimalsformat_stringr   r   r   sizeof_human   s    &ra   c           	      C   s  t | d d }t | } | dkr8|r,|dkr8|r4dS dS ddddd	d
dg}|r`ddddddg}ndddddddg}g }tt|d ddD ]B}| ||  }|dkr|||| d|  f | |||  8 } q|r|dkr|||rdndf |r
ddd |D S dd d |D S )!az  
    Human-readable formatting for timing. Based on code from `here <http://stackoverflow.com/questions/6574329/how-can-i-produce-a-human-readable-difference-when-subtracting-two-unix-timestam>`_.
    
    >>> time_human(175799789)
    '6 years, 2 weeks, 4 days, 17 hours, 16 minutes, 29 seconds'
    >>> time_human(589, fmt_short=True)
    '9m49s'
    
    :param duration: Duration in seconds.
    :type duration: int/float
    :param fmt_short: Format as a short string (`47s` instead of `47 seconds`)
    :type fmt_short: bool
    :param show_ms: Specify milliseconds in the string.
    :type show_ms: bool
    :rtype: string
    r   i  r   Z0sz	0 seconds<   i  iQ i:	 i $ i ssmmhhddZwwyy)secondseconds)minuteminutes)hourhours)daydays)weekweeks)monthmonths)yearZyearsmsmilliseconds c                 S   s   g | ]}d | qS )z%s%sr   .0xr   r   r   
<listcomp>   s     ztime_human.<locals>.<listcomp>z, c                 S   s   g | ]}d | qS )z%s %sr   ry   r   r   r   r|      s     )r0   ranger	   appendjoin)	Zduration	fmt_shortZshow_msrv   Z	INTERVALSZNAMESresultiar   r   r   
time_human   s4    
r   c              	   C   sP   t | }d}t|d*}||}|r>|| ||}q$W 5 Q R X | S )ah  
    Calculates a file's hash.

    .. WARNING::
        The hashing algorithm must be supported on your system, as documented at `hashlib documentation page <http://docs.python.org/3/library/hashlib.html>`_.
    
    :param algorithm: Hashing algorithm.
    :type algorithm: string
    :param path: The file path
    :type path: string
    :rtype: string
    i   r   )hashlibnewr   r   update	hexdigest)	algorithmr%   ZhashAlgZblock_szfr   r   r   r   get_file_hash   s    


r   c           	      C   s   | s
dgS t | | |k r,|dkr,|d8 }q
g }d}t | | }t|D ]>}|}|| }|| d krl| d }|||f ||d 7 }qH|S )a+  
    Calculates the byte chunks to download.
    
    :param filesize: filesize in bytes.
    :type filesize: int
    :param threads: Number of trheads
    :type threads: int
    :param minChunkFile: Minimum chunk size
    :type minChunkFile: int
    :rtype: Array of (startByte,endByte) tuples
    )r   r   r   r   )r   r}   r~   )	rE   threadsminChunkFileargsposchunkr   Z	startByteZendByter   r   r   calc_chunk_size  s    
r   c                  C   sP   t d} tsL| t j t  }|t j |t d | | da| S )zg
    Creates a debugging logger that prints to console.
    
    :rtype: `logging.Logger` instance
    	pySmartDLzA[%(levelname)s||%(thread)d@{%(pathname)s:%(lineno)d}] %(message)sT)	logging	getLoggerDEFAULT_LOGGER_CREATEDsetLevelDEBUGStreamHandlersetFormatter	Formatter
addHandler)Zt_logconsoler   r   r   create_debugging_logger.  s    

r   c                   @   s(   e Zd ZdZdd Zdd Zdd ZdS )	DummyLoggerzk
    A dummy logger. You can call `debug()`, `warning()`, etc on this object, and nothing will happen.
    c                 C   s   d S Nr   selfr   r   r   __init__F  s    zDummyLogger.__init__c                 O   s   d S r   r   )r   r   kargsr   r   r   
dummy_funcI  s    zDummyLogger.dummy_funcc                 C   s   | drt|S | jS )N__)
startswithobject__getattr__r   )r   namer   r   r   r   L  s    

zDummyLogger.__getattr__N)__name__
__module____qualname____doc__r   r   r   r   r   r   r   r   B  s   r   c                       s@   e Zd ZdZdd Z fddZdd Zdd	 Zd
d Z  Z	S )ManagedThreadPoolExecutorzF
	Managed Thread Pool Executor. A subclass of ThreadPoolExecutor.
    c                 C   s   t j| | g | _d S r   )r   ThreadPoolExecutorr   _futures)r   max_workersr   r   r   r   U  s    z"ManagedThreadPoolExecutor.__init__c                    s$   t  j|f||}| j| |S r   )supersubmitr   r~   )r   fnr   kwargsfuture	__class__r   r   r   Y  s    z ManagedThreadPoolExecutor.submitc                 C   s   t dd | jD S )Nc                 S   s   g | ]}|  qS r   )donery   r   r   r   r|   _  s     z2ManagedThreadPoolExecutor.done.<locals>.<listcomp>)allr   r   r   r   r   r   ^  s    zManagedThreadPoolExecutor.donec                 C   s*   g }| j D ]}| r
||  q
|S )zY
        Return all the exceptions raised.

        :rtype: List of `Exception` instances)r   	exceptionr~   )r   rS   r{   r   r   r   get_exceptionsa  s
    
z(ManagedThreadPoolExecutor.get_exceptionsc                 C   s$   | j D ]}| r|   S qdS )z
        Returns only the first exception. Returns None if no exception was raised.

        :rtype: `Exception` instance
        N)r   r   )r   r{   r   r   r   get_exceptionl  s    
z'ManagedThreadPoolExecutor.get_exception)
r   r   r   r   r   r   r   r   r   __classcell__r   r   r   r   r   Q  s   r   )r   )r   )r)   r,   )r5   )Nr5   )r5   )FF) r   r   urllib.requestr   urllib.parseurllib.errorrQ   r   r   
concurrentr   mathr   r   r
   r   r   r(   r4   rF   rI   r=   rT   ra   r   r   r   r   r   r   r   r   r   r   r   r   <module>   s.   





 
3