
    MfNy                        d Z ddlZddlZddlZddlZddlmZmZmZ ddl	Z	ddl	m
Z
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mZ d	dlmZ d	dlmZ d	dlmZ d	dlmZmZ 	 ddlm Z   e d           G d d                      Z!n#   G d d          Z!Y nxY wda"i a#da$d Z%d Z&d Z'd Z( G d d          Z) G d d          Z* G d de          Z+d Z, G d  d!e
          Z-dS )"a  
dash_wrapper

This module provides a DjangoDash class that can be used to
expose a Plotly Dasb application through a Django server

Copyright (c) 2018 Gibbs Consulting and others - see CONTRIBUTIONS.md

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
    N)DictListCallable)Dashdependencies)split_callback_idinputs_to_dict)reverse)slugify)Flask   )app_namemain_view_label)EmbeddedHolder)serve_locally)stateless_app_lookup_hook)static_asset_pathDjangoPlotlyJSONEncoder)	dataclassT)frozenc                   V    e Zd ZU eed<   eed<   eed<   eed<   eed<   eed<   eed<   dS )	CallbackContextinputs_listinputsstates_liststatesoutputs_listoutputs	triggeredN)__name__
__module____qualname__r   __annotations__r        ^/var/www/surfInsights/venv3-11/lib/python3.11/site-packages/django_plotly_dash/dash_wrapper.pyr   r   1   sX         r%   r   c                       e Zd Zd Zed             Zed             Zed             Zed             Zed             Z	ed             Z
ed             Zd	S )
r   c                     || _         d S N_args)selfkwargss     r&   __init__zCallbackContext.__init__>   s    DJJJr%   c                     | j         d         S )Nr   r*   r,   s    r&   r   zCallbackContext.inputs_listA       :m,,r%   c                     | j         d         S )Nr   r*   r0   s    r&   r   zCallbackContext.inputsE       :h''r%   c                     | j         d         S )Nr   r*   r0   s    r&   r   zCallbackContext.states_listI   r1   r%   c                     | j         d         S )Nr   r*   r0   s    r&   r   zCallbackContext.statesM   r3   r%   c                     | j         d         S )Nr   r*   r0   s    r&   r   zCallbackContext.outputsQ   s    :i((r%   c                     | j         d         S )Nr   r*   r0   s    r&   r   zCallbackContext.outputs_listU   s    :n--r%   c                     | j         d         S )Nr   r*   r0   s    r&   r   zCallbackContext.triggeredX   s    :k**r%   N)r    r!   r"   r.   propertyr   r   r   r   r   r   r   r$   r%   r&   r   r   =   s        	  	  	  
	- 	- 
	- 
	( 	( 
	( 
	- 	- 
	- 
	( 	( 
	( 
	) 	) 
	) 
	. 	. 
	.		+ 	+ 
	+ 	+ 	+r%   c                     |t           | <   | S )z!Add app to local registry by nameusable_apps)nameapps     r&   add_usable_appr?   c   s     KKr%   c                      t           S )zLReturn a dictionary of all locally registered apps with the slug name as keyr;   r$   r%   r&   all_appsrA   i   s    r%   c                  *    t          t                    S )z;Return a list of all locally registered stateless apps
    )listr<   r$   r%   r&   get_local_stateless_listrD   m   s     r%   c                     t                               | d          }|s$t          t                      at          |           }|st	          d| z            |S )zg
    Locate a registered dash app by name, and return a DjangoDash instance encapsulating the app.
    Nz,Unable to find stateless DjangoApp called %s)r<   get_stateless_app_lookup_funcr   KeyError)r=   sas     r&   get_local_stateless_by_namerJ   r   sb     
t	$	$B . &-)B)D)D&'-- LEdJKKKIr%   c                   $    e Zd ZdZd Zd Zd ZdS )Holderz.Helper class for holding configuration optionsc                     g | _         d S r)   )itemsr0   s    r&   r.   zHolder.__init__   s    


