B
    eJd:8                 @   s   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 d dl	m
Z
 ejdkZdd ZG dd	 d	ejZG d
d deZdd Zdd Zd$ddZdd Zdd Zdd Zd%ddZd&ddZd d! Zd"d# ZdS )'    N)reduce)
get_module)ImageUriValidator)      c             C   s   dd }t || g }|S )z0
    Custom cumsum to avoid a numpy import.
    c             S   s$   t | dkr|gS | | d | g S )Nr   )len)ax r   E/var/www/html/venv/lib/python3.7/site-packages/_plotly_utils/utils.py_reducer   s    zcumsum.<locals>._reducer)r   )r
   r   retr   r   r   cumsum   s    r   c                   s   e Zd ZdZdd Z fddZdd Zedd	 Zed
d Z	edd Z
edd Zedd Zedd Zedd Zedd Zedd Z  ZS )PlotlyJSONEncodera9  
    Meant to be passed as the `cls` kwarg to json.dumps(obj, cls=..)

    See PlotlyJSONEncoder.default for more implementation information.

    Additionally, this encoder overrides nan functionality so that 'Inf',
    'NaN' and '-Inf' encode to 'null'. Which is stricter JSON than the Python
    version.

    c             C   s   |dkrdS |S dS )zU
        This is used to ultimately *encode* into strict JSON, see `encode`

        )Infinityz	-InfinityNaNNr   )selfconstr   r   r   coerce_to_strict(   s    z"PlotlyJSONEncoder.coerce_to_strictc                sx   t t| |}d|ks$d|ks$|S ytj|| jd}W n tk
rT   tdY n X tj|| j| j	| j
| jfdS dS )z
        Load and then dump the result using parse_constant kwarg

        Note that setting invalid separators will cause a failure at this step.

        r   r   )parse_constantzSEncoding into strict JSON failed. Did you set the separators valid JSON separators?)	sort_keysindent
separatorsN)superr   encode_jsonloadsr   
ValueErrordumpsr   r   item_separatorkey_separator)r   oZ	encoded_oZnew_o)	__class__r   r   r   3   s    zPlotlyJSONEncoder.encodec          	   C   sb   | j | j| j| j| j| j| j| j| jf	}x*|D ]"}y||S  t	k
rN   Y q.X q.W t
j| |S )a  
        Accept an object (of unknown type) and try to encode with priority:
        1. builtin:     user-defined objects
        2. sage:        sage math cloud
        3. pandas:      dataframes/series
        4. numpy:       ndarrays
        5. datetime:    time/datetime objects

        Each method throws a NotEncoded exception if it fails.

        The default method will only get hit if the object is not a type that
        is naturally encoded by json:

            Normal objects:
                dict                object
                list, tuple         array
                str, unicode        string
                int, long, float    number
                True                true
                False               false
                None                null

            Extended objects:
                float('nan')        'NaN'
                float('infinity')   'Infinity'
                float('-infinity')  '-Infinity'

        Therefore, we only anticipate either unknown iterables or values here.

        )encode_as_plotlyencode_as_sageencode_as_numpyencode_as_pandasencode_as_datetimeencode_as_dateencode_as_listencode_as_decimalencode_as_pilNotEncodabler   JSONEncoderdefault)r   objZencoding_methodsZencoding_methodr   r   r   r/   X   s    !

zPlotlyJSONEncoder.defaultc             C   s&   y|   S  tk
r    tY nX dS )z1Attempt to use a builtin `to_plotly_json` method.N)Zto_plotly_jsonAttributeErrorr-   )r0   r   r   r   r$      s    z"PlotlyJSONEncoder.encode_as_plotlyc             C   s   t | dr|  S tdS )z@Attempt to use `tolist` method to convert to normal Python list.tolistN)hasattrr2   r-   )r0   r   r   r   r*      s    
z PlotlyJSONEncoder.encode_as_listc             C   s<   t d}|st| |jkr"t| S | |jkr4t| S tdS )z@Attempt to convert sage.all.RR to floats and sage.all.ZZ to intszsage.allN)r   r-   ZRRfloatZZZint)r0   Zsage_allr   r   r   r%      s    

