B
    &[_                 @   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 ej	dk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S )    N)
get_module)ImageUriValidator)      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NaNN )selfconstr	   r	   7/tmp/pip-install-l29rncou/plotly/_plotly_utils/utils.pycoerce_to_strict   s    z"PlotlyJSONEncoder.coerce_to_strictc                sd   t t| |}ytj|| jd}W n tk
r@   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.

        )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   $   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'   C   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%   )r(   r	   r	   r   r   u   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)hasattrr*   r%   )r(   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)r(   Zsage_allr	   r	   r   r      s    

z PlotlyJSONEncoder.encode_as_sagec             C   s*   t ddd}|st| |jkr"dS tdS )zAttempt to convert pandas.NaTpandasF)should_loadN)r   r%   ZNaT)r(   r.   r	   r	   r   r      s    
z"PlotlyJSONEncoder.encode_as_pandasc             C   s2   t ddd}|st| |jjjkr*tdS tdS )z'Attempt to convert numpy.ma.core.maskednumpyF)r/   nanN)r   r%   macoreZmaskedr,   )r(   r0   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)	isoformatr)   r%   )r(   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)r4   r)   r%   iso_to_plotly_time_string)r(   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)
isinstancedecimalDecimalr,   r%   )r(   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   r6   ZImager   Zpil_image_to_urir%   )r(   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)r:   r;   r<   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   r5      s    (
r5   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   rI   )sysversion_infor=   format)func)namesr	   r   
_decorator   s    
z template_doc.<locals>._decoratorr	   )rN   rO   r	   )rN   r   template_doc   s    rP   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+))rerE   rangelenr-   r   tuple)vZv_partsir	   r	   r   key   s    
z"_natural_sort_strings.<locals>.key)rW   reverse)sorted)valsrX   rW   r	   r	   r   _natural_sort_strings   s    
r[   c              C   s&   t ddd} | rt| jf}ntf}|S )Nr0   F)r/   )r   r-   integer)npZint_typer	   r	   r   _get_int_type   s
    r^   )F)r7   jsonr   rJ   rQ   Z_plotly_utils.optional_importsr   Z_plotly_utils.basevalidatorsr   rK   ZPY36_OR_LATERr&   r   rF   r%   r5   rP   r[   r^   r	   r	   r	   r   <module>   s   
 C