r%   c                 :    | j                             |           dS )z,Add extra css file name to component packageNrN   append)r,   
stylesheets     r&   
append_csszHolder.append_css   s    
*%%%%%r%   c                 :    | j                             |           dS )z/Add extra script file name to component packageNrP   )r,   scripts     r&   append_scriptzHolder.append_script   s    
&!!!!!r%   N)r    r!   r"   __doc__r.   rS   rV   r$   r%   r&   rL   rL      sG        44  & & &" " " " "r%   rL   c                       e Zd ZdZ	 	 	 	 	 ddZd ZddZd Zd Zd	 Z	d
 Z
ddZddZed             Zd ZeZd Zd ZdS )
DjangoDashz
    Wrapper class that provides Dash functionality in a form that can be served by Django

    To use, construct an instance of DjangoDash() in place of a Dash() one.
    NFc                    |pg | _         |pg | _        || _        |r(t          j        d                    |                     |t          dz  adt          z  | _        n|| _        d | _        g | _	        g | _
        t                      | _        t                      | _        t          | j        |            |t                      | _        n|| _        || _        |r	 ddlm}  |            d         }	n#  ddlm}  |            d         }	Y nxY w| j        r=d	}
|	                    d
          d         }| j                            |	g||
d           n| j                            d|	gi           t/          j                    d         }t/          j        |d                   | _        	 t/          j        | j                  | _        n#  d | _        Y nxY wd| _        d S )NzYou are passing extra arguments {kwargs} that will be passed to Dash(...) but may not be properly handled by django-plotly-dash.r-   r   z	djdash_%ir   )css_urlhrefurldpd_static_support/)external_urlrelative_package_path	namespacerb   assets)external_stylesheetsexternal_scripts_kwargswarningswarnformatuid_counter_uidlayout_callback_sets_clientside_callback_setsrL   cssscriptsr?   serve_locally_setting_serve_locally_suppress_callback_exceptionsbootstrap4.bootstrapr\   django_bootstrap5.coresplitrV   inspectstack	getmodulecaller_modulegetfilecaller_module_locationassets_folder)r,   r=   r   add_bootstrap_linkssuppress_callback_exceptionsrf   rg   r-   r\   bootstrap_sourcehard_coded_package_namebase_file_namecaller_frames                r&   r.   zDjangoDash.__init__   sC    %9$>B! 0 6B 	jM SSYSYagSYShShj j j <1K#k1DIIDI )+&88xxty	 	 	  "7"9"9D"/D-I* 	N4888888#*799V#4  4::::::#*799U#3   " 
N*>'!1!7!7!<!<R!@&&@P?RBPBY(* (* + + + +
 &&8H7J'LMMM }q)$.|A??	/*1/$:L*M*MD''	/*.D'''%s   C5 5D,G 	Gc                 :    | j         j        }t          ||          S r)   )r|   r    r   )r,   
asset_pathmodule_names      r&   get_asset_static_urlzDjangoDash.get_asset_static_url   s    (1 j999r%   c                 .    |                      |          S )zE
        Form a dash instance, for stateless use of this app
        )cache_id)do_form_dash_instance)r,   r   s     r&   as_dash_instancezDjangoDash.as_dash_instance   s     ))8)<<<r%   c                     dS z/Do nothing impl - only matters if state presentNr$   r0   s    r&   handle_current_statezDjangoDash.handle_current_state       r%   c                     dS r   r$   )r,   widkeyvalues       r&   update_current_statezDjangoDash.update_current_state   r   r%   c                     dS r   r$   )r,   r   r   s      r&   have_current_state_entryz#DjangoDash.have_current_state_entry   r   r%   c                     |st           dt          }| j        }nt           dt          }|}d|i}|r
