B
    eJd!                 @   s   d dl Z d dlmZ d dlZd dlZyd dlmZ W n  ek
rT   d dlmZ Y nX d dl	Z
d dlmZmZmZmZmZ ddlmZmZ ddlmZmZmZmZ dd	lmZ dd
lmZ e
jG dd dee
jZdS )    N)import_module)parse)urlparse)ListUnicodeDictobserveInteger   )
BaseFigureBasePlotlyType)BoxSelectorLassoSelectorInputDeviceStatePoints)custom_serializers)__frontend_version__c                   st  e Zd ZdZedjddZedjddZeejddZ	edjddZ
edjddZeejddZe jf ddieZe jf ddieZe jf ddieZeddjf ddieZeddjf ddieZeddjf ddieZeddjf ddieZeddjf ddieZeddjf ddieZeddjf ddieZeddjf ddieZeddjf ddieZeddjf ddieZeddjf ddieZeddjf ddieZeddjf ddieZeddjf ddieZ eddjf ddieZ!e"d	jddZ#e"d	jddZ$dZ%d
Z&d@ fdd	Z'dAddZ(dBddZ)dd Z*dd Z+dCddZ,dd Z-dd Z.e/ddd Z0e/dd d! Z1e/d"d#d$ Z2e/d%d&d' Z3e/d(d)d* Z4e/d+d,d- Z5d.d/ Z6dDd0d1Z7d2d3 Z8d4d5 Z9e:d6d7 Z;e;j<d8d7 Z;e=d9d: Z>e=dEd<d=Z?e=dFd>d?Z@  ZAS )GBaseFigureWidgetza
    Base class for FigureWidget. The FigureWidget class is code-generated as a
    subclass
    Z
FigureViewT)synczjupyterlab-plotlyZFigureModelr   )
allow_noner   FNc                sV   t t| jf ||||d| | jr.t  d| _d| _g | _d| _d| _	d| _
d S )N)dataZlayout_plotlyframesskip_invalidr   F)superr   __init___frame_objs_display_frames_error_last_layout_edit_id_layout_edit_in_process_waiting_edit_callbacks_last_trace_edit_id_trace_edit_in_processZ_view_count)selfr   layoutr   r   kwargs)	__class__ C/var/www/html/venv/lib/python3.7/site-packages/plotly/basewidget.pyr   l   s    	zBaseFigureWidget.__init__c             C   s2   | j d }|| _ d| _|||d}|| _d| _dS )a  
        Send Plotly.relayout message to the frontend

        Parameters
        ----------
        layout_data : dict
            Plotly.relayout layout data
        source_view_id : str
            UID of view that triggered this relayout operation
            (e.g. By the user clicking 'zoom' in the toolbar). None if the
            operation was not triggered by a frontend view
        r
   T)relayout_datalayout_edit_idsource_view_idN)r   r   _py2js_relayout)r"   layout_datar*   r)   msg_datar&   r&   r'   _send_relayout_msg   s    
z#BaseFigureWidget._send_relayout_msgc             C   sV   |  |}| jd }|| _d| _| jd }|| _d| _|||||d}|| _d| _dS )a  
        Send Plotly.restyle message to the frontend

        Parameters
        ----------
        restyle_data : dict
            Plotly.restyle restyle data
        trace_indexes : list[int]
            List of trace indexes that the restyle operation
            applies to
        source_view_id : str
            UID of view that triggered this restyle operation
            (e.g. By the user clicking the legend to hide a trace).
            None if the operation was not triggered by a frontend view
        r
   T)restyle_dataZrestyle_tracestrace_edit_idr)   r*   N)_normalize_trace_indexesr   r   r    r!   _py2js_restyle)r"   r/   trace_indexesr*   r)   r0   restyle_msgr&   r&   r'   _send_restyle_msg   s    


z"BaseFigureWidget._send_restyle_msgc             C   sH   | j d }|| _ d| _| jd }|| _d| _|||d}|| _d| _dS )z
        Send Plotly.addTraces message to the frontend

        Parameters
        ----------
        new_traces_data : list[dict]
            List of trace data for new traces as accepted by Plotly.addTraces
        r
   T)Z
trace_datar0   r)   N)r   r   r    r!   _py2js_addTraces)r"   Znew_traces_datar)   r0   Zadd_traces_msgr&   r&   r'   _send_addTraces_msg   s    