z PlotlyJSONEncoder.encode_as_sagec             C   sB   t ddd}|st| |jkr"dS t|dr:| |jkr:dS tdS )z)Attempt to convert pandas.NaT / pandas.NApandasF)should_loadNNA)r   r-   ZNaTr3   r8   )r0   r6   r   r   r   r'      s    
z"PlotlyJSONEncoder.encode_as_pandasc             C   sn   t ddd}|st| |jjjkr*tdS t| |jrf| jj	dkrfy|
|  S  tk
rd   Y nX tdS )z'Attempt to convert numpy.ma.core.maskednumpyF)r7   nanMN)r   r-   macoreZmaskedr4   
isinstanceZndarrayZdtypekindZdatetime_as_stringr2   	TypeError)r0   r9   r   r   r   r&      s    z!PlotlyJSONEncoder.encode_as_numpyc             C   s&   y|   S  tk
r    tY nX dS )z.Convert datetime objects to iso-format stringsN)	isoformatr1   r-   )r0   r   r   r   r(      s    z$PlotlyJSONEncoder.encode_as_datetimec             C   s2   y|   }W n tk
r$   tY n
X t|S dS )z=Attempt to convert to utc-iso time string using date methods.N)rA   r1   r-   iso_to_plotly_time_string)r0   Ztime_stringr   r   r   r)      s
    
z PlotlyJSONEncoder.encode_as_datec             C   s   t | tjrt| S tdS )z3Attempt to encode decimal by converting it to floatN)r>   decimalDecimalr4   r-   )r0   r   r   r   r+      s    z#PlotlyJSONEncoder.encode_as_decimalc             C   s.   t d}|dk	r&t| |jr&t| S tdS )z5Attempt to convert PIL.Image.Image to base64 data uriz	PIL.ImageN)r   r>   ZImager   Zpil_image_to_urir-   )r0   imager   r   r   r,      s    
zPlotlyJSONEncoder.encode_as_pil)__name__
__module____qualname____doc__r   r   r/   staticmethodr$   r*   r%   r'   r&   r(   r)   r+   r,   __classcell__r   r   )r#   r   r      s   
%2
r   c               @   s   e Zd ZdS )r-   N)rF   rG   rH   r   r   r   r   r-      s   r-   c             C   sj   |  ddd dks(|  dd dkr0td| dd	d
d	} | drZ| dd	S | ddS dS )z=Remove timezone info and replace 'T' delimeter with ' ' (ws).-Nr   z00:00+r   z]Plotly won't accept timestrings with timezone info.
All timestrings are assumed to be in UTC.z-00:00 z+00:00z	T00:00:00T )split	Exceptionreplaceendswith)Z
iso_stringr   r   r   rB      s    (
rB   c                 s    fdd}|S )Nc                s0   t jd d dks,| jd k	r,| jjf  | _| S )N   )r   rU   )sysversion_inforI   format)func)namesr   r   
_decorator  s    
z template_doc.<locals>._decoratorr   )rZ   r[   r   )rZ   r   template_doc  s    r\   Fc             C   s   dd }t | ||dS )Nc          	   S   sT   t d| }x>tt|D ].}yt|| ||< W q tk
rF   Y qX qW t|S )Nz(\d+))rerQ   ranger   r5   r   tuple)vZv_partsir   r   r   key  s    
z"_natural_sort_strings.<locals>.key)rb   reverse)sorted)valsrc   rb   r   r   r   _natural_sort_strings  s    
rf   c              C   s&   t ddd} | rt| jf}ntf}|S )Nr9   F)r7   )r   r5   integer)npZint_typer   r   r   _get_int_type  s
    ri   c                s>   t |dkr| S |  tdd t fdd| } t| |S )ar  
    Split all the strings in ss at any of the characters in chars.
    Example:

        >>> ss = ["a.string[0].with_separators"]
        >>> chars = list(".[]_")
        >>> split_multichar(ss, chars)
        ['a', 'string', '0', '', 'with', 'separators']

    :param (list) ss: A list of strings.
    :param (list) chars: Is a list of chars (note: not a string).
    r   c             S   s   | | S )Nr   )r
   yr   r   r   <lambda>3      z!split_multichar.<locals>.<lambda>c                s
   |   S )N)rQ   )r
   )cr   r   rk   3  rl   )r   popr   mapsplit_multichar)sscharsr   )rm   r   rp   #  s
    rp   c             C   s<   t tdd ttt| tdgt tt| dd  S )a  
    Given a list of strings split using split_multichar, return a list of
    integers representing the indices of the first character of every string in
    the original string.
    Example:

        >>> ss = ["a.string[0].with_separators"]
        >>> chars = list(".[]_")
        >>> ss_split = split_multichar(ss, chars)
        >>> ss_split
        ['a', 'string', '0', '', 'with', 'separators']
        >>> split_string_positions(ss_split)
        [0, 2, 9, 11, 12, 17]

    :param (list) ss: A list of strings.
    c             S   s   | d | d  S )Nr      r   )tr   r   r   rk   J  rl   z(split_string_positions.<locals>.<lambda>r   Nr   )listro   zipr^   r   r   )rq   r   r   r   split_string_positions7  s    rw   rs   ^Tc             C   s   dd t t| d | | D }d}|dkrdx^| D ]*}x$t |D ]}	|| |	 }|||< qBW q4W n*x(t |D ]}	| | | |	 }|||< qnW d|}