||d<   |dz   }t          ||          }|d         dk    r|dz   }||fS )	zOBase path name of this instance, taking into account any state or statelessnessz:app-:identr   z--argsr[   ra   r`   )r   r   rm   r
   )r,   specific_identifierr   app_pathnamendidr-   full_urls          r&   get_base_pathnamezDjangoDash.get_base_pathname   s    " 	')1??CL9DD&.hh@L&D4 	3!)F:'(2L<777B<3#~HX~r%   c                 b    |                      ||          \  }}|                     |||          S )zIPerform the act of constructing a Dash instance taking into account state)r   form_dash_instance)r,   replacementsr   r   r   base_pathnames         r&   r   z DjangoDash.do_form_dash_instance  s7     #445H(SSm&&|T=IIIr%   c           
         || j         }t          d|||| j        | j        | j        d| j        }| j        |_        | j        |j        d<   | j	        D ]\  }}  |j
        di ||           | j        D ]} |j        di | | j        j        D ]}|j                            |           | j        j        D ]}|j                            |           |S )z3Construct a Dash instance taking into account stateN)r   r   r   r   rf   rg   r   r$   )rm   WrappedDashrt   rf   rg   rh   rn   ru   configro   callbackrp   clientside_callbackrq   rN   rS   rr   rV   )r,   r   r   r   rdcbfuncss           r&   r   zDjangoDash.form_dash_instance  s1    <9D )}&2"'+':.2.G*.*?) )  <) ) K	484V	01+ 	$ 	$HBKBK"d####0 	) 	)B"B"((R(((( 	! 	!AFa    # 	( 	(AJ$$Q''''	r%   c                 "   t          |pg           t          |pg           z   }d t          j        t          j        |           j                                        d           D             }t          j        j        |v rd}nt          j        j	        |v r&|
                    t          j        j        g           }nS|
                    t          j        j        g           |d         |
                    t          j        j        g           z   }|S )ai  Analyse a callback function signature to detect the expanded arguments to add when called.
        It uses the inputs and the state information to identify what arguments are already coming from Dash.

        It returns a list of the expanded parameters to inject (can be [] if nothing should be injected)
         or None if all parameters should be injected.c                 .    i | ]\  }}|d  |D             S )c                     g | ]	}|j         
S r$   )r=   ).0ps     r&   
<listcomp>z@DjangoDash.get_expanded_arguments.<locals>.<dictcomp>.<listcomp>1  s    !=!=!=Q!&!=!=!=r%   r$   )r   kind
parameterss      r&   
<dictcomp>z5DjangoDash.get_expanded_arguments.<locals>.<dictcomp>1  s@     m m mBR$
4!=!=*!=!=!= m m mr%   c                     | j         S r)   )r   )r   s    r&   <lambda>z3DjangoDash.get_expanded_arguments.<locals>.<lambda>2  s
    dedj r%   N)len	itertoolsgroupbyry   	signaturer   values	ParameterVAR_KEYWORDVAR_POSITIONALrF   KEYWORD_ONLYPOSITIONAL_OR_KEYWORD)r   r   staten_dash_parametersparameter_typesexpandeds         r&   get_expanded_argumentsz!DjangoDash.get_expanded_arguments(  s     "--EKR0@0@@m m$,W->t-D-D-O-V-V-X-XZjZjkkm m m(O;;HH-@@ '**7+<+I2NNHH '**7+<+RTVWW())+-<-@-@ARA_ac-d-deH r%   c                 `     t          j        ||          \  }}||d fd}|S )ac  Form a callback function by wrapping, in the same way as the underlying Dash application would
        but handling extra arguments provided by dpd.

        It will inspect the signature of the function to ensure only relevant expanded arguments are passed to the callback.

        If the function accepts a **kwargs => all expanded arguments are sent to the function in the kwargs.
        If the function has a *args => expanded arguments matching parameters after the *args are injected.
        Otherwise, take all arguments beyond the one provided by Dash (based on the Inputs/States provided).

        )outputr   r   prevent_initial_callc                     j                             | f           t                              |           | _        | S r)   )ro   rQ   rY   r   r   )r   callback_setr   r,   r   s    r&   	wrap_funcz&DjangoDash.callback.<locals>.wrap_funcV  s?    &&d';<<<
 '==dFERRDMKr%   )r   handle_callback_args)	r,   r+   rh   r   r   r   r   r   r   s	   `     @@@r&   r   zDjangoDash.callbackA  sv     7C6W77
 7