z$BaseFigureWidget._send_addTraces_msgc             C   s   ||d}|| _ d| _ dS )z
        Send Plotly.moveTraces message to the frontend

        Parameters
        ----------
        current_inds : list[int]
            List of current trace indexes
        new_inds : list[int]
            List of new trace indexes
        )Zcurrent_trace_indsZnew_trace_indsN)_py2js_moveTraces)r"   Zcurrent_indsZnew_indsZmove_msgr&   r&   r'   _send_moveTraces_msg  s    
z%BaseFigureWidget._send_moveTraces_msgc             C   sX   |  |}| jd }|| _d| _| jd }|| _d| _||||||d}|| _d| _dS )a'  
        Send Plotly.update message to the frontend

        Parameters
        ----------
        restyle_data : dict
            Plotly.update restyle data
        relayout_data : dict
            Plotly.update relayout data
        trace_indexes : list[int]
            List of trace indexes that the update operation applies to
        source_view_id : str
            UID of view that triggered this update operation
            (e.g. By the user clicking a button).
            None if the operation was not triggered by a frontend view
        r
   T)
style_datar,   style_tracesr0   r)   r*   N)r1   r    r!   r   r   _py2js_update)r"   r/   r(   r3   r*   r0   r)   
update_msgr&   r&   r'   _send_update_msg)  s    


z!BaseFigureWidget._send_update_msgc             C   sZ   |  |}| jd }|| _d| _| jd }|| _d| _||||||dd}|| _d| _dS )a  
        Send Plotly.update message to the frontend

        Note: there is no source_view_id parameter because animations
        triggered by the fontend are not currently supported

        Parameters
        ----------
        styles_data : list[dict]
            Plotly.animate styles data
        relayout_data : dict
            Plotly.animate relayout data
        trace_indexes : list[int]
            List of trace indexes that the animate operation applies to
        r
   TN)r:   r,   r;   animation_optsr0   r)   r*   )r1   r    r!   r   r   _py2js_animate)r"   Zstyles_datar(   r3   r?   r0   r)   Zanimate_msgr&   r&   r'   _send_animate_msg[  s     


z"BaseFigureWidget._send_animate_msgc             C   sH   | j d }|| _ d| _| jd }|| _d| _|||d}|| _d| _dS )z
        Send Plotly.deleteTraces message to the frontend

        Parameters
        ----------
        delete_inds : list[int]
            List of trace indexes of traces to delete
        r
   T)delete_indsr)   r0   N)r    r!   r   r   _py2js_deleteTraces)r"   rB   r0   r)   Z
delete_msgr&   r&   r'   _send_deleteTraces_msg  s    

z'BaseFigureWidget._send_deleteTraces_msg_js2py_traceDeltasc             C   s   |d }|sd| _ dS |d }|d }|| jkrx~|D ]v}|d }dd | jD }||}| j| }	t|	j|}
| |	j|	j}|r||d}|| _	d| _	| 
|
|g q6W d	| _| jsx| jr| j   qW d| _ dS )
z@
        Process trace deltas message from the frontend
        newNtrace_deltasr0   uidc             S   s   g | ]
}|j qS r&   )rH   ).0tracer&   r&   r'   
<listcomp>  s    z?BaseFigureWidget._handler_js2py_traceDeltas.<locals>.<listcomp>)Zremove_traceremove_propsF)rE   r    r   indexr   _transform_dataZ_prop_defaults_remove_overlapping_propsZ_props_py2js_removeTracePropsZ _dispatch_trace_change_callbacksr!   r   r   pop)r"   changer-   rG   r0   deltaZ	trace_uidZ
trace_uidstrace_indexZ	uid_tracedelta_transformrL   Zremove_trace_props_msgr&   r&   r'   _handler_js2py_traceDeltas  s6    




z+BaseFigureWidget._handler_js2py_traceDeltas_js2py_layoutDeltac             C   s   |d }|sd| _ dS |d }|d }|| jkrt| j|}| | j| j}|rfd|i}|| _d| _x8|D ]0}|d }	| j	|	}
|
rl|	| jkrli | j|	< qlW | 
| d| _| jsx| jr| j   qW d| _ dS )z@
        Process layout delta message from the frontend
        rF   Nlayout_deltar)   rL   r   F)rW   r   r   rN   Z_layout_defaultsrO   _layout_py2js_removeLayoutPropsr#   Z_subplot_re_matchZ!_dispatch_layout_change_callbacksr   r!   r   rQ   )r"   rR   r-   rX   r)   rU   Zremoved_propsZremove_props_msgZproppathpropmatchr&   r&   r'   _handler_js2py_layoutDelta  s4    