|r|
d|d  }
|
S )a  
    Return a string that is whitespace except at p[i] which is replaced with char.
    If i is None then all the indices of the string in p are replaced with char.

    Example:

        >>> ss = ["a.string[0].with_separators"]
        >>> chars = list(".[]_")
        >>> ss_split = split_multichar(ss, chars)
        >>> ss_split
        ['a', 'string', '0', '', 'with', 'separators']
        >>> ss_pos = split_string_positions(ss_split)
        >>> ss[0]
        'a.string[0].with_separators'
        >>> display_string_positions(ss_pos,4)
        '            ^'
        >>> display_string_positions(ss_pos,4,offset=1,length=3,char="~",trim=False)
        '             ~~~      '
        >>> display_string_positions(ss_pos)
        '^ ^      ^ ^^    ^'
    :param (list) p: A list of integers.
    :param (integer|None) i: Optional index of p to display.
    :param (integer) offset: Allows adding a number of spaces to the replacement.
    :param (integer) length: Allows adding a replacement that is the char
                             repeated length times.
    :param (str) char: allows customizing the replacement character.
    :param (boolean) trim: trims the remaining whitespace if True.
    c             S   s   g | ]}d qS )rP   r   ).0_r   r   r   
<listcomp>m  s    z,display_string_positions.<locals>.<listcomp>rs   r   NrN   )r^   maxjoin)pra   offsetlengthcharZtrimsZmaxaddrZp_lr   r   r   r   display_string_positionsP  s    "

r   c             C   sx   dd }|r|t || |S t| s*| S ttt| dkrN|t| d  gS G dd d}tttt||| dgS )a  
    Given a list of strings, some of which are the empty string "", replace the
    empty strings with c and combine them with the closest non-empty string on
    the left or "" if it is the first string.
    Examples:
    for c="_"
    ['hey', '', 'why', '', '', 'whoa', '', ''] -> ['hey_', 'why__', 'whoa__']
    ['', 'hi', '', "I'm", 'bob', '', ''] -> ['_', 'hi_', "I'm", 'bob__']
    ['hi', "i'm", 'a', 'good', 'string'] -> ['hi', "i'm", 'a', 'good', 'string']
    Some special cases are:
    [] -> []
    [''] -> ['']
    ['', ''] -> ['_']
    ['', '', '', ''] -> ['___']
    If reverse is true, empty strings are combined with closest non-empty string
    on the right or "" if it is the last string.
    c             S   s   dd | D d d d S )Nc             S   s   g | ]}|d d d qS )Nr   r   )ry   r   r   r   r   r{     s    z5chomp_empty_strings.<locals>._rev.<locals>.<listcomp>r   r   )r   r   r   r   _rev  s    z!chomp_empty_strings.<locals>._revr   rs   c               @   s   e Zd Zdd Zdd ZdS )z%chomp_empty_strings.<locals>._Chomperc             S   s
   || _ d S )N)rm   )r   rm   r   r   r   __init__  s    z.chomp_empty_strings.<locals>._Chomper.__init__c             S   s6   t |dkr(|d d |d | j g S ||g S d S )Nr   r   )r   rm   )r   r
   rj   r   r   r   __call__  s    z.chomp_empty_strings.<locals>._Chomper.__call__N)rF   rG   rH   r   r   r   r   r   r   _Chomper  s   r   rN   )chomp_empty_stringsr   sumro   ru   filterr   )stringsrm   rc   r   r   r   r   r   r   ~  s    r   c             C   s   t | t |k rt|| S t |dkr.t | S tt |d }xvt| D ]j\}}|d g}xRt|D ]F\}}||d  d }|| d }	|| ||k }
|t||	|
 qdW |}qHW |d S )Nr   rs   r   )r   levenshteinr^   	enumerateappendmin)s1s2Zprevious_rowra   c1Zcurrent_rowjc2
insertionsZ	deletionsZsubstitutionsr   r   r   r     s    

r   c                s    fdd}t ||dd S )Nc                s   t |  | fS )N)r   )r   )stringr   r   _key  s    z!find_closest_string.<locals>._key)rb   r   )rd   )r   r   r   r   )r   r   find_closest_string  s    r   )F)Nr   rs   rx   T)F)rC   jsonr   rV   r]   	functoolsr   Z_plotly_utils.optional_importsr   Z_plotly_utils.basevalidatorsr   rW   ZPY36_OR_LATERr   r.   r   rR   r-   rB   r\   rf   ri   rp   rw   r   r   r   r   r   r   r   r   <module>   s*   
 R

	
.
0