33 #)"(!&0DF F
	 	 	 	 	 	 	 	 r%   c                 ~    t          j        ||          \  }}}}|||||d}| j                            |           dS )z^Form a callback function by wrapping, in the same way as the underlying Dash application would)clientside_functionr   r   r   r   N)r   r   rp   rQ   )	r,   r   r+   rh   r   r   r   r   r   s	            r&   r   zDjangoDash.clientside_callbackb  sb    6B6W77
 7
33 1D#)#)"'1E	G G 	&--l;;;;;r%   c                 &    dt          |          z   S )zcURL of an asset associated with this component

        Use a placeholder and insert later
        zassets/)str)r,   
asset_names     r&   get_asset_urlzDjangoDash.get_asset_urlq  s     3z??**r%   )NNFFNNr)   NNN)r    r!   r"   rW   r.   r   r   r   r   r   r   r   r   staticmethodr   r   expanded_callbackr   r   r$   r%   r&   rY   rY      s#         15%*.3&*"&	A& A& A& A&F: : := = = =        (J J J J   8   \0  > !< < <+ + + + +r%   rY   c                   <    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
d	S )
PseudoFlaskzFDummy implementation of a Flask instance, providing stub functionalityc                 ^    ddi| _         i | _        d| _        i | _        d| _        i | _        d S )NDEBUGFPseudoFlaskDummyName)r   	endpointsr=   
blueprints_got_first_requestbefore_request_funcsr0   s    r&   r.   zPseudoFlask.__init__}  s9    &*	"'$&!!!r%   c                     d S r)   r$   r,   argsr-   s      r&   after_requestzPseudoFlask.after_request      r%   c                     fd}|S )Nc                     d         S )Nr   r$   )fr   s    r&   eh_funcz)PseudoFlask.errorhandler.<locals>.eh_func  s    7Nr%   r$   )r,   r   r-   r   s    `  r&   errorhandlerzPseudoFlask.errorhandler  s!    	 	 	 	 	r%   c                 *    |d         }|| j         |<   d S )Nendpoint)r   )r,   r   r-   routes       r&   add_url_rulezPseudoFlask.add_url_rule  s    z" &ur%   c                     d S r)   r$   r   s      r&   before_first_requestz PseudoFlask.before_first_request  r   r%   c                     d S r)   r$   r   s      r&   runzPseudoFlask.run  r   r%   c                     d S r)   r$   r   s      r&   register_blueprintzPseudoFlask.register_blueprint  r   r%   N)r    r!   r"   rW   r.   r   r   r   r   r   r   r$   r%   r&   r   r   {  s        LL' ' '    ' ' '        r%   r   c                     t          | t                    r| S d                    d t          |                                           D                       }d| dS )zConvert an python id (str or dict) into its Dash representation.

    see https://github.com/plotly/dash/blob/c5ba38f0ae7b7f8c173bda10b4a8ddd035f1d867/dash-renderer/src/actions/dependencies.js#L114,c              3   r   K   | ]2\  }}t          j        |           d t          j        |           V  3dS )r   N)jsondumps)r   kvs      r&   	<genexpr>zwid2str.<locals>.<genexpr>  sD      WW41atz!}}66tz!}}66WWWWWWr%   {})
isinstancer   joinsortedrN   )r   datas     r&   wid2strr    sY     #s 
88WW6#))++CVCVWWWWWD===r%   c                        e Zd ZdZ	 d fd	Zd Zd ZddZd Zd	 Z	d
 Z
d Zd Zd ZddZej        j        d             Zd Zd Zd Z fdZ fdZd Zd ZddZd Z fdZddZd Z xZS )r   z3Wrapper around the Plotly Dash application instanceNFc                    || _         t          | j                   | _        t                      | _        || _        | j        |d<   | j        |d<    t                      j        t          fi | || j	        j
        _        || j        j
        _        d| _        |r|| _        nt                      | _        t!          | j                  dk     | _        d| _        d S )Nurl_base_pathnameserverFr   )rm   r   