z+BaseFigureWidget._handler_js2py_layoutDelta_js2py_restylec             C   sH   |d }|sd| _ dS |d }|d }|d }| j|||d d| _ dS )zB
        Process Plotly.restyle message from the frontend
        rF   Nr:   r;   r*   )r/   r3   r*   )r^   Zplotly_restyle)r"   rR   r4   r:   r;   r*   r&   r&   r'   _handler_js2py_restyle1  s    z'BaseFigureWidget._handler_js2py_restyle_js2py_updatec             C   sR   |d }|sd| _ dS |d }|d }|d }|d }| j||||d d| _ dS )zA
        Process Plotly.update message from the frontend
        rF   Nr:   r;   r,   r*   )r/   r(   r3   r*   )r`   Zplotly_update)r"   rR   r=   styler3   r#   r*   r&   r&   r'   _handler_js2py_updateM  s    z&BaseFigureWidget._handler_js2py_update_js2py_relayoutc             C   sP   |d }|sd| _ dS |d }|d }d|kr8|d | j||d d| _ dS )zC
        Process Plotly.relayout message from the frontend
        rF   Nr(   r*   ZlastInputTime)r(   r*   )rc   rQ   Zplotly_relayout)r"   rR   Zrelayout_msgr(   r*   r&   r&   r'   _handler_js2py_relayoutk  s    
z(BaseFigureWidget._handler_js2py_relayout_js2py_pointsCallbackc                s  |d }|sd _ dS |d }|ddrx|d }|d }|d }|dkrVtf |}q||dkrjtf |}q|td	| nd}|d
dr|d
 }tf |}	nd}	|d }
 fddtt jD }x`t	|
d |
d |
d |
d D ]>\}}}}|| }|d 
| |d 
| |d 
| qW x| D ]\}}tf |} j| }|dkrd|||	 n\|dkr||||	 nD|dkr|||	 n,|dkr||| n|dkr0|| q0W d _ dS )zC
        Process points callback message from the frontend
        rF   N
event_typeselectortypeselector_stateboxlassozUnsupported selector type: %sZdevice_statepointsc                s&   i | ]}g g g  j | j|d |qS ))
point_indsxsysZ
trace_namerT   )
_data_objsname)rI   	trace_ind)r"   r&   r'   
<dictcomp>  s   zBBaseFigureWidget._handler_js2py_pointsCallback.<locals>.<dictcomp>rn   ro   Zpoint_indexesr3   rm   Zplotly_clickZplotly_hoverZplotly_unhoverZplotly_selectedZplotly_deselect)re   getr   r   
ValueErrorr   rangelenrp   zipappenditemsr   r   Z_dispatch_on_clickZ_dispatch_on_hoverZ_dispatch_on_unhoverZ_dispatch_on_selectionZ_dispatch_on_deselect)r"   rR   Zcallback_datarf   Zselector_dataZselector_typeri   rg   Zdevice_state_datastateZpoints_dataZtrace_pointsxyZ	point_indrr   Z
trace_dictZtrace_points_datarl   rJ   r&   )r"   r'   _handler_js2py_pointsCallback  sZ    







z.BaseFigureWidget._handler_js2py_pointsCallbackc             C   s   t dS )z/
        Customize html representation
        N)NotImplementedError)r"   r&   r&   r'   _repr_html_  s    zBaseFigureWidget._repr_html_c             K   s   ddd| j diS )zF
        Return mimebundle corresponding to default renderer.
        z(application/vnd.jupyter.widget-view+json   r   )Zversion_majorZversion_minorZmodel_id)Z	_model_id)r"   includeexcludevalidater$   r&   r&   r'   _repr_mimebundle_  s    z"BaseFigureWidget._repr_mimebundle_c             C   s   t dS )zD
        Handle rich display of figures in ipython contexts
        N)r   )r"   r&   r&   r'   _ipython_display_  s    z"BaseFigureWidget._ipython_display_c             C   s$   | j s| jr| j| n|  dS )a  
        Register a function to be called after all pending trace and layout
        edit operations have completed

        If there are no pending edit operations then function is called
        immediately

        Parameters
        ----------
        fn : callable
            Function of zero arguments to be called when all pending edit
            operations have completed
        N)r   r!   r   ry   )r"   fnr&   r&   r'   on_edits_completed  s    z#BaseFigureWidget.on_edits_completedc             C   s   | j S )N)r   )r"   r&   r&   r'   r     s    zBaseFigureWidget.framesc             C   s   |rt   d S )N)r   r   )r"   Z