_flask_appr   	_notflask_base_pathnamesuperr.   r    rq   r   r   rr   
_adjust_id_replacementsdictr   _use_dash_layout_return_embedded)r,   r   r   r   r   r-   	__class__s         r&   r.   zWrappedDash.__init__  s     		**$+&*&9"#>x 	,,V,,,(5%,9) 	(!-D!%D #D$6 7 7! ; %r%   c                     dS )aA  Return True if underlying dash dispatching should be used.

        This stub is present to allow older code to work. Following PR #304
        (see https://github.com/GibbsConsulting/django-plotly-dash/pull/304/files for
        details) this function is no longer needed and therefore should always
        return FalseFr$   r0   s    r&   use_dash_dispatchzWrappedDash.use_dash_dispatch  s	     ur%   c                     | j         S )z
        Indicate if the underlying dash layout can be used.

        If application state is in use, then the underlying dash layout functionality has to be
        augmented with the state information and this function returns False
        )r  r0   s    r&   use_dash_layoutzWrappedDash.use_dash_layout  s     $$r%   c                 Z   |                                  r|s	 |j        }t          j        |                    d                    }|si }t          | j                  }|                    |           | 	                    ||          }t          j
        |t                    }||j        fS )z'Add application state to initial valuesFzutf-8)cls)r  r  mimetyper   loadsdecoder  r  updatewalk_tree_and_replacer   r   )r,   base_responseinitial_argumentsbaseDataInBytesbaseData	overridesreworked_dataresponse_datas           r&   augment_initial_layoutz"WrappedDash.augment_initial_layout  s    !! 	>*; 	> 	> (,:o44W==>> ! 	# " +,,	*+++ 228YGG
='>@ @ @ m444r%   c                    t          |t                    rdD ],}|                     |                    |d          |           -|                    dd          }|Ot	          |          }|                    |i           }|                                D ]\  }}|dvr|||<   |r|||<   t          |t                    r|D ]}|                     ||           dS dS )zEWalk tree of properties and extract identifiers and associated values)childrenpropsNid)r'  optionsr&  r(  )r   r  walk_tree_and_extractrF   r  rN   rC   )r,   r  targetr   r   idValsr   elements           r&   r*  z!WrappedDash.walk_tree_and_extract  s   dD!! 	+, H H**488C+>+>GGGGHHT4((E E2.."&**,, , ,JC"HHH&+s +$*F5MdD!! 	< < <**7F;;;;	< 	<< <r%   c                     t          |t                    ri }i }|                    dd          }t          |t                    r4t          |          }                                D ]\  }}||k    r|} nn|                    |i           }|                                D ]8\  }}|                    |d          }|                     |          }|||<   9|S t          |t                    r fd|D             S |S )z
        Walk the tree. Rely on json decoding to insert instances of dict and list
        ie we use a dna test for anatine, rather than our eyes and ears...
        r(  Nc                 <    g | ]}                     |          S r$   )r  )r   xr!  r,   s     r&   r   z5WrappedDash.walk_tree_and_replace.<locals>.<listcomp>  s)    KKKD..q)<<KKKr%   )r   r  rF   r  rN   r  rC   )	r,   r  r!  responser   thisIDr   r   rs	   ` `      r&   r  z!WrappedDash.walk_tree_and_replace   s2   
 dD!! 	HLXXdD))F&$'' 	9 %OO--  DAq{{'( # #(}}VR88

    1 $$Q--9221i@@AOdD!! 	LKKKKKdKKKKr%   c                     | j         S )z4Underlying flask application for stub implementation)r  r0   s    r&   	flask_appzWrappedDash.flask_app   s
    r%   c                     | j         S )zBase url of this component)r
  r0   s    r&   base_urlzWrappedDash.base_url$  s    ""r%   c                 &     | j         j        |i |S )z=Extract application context from underlying flask application)r  app_contextr   s      r&   r9  zWrappedDash.app_context(  s%    *t*D 5-35 5 	5r%   c                 &     | j         j        |i |S )z>Request context for testing from underluying flask application)r  test_request_contextr   s      r&   r;  z WrappedDash.test_request_context-  s%    3t3T >6<> > 	>r%   c                 ^    || j         d|}n| j         }| j        j        |         d         S )z+Locate endpoint function given name of viewN_	view_func)r
  r	  r   )r,   r=   eps      r&   locate_endpoint_functionz$WrappedDash.locate_endpoint_function2  sA    ...4!BB $B~'+K88r%   c                 z    | j         r|                     |           t          j                            | |          S )z;Overloaded layout function to fix component names as needed)r  _fix_component_idr   rn   fset)r,   r   s     r&   rn   zWrappedDash.layout<  s:     ? 	*""5))){e,,,r%   c                     t          |dd          }|$t          |d|                     |                     	 |j        D ]}|                     |           dS #  Y dS xY w)z,Fix name of component ad all of its childrenr(  N)getattrsetattr_fix_idr&  rB  )r,   	componenttheIDcs       r&   rB  zWrappedDash._fix_component_idD  s     	4..ItT\\%%8%8999	' * *&&q))))* *	DDs   A Ac                 ,    | j         s|S | j        d|S )z+Adjust identifier to include component namez_-_)r  rm   )r,   r=   s     r&   rG  zWrappedDash._fix_idP  s)     	K9994! 	!r%   c                 D    |                      |j                  |_        |S )zUpdate component identifier)rG  component_id)r,   items     r&   _fix_callback_itemzWrappedDash._fix_callback_itemW  s     LL):;;r%   c                      t          |t          t          f          r fd|D             }n                     |          }t	                                          | fd|D              fd|D             |          S )3Invoke callback, adjusting variable names as neededc                 :    g | ]}                     |          S r$   rO  r   r0  r,   s     r&   r   z(WrappedDash.callback.<locals>.<listcomp>`  '    HHHAT44Q77HHHr%   c                 :    g | ]}                     |          S r$   rS  rT  s     r&   r   z(WrappedDash.callback.<locals>.<listcomp>e  s'     L L L!8!8!;!; L L Lr%   c                 :    g | ]}                     |          S r$   rS  rT  s     r&   r   z(WrappedDash.callback.<locals>.<listcomp>f  s'     K K K!8!8!;!; K K Kr%   r   )r   rC   tuplerO  r  r   )r,   r   r   r   r   fixed_outputsr  s   `     r&   r   zWrappedDash.callback\  s     ftUm,, 	<HHHHHHHMM 33F;;Mww L L L LV L L L K K K KU K K K5I   K K 	Kr%   c                     t          |t          t          f          r fd|D             }n                     |          }t	                                          || fd|D              fd|D             |          S )rQ  c                 :    g | ]}                     |          S r$   rS  rT  s     r&   r   z3WrappedDash.clientside_callback.<locals>.<listcomp>m  rU  r%   c                 :    g | ]}                     |          S r$   rS  rT  s     r&   r   z3WrappedDash.clientside_callback.<locals>.<listcomp>s  s'    +W+W+W1D,C,CA,F,F+W+W+Wr%   c                 :    g | ]}                     |          S r$   rS  rT  s     r&   r   z3WrappedDash.clientside_callback.<locals>.<listcomp>t  s'    +V+V+V1D,C,CA,F,F+V+V+Vr%   rX  )r   rC   rY  rO  r  r   )r,   r   r   r   r   r   rZ  r  s   `      r&   r   zWrappedDash.clientside_callbacki  s     ftUm,, 	<HHHHHHHMM 33F;;Mww**+>+8+W+W+W+WPV+W+W+W+V+V+V+VPU+V+V+V@T	 + V V 	Vr%   c                    |                     dg           }t          |          |                     dg           }|d         }|                     d          pt          |          }|                     dg           }fd|D             }||t          |          |||d}	t          di |	}
|
t          _        t          |          dk    r|
|d	<   |                    d
          o|                    d
           }|r|g}n|dd         	                    d          }|                     dd          }| j
        |         }g }||z   D ]}t          |t                    rHd |D             }|r9t          ||          D ](\  }}|                    |d         |d         |           )n:|                     d          }|r#|                    |d         |d         |           |                    |           |                     d          pt          |          }||d<   t          |          t          |d                   k     rdS |d         }|j        2h |j        d ||i fd|                                D             n ||i ||r G d d          } |fd          }|D ]}t          |t$                    rp|	                    d          \  }}|                    ||          rA|                     |i                                |d          }|                    |||           t)          d          S )zOPerform callback dispatching, with enhanced arguments and recording of responser   r   r   r   changedPropIdsc                 @    g | ]}|                     |          d S ))prop_idr   rF   )r   r0  input_valuess     r&   r   z2WrappedDash.dispatch_with_args.<locals>.<listcomp>  s/    ```QL4D4DQ4G4GHH```r%   )r   r   r   r   r   r   r   r   callback_contextz..   z...dash_appNc                 8    g | ]}|                     d           S )r   rc  )r   cis     r&   r   z2WrappedDash.dispatch_with_args.<locals>.<listcomp>  s"    111RVVG__111r%   r(  r9   r   r   EDGECASEEXITr   c                 $    i | ]\  }}|v 	||S r$   r$   )r   r   r   parameters_to_injects      r&   r   z2WrappedDash.dispatch_with_args.<locals>.<dictcomp>  s*    $b$b$bdaMaHaHaQHaHaHar%   c                       e Zd ZdZd Zd ZdS )0WrappedDash.dispatch_with_args.<locals>.LazyJsonzA class to allow delayed the evaluation of a dict (returned by `func`)
                 till the first get(...) is called on the dict.c                     || _         d S r)   )_root_value)r,   r   s     r&   r.   z9WrappedDash.dispatch_with_args.<locals>.LazyJson.__init__  s    '+D$$$r%   c                     t          | j        t                    r|                                 | _        | j                            ||          S r)   )r   rq  r   rF   )r,   rN  defaults      r&   rF   z4WrappedDash.dispatch_with_args.<locals>.LazyJson.get  sD    !$"2H== >+/+;+;+=+=(+//g>>>r%   N)r    r!   r"   rW   r.   rF   r$   r%   r&   LazyJsonro    s>        C C, , ,? ? ? ? ?r%   rt  c                  T    t          j                                       di           S )Nr1  )r   r  rF   )ress   r&   r   z0WrappedDash.dispatch_with_args.<locals>.<lambda>  s    $*S//*=*=j"*M*M r%   .zFUpdating state for dict keys (pattern matching) is not yet implementedr$   )rF   r	   r   r   dashre  r   
startswithendswithrx   callback_mapr   rC   zipr   rQ   r   rN   r   r   NotImplementedError)r,   bodyargMapr   r   r   r   changed_propstriggered_inputscallback_context_infore  single_caser   dacallback_infor   rJ  r   rj  vir   rt  
root_valueoutput_item	output_idoutput_propertyr   rd  rm  rv  s                              @@@r&   dispatch_with_argszWrappedDash.dispatch_with_argsx  s   (B''%f--'2&&hxx	**G.?.G.G!1266````R_``` ""!$V,,(#)! ! +CC-BCC !1 v;;??)9F%& ++D11Kfood6K6KL 	0hGG QrTl((//G ZZ
D)))&1& 	 	A!T"" G11q111 N"%a)) N NB//4"Z."MMMMEE'NN G++AdGQz]AFFFKKNNNN xx	**G.?.G.G!-~ t99s=23333!> ,(#GX%6#G#G (Dc$b$b$b$bfllnn$b$b$bccCC(D+F++C 	x
? 
? 
? 
? 
? 
? 
? 
? ""M"M"M"MNNJ& x xk3// x1<1B1B31G1G.I229oNN S *y < < @ @RV W W//	?ERRR ..vwww
r%   c                 .    | j         }t          |          S )z)Return the app id in a slug-friendly form)rm   r   )r,   pre_slugified_ids     r&   slugified_idzWrappedDash.slugified_id  s    9'(((r%   c                 h    |r|nd}|rd|z  nd}|r|nd}|                                  }d||||dz  S )z
        Return extra html properties to allow individual apps to be styled separately.

        The content returned from this function is injected unescaped into templates.
        zdjango-plotly-dashz-%s iframezT%(prefix)s %(prefix)s-%(template_type)s %(prefix)s-app-%(slugified_id)s%(post_part)s)r  	post_parttemplate_typeprefix)r  )r,   r  postfixr  r  r  s         r&   extra_html_propertiesz!WrappedDash.extra_html_properties  su     ";';'.6EGOOB	)6DH((**e  yEu~ zGrxij ij j 	jr%   c           
         |                                  }|                                 }|                                 }|                                 }|                                 }t          | dd          }| j        r4dd l}	d                    |		                    d| j                            }