new_framesr&   r&   r'   r     s    c              C   s   d} t | dS )z
        Display an informative error when user attempts to set frames on a
        FigureWidget

        Raises
        ------
        ValueError
            always
        z
Frames are not supported by the plotly.graph_objs.FigureWidget class.
Note: Frames are supported by the plotly.graph_objs.Figure classN)ru   )msgr&   r&   r'   r     s    z&BaseFigureWidget._display_frames_errorr&   c       
      C   sJ  g }t | trt |tstx| D ]\}}t |tsBt|r|| kr| | }||f }t|||}|| |s| 	| |
| q&|| kr&|dkr&| 	| |
||f  q&W nt | trFt |tstxlt|D ]`\}	}|	t| krP | |	 }|dk	rt |ts t|r||	f }t|||}|| qW |S )a  
        Remove properties in input_data that are also in delta_data, and do so
        recursively.

        Exception: Never remove 'uid' from input_data, this property is used
        to align traces

        Parameters
        ----------
        input_data : dict|list
        delta_data : dict|list

        Returns
        -------
        list[tuple[str|int]]
            List of removed property path tuples
        rH   N)
isinstancedictAssertionErrorrz   r   _is_dict_listr   rO   extendrQ   ry   list	enumeraterw   )
Z
input_dataZ
delta_dataZ	prop_pathremovedpZ	delta_val	input_valZrecur_prop_pathZrecur_removedir&   r&   r'   rO   -  s>    









z*BaseFigureWidget._remove_overlapping_propsc          	   C   s  i }t | trt |ts,tdj| |dx| D ]\}}t |tsRt|r|| krpt |trhi ng | |< | | }|tj	|||||f d q6|| kst
| | |s6|| |< ||f }|||< q6W |rxt|  t| D ]}	| |	 qW nt | trt |ts.tdj| |dxt|D ]\}
}|
t| krX| d | |
 }|dk	rt |tst|r|tj	|||||
f d n(t
| |
 |s8|| |
< ||||
f < q8W |S )aB  
        Transform to_data into from_data and return relayout-style
        description of the transformation

        Parameters
        ----------
        to_data : dict|list
        from_data : dict|list

        Returns
        -------
        dict
            relayout-style description of the transformation
        z,Mismatched data types: {to_dict} {from_data})to_dict	from_data)should_removerelayout_pathz5Mismatched data types: to_data: {to_data} {from_data})to_datar   N)r   r   ru   formatrz   r   r   updater   rN   r   Z_vals_equalsetkeys
differencerQ   r   r   rw   ry   )r   r   r   r   r(   Z	from_propZfrom_valr   Zrelayout_path_propZremove_propr   r&   r&   r'   rN   |  s^    



z BaseFigureWidget._transform_data)NNNF)N)NN)NN)NNT)r&   )Tr&   )B__name__
__module____qualname____doc__r   tagZ
_view_nameZ_view_moduler   Z_view_module_versionZ_model_nameZ_model_moduleZ_model_module_versionr   r   rY   r   _data_configr6   r2   r+   r<   r@   rC   r8   rZ   rP   rE   rW   r^   rc   r`   re   r	   r   r    Z_set_trace_uidZ_allow_disable_validationr   r.   r5   r7   r9   r>   rA   rD   r   rV   r]   r_   rb   rd   r~   r   r   r   r   propertyr   setterstaticmethodr   rO   rN   __classcell__r&   r&   )r%   r'   r      sn   
8
 
.!
12#A@X
Nr   ) uuid	importlibr   osnumbersurllibr   ImportErrorr   
ipywidgetsZwidgetsZ	traitletsr   r   r   r   r	   Zbasedatatypesr   r   	callbacksr   r   r   r   Zserializersr   versionr   registerZ	DOMWidgetr   r&   r&   r&   r'   <module>   s   