nd}
d}| 
                    |||||||
|	          }|S )
Ntitler   r   z/<link rel="icon" type="image/x-icon" href="{}">zassets.static)filenamer  z[
<div id="react-entry-point">
  <div class="_dash-loading">
    Loading...
  </div>
</div>
)metasr  rq   r   rr   	app_entryfaviconrenderer)_generate_scripts_html_generate_css_dist_html_generate_config_html_generate_meta_html_generate_rendererrE  _faviconflaskrk   url_forinterpolate_index)r,   r   r-   rr   rq   r   r  r  r  r  r  
_app_entryindexs                r&   r  zWrappedDash.index  s    --//**,,++--((****,,gv..= 	LLLGNNoFFH HGG GJ &&u#fz7 '  
 r%   c                    | j         s t                      j        di |}|S | j                             |d                    | j                             |d                    | j                             |d                    |d         S )Nrq   r   rr   r  r$   )r  r  r  add_css
add_configadd_scripts)r,   r-   respr  s      r&   r  zWrappedDash.interpolate_index  s    $ 	,577,66v66DK%%fUm444(()9:::))&*;<<<k""r%   c                 4    |r|nt                      | _        dS )zISet a handler for embedded references prior to evaluating a view functionN)r   r  )r,   embedded_holders     r&   set_embeddedzWrappedDash.set_embedded"  s    3B XHXHXr%   c                     d| _         dS )z1Exit the embedded section after processing a viewFN)r  r0   s    r&   exit_embeddedzWrappedDash.exit_embedded&  s     %r%   )NNNFr)   r   )r    r!   r"   rW   r.   r  r  r$  r*  r  r5  r7  r9  r;  r@  r   rn   setterrB  rG  rO  r   r   r  r  r  r  r  r  r  __classcell__)r  s   @r&   r   r     s       99 RW& & & & & &:  % % %5 5 5 54< < <$  @  # # #5 5 5
> > >
9 9 9 9 
[- - -
 
 
! ! !  
K K K K KV V V V Vg g gR) ) )
j j j j(  8
# 
# 
# 
# 
#Y Y Y Y& & & & & & &r%   r   ).rW   ry   r   r   ri   typingr   r   r   rx  r   r   dash._utilsr   r	   django.urlsr
   django.utils.textr   r  r   r   r   
middlewarer   utilr   rs   r   r   r   dataclassesr   r   rl   r<   rG   r?   rA   rD   rJ   rL   rY   r   r  r   r$   r%   r&   <module>r     s   4        ' ' ' ' ' ' ' ' ' '  # # # # # # # # 9 9 9 9 9 9 9 9       % % % % % %       / / / / / / / / & & & & & & 8 8 8 8 8 8 + + + + + + < < < < < < < <,+%%%%%%Yd        ++ + + + + + + + + +@ !       
  ,	" 	" 	" 	" 	" 	" 	" 	"c+ c+ c+ c+ c+ c+ c+ c+N    %   :  F& F& F& F& F&$ F& F& F& F& F&s   &%B B