
    }tfg                    L   U d Z ddlm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	m
Z
 ddlmZmZ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mZmZmZmZ dd	lm Z  er6ddl!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*m+Z+  G d de'      Z,eZ-de.d<   ddgZ/dZ0dZ1dZ2dZ3dZ4dZ5dZ6e6e4e e6e5e ddZ7e3ef	 	 	 	 	 d/dZ8i Z9de.d<   d0dZ: G d d      Z; G d d      Z<d1d Z=d2d!Z>d3d"Z?d4d#Z@d5d$ZAd6d%ZBd7d&ZCd'ZD	 	 	 	 	 	 d8d(ZEd6d)ZFd9d*ZG	 	 	 	 	 	 d:d+ZH	 	 	 	 	 	 d:d,ZId;d-ZJd<d.ZKy)=a  Descriptor for _repr_mimebundle_ attribute that manages the comm channel.

`MimeBundleDescriptor()` takes the place of a `_repr_mimebundle_` method on a class.

- `MimeBundleDescriptor` is a
  [descriptor](https://docs.python.org/3/howto/descriptor.html). When the
  `_repr_mimebundle_` attribute is accessed on an instance of the decorated class, a
  `ReprMimeBundle` instance is created and returned.
- A `ReprMimeBundle` is first and foremost a callable object that implements the
  `_repr_mimebundle_` protocol that jupyter expects.  However, it also manages a
  Comm instance that is used to send the state of the python model to the
  javascript view.  This is done lazily, so that the Comm is only created when the
  `_repr_mimebundle_` is first accessed.
- `ReprMimeBundle` has the logic to get/set the state of the python model, and will keep
  the two in sync ("bind"/"unbind_instance" methods can be used to control this).
    )annotationsN)asdictis_dataclass)TYPE_CHECKINGAnyCallableIterableSequencecastoverload   )FileContentsVirtualFileContents)_ANYWIDGET_ID_KEY_DEFAULT_ESM_ESM_KEY_PROTOCOL_VERSIONput_buffersremove_buffersrepr_mimebundletry_file_contents)_ANYWIDGET_SEMVER_VERSION)Protocol	TypeAlias	TypeGuard)CommMessagec                      e Zd ZddZy)	_GetStatec                     y N )selfobjincludes      _/var/www/html/software/conda/envs/higlass/lib/python3.12/site-packages/anywidget/_descriptor.py__call__z_GetState.__call__<   s        N)r#   r   r$   set[str] | Nonereturndict)__name__
__module____qualname__r&   r!   r'   r%   r   r   ;   s    Kr'   r   r   SerializableMimeBundleDescriptorReprMimeBundle_repr_mimebundle__get_anywidget_state_set_anywidget_statezjupyter.widgetAnyModelAnyView	anywidget)_model_module_model_name_model_module_version_view_module
_view_name_view_module_version_view_countc                D    dd l } |j                  | d|idt        i      S )Nr   versionstate)target_namemetadatadata)commcreate_comm_ANYWIDGET_STATE)rA   r?   rD   s      r%   	open_commrG   W   s0     4W%'( r'   z"dict[int, comm.base_comm.BaseComm]_COMMSc                $   t        |       }|t        vrat               t        |<   t        j                  t
              5  t        j                  | t        j                  |       ddd       t        |   S t        |   S # 1 sw Y   t        |   S xY w)zGet or create a communcation channel for a given object.

    Comms are cached by object id, so that if the same object is used in multiple
    places, the same comm will be used. Comms are deleted when the object is garbage
    collected.
    N)	idrH   rG   
contextlibsuppress	TypeErrorweakreffinalizepop)r#   obj_ids     r%   	_comm_forrR   i   sw     WFV"v  + 	6 S&**f5	6 &>6&>		6 &>s   &A>>Bc                  t    e Zd ZdZdddd	 	 	 	 	 	 	 	 	 ddZddZedd       Zedd       Z	 	 	 	 	 	 dd	Zy
)r/   a  Descriptor that builds a ReprMimeBundle when accessed on an instance.

    The `__get__` method is called when the descriptor's name is accessed on a class or
    instance.  It returns a `ReprMimeBundle` instance, which is a callable that
    implements the `_repr_mimebundle_` protocol that jupyter expects, but also manages
    the comm channel between the python model and the javascript view.

    For more on descriptors, see: <https://docs.python.org/3/howto/descriptor.html>

    Parameters
    ----------
    follow_changes : bool, optional
        If `True` (default), the state of the python model will be updated whenever the
        state of the javascript view changes (and vice versa).
    autodetect_observer : bool, optional
        If `True` (default), an attempt will be made to find a known observer-pattern
        API on the object (such as a psygnal.SignalGroup or traitlets.HasTraits) and
        use it to automatically send state changes to the javascript view.  If `False`,
        the javascript view will only be updated when the `send_state()` method is
        explicitly called.
    no_view : bool, optional
        If `True`, the callable will return `None` instead of a mimebundle. This is
        useful for cases where you want to use the comm channel to send state updates
        to the front end, but don't want to display anything in the notebook
        (i.e., A DOM-less widget).  Defaults to `False`.
    **extra_state : Any, optional
        Any extra state that should be sent to the javascript view (for example,
        for the `_esm` anywidget field.)  By default, `{'_esm': _DEFAULT_ESM}` is added
        to the state.

    Examples
    --------
    Note that *technically* you could name the attribute anything you want
    but it probably only makes sense to call it '_repr_mimebundle_'.

    >>> class Foo:
    ...     _repr_mimebundle_ = MimeBundleDescriptor()
    >>> foo = Foo()

    in a jupyter notebook, this line will now access `_repr_mimebundle_`, and turn the
    descriptor into an instance of `ReprMimeBundle`, which spins up a comm channel, sets
    up state synchronization, and, when called, returns a mimebundle dict that includes
    the comm id.

    >>> foo
    TF)follow_changesautodetect_observerno_viewc                  |j                  t        t               || _        t        | _        || _        || _        || _        | j                  j                         D ]"  \  }}t        |      }||| j                  |<   $ y r    )
setdefaultr   r   _extra_state
_REPR_ATTR_name_follow_changes_autodetect_observer_no_viewitemsr   )r"   rT   rU   rV   extra_statekvfile_contentss           r%   __init__zMimeBundleDescriptor.__init__   s|     	x6'
-$7!%%++- 	5DAq-a0M('4!!!$		5r'   c                    || _         y)zCalled when this descriptor is assigned to an attribute on a class.

        In most cases, we won't *want* `name` to be anything other than
        `'_repr_mimebundle_'`.
        N)r[   )r"   ownernames      r%   __set_name__z!MimeBundleDescriptor.__set_name__   s     
r'   c                     y r    r!   r"   instancerf   s      r%   __get__zMimeBundleDescriptor.__get__   s    LOr'   c                     y r    r!   rj   s      r%   rl   zMimeBundleDescriptor.__get__   s    HKr'   c                   || S 	 t        || j                  | j                  | j                        }| j                  r|j                          t        j                  t        t              5  t        || j                  |       ddd       |S # t        $ r }t        j                  d| d        d}~ww xY w# 1 sw Y   |S xY w)a  Called when this descriptor's name is accessed on a class or instance.

        Examples
        --------
        >>> class Foo:
        ...     _repr_mimebundle_ = MimeBundleDescriptor()
        ...
        >>> Foo._repr_mimebundle_  # same as Foo._repr_mimebundle_.__get__(None, Foo)
        >>> foo = Foo()
        >>> foo._repr_mimebundle_  # same as Foo._repr_mimebundle_.__get__(foo, Foo)
        N)rU   r`   rV   zError in Anywidget repr:
r   
stacklevel)r0   r]   rY   r^   r\   sync_object_with_view	ExceptionwarningswarnrK   rL   AttributeError
ValueErrorsetattrr[   )r"   rk   rf   repr_objes        r%   rl   zMimeBundleDescriptor.__get__   s     K	%$($=$= --	H ##..0   < 	4 Hdjj(3		4 #  	 MM6qc:qI		4 s$   A	B -B;	B8B33B8;CN)
rT   boolrU   rz   rV   rz   r`   r   r)   None)rf   typerg   strr)   r{   )rk   r{   rf   r|   r)   r/   )rk   objectrf   r|   r)   r0   )rk   zobject | Nonerf   r|   r)   z%ReprMimeBundle | MimeBundleDescriptor)r+   r,   r-   __doc__rd   rh   r   rl   r!   r'   r%   r/   r/   ~   s    -d  $$(5 5 "	5
 5 5 
5* O OK K/%/.2/	./r'   c                  p    e Zd Z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
y)r0   aO  Callable object that behaves like a `_repr_mimebundle_` method...

    which is to say, it returns a mimebundle (mapping of mimetypes to data) when called.

    This object *also* controls an Comm channel between the front-end js view
    and some python model object (`obj`),

    Parameters
    ----------
    obj : object
        The python model object which is being represented by the view.  Most likely
        this will be a dataclass instance that has been made "evented" by the anywidget
        decorator... but we type it as `object` to allow for other use cases, to make it
        clearer what protocols we expect from the object.
    autodetect_observer : bool, optional
        If `True` (default), an attempt will be made to find a known observer-pattern
        API on the object (such as a psygnal.SignalGroup or traitlets.HasTraits) and
        use it to automatically send state changes to the javascript view.  If `False`,
        the javascript view will only be updated when the `send_state()` method is
        explicitly called.
    no_view : bool, optional
        If `True`, the callable will return `None` instead of a mimebundle. This is
        useful for cases where you want to use the comm channel to send state updates
        to the front end, but don't want to display anything in the notebook
        (i.e., A DOM-less widget).  Defaults to `False`.
    extra_state : dict, optional
        Any extra state that should be sent to the javascript view (for example,
        for the `_esm` anywidget field.)  By default, `{'_esm': DEFAULT_ESM}` is added
        to the state.
    Nc                    | _         |xs i j                          _         j                  j                  t        t                     | _        	 t        j                   j                         _
        t               _        t!                _        t%               _        t)               _         j                  j-                         D ]U  \  }}t/        |t0        t2        f      st5        |       j                  |<   |j6                  j8                  |fd fd       }W y # t        $ r( fd _
        t        j                  d dd       Y w xY w)Nc                      S r    r!   r#   s   r%   <lambda>z)ReprMimeBundle.__init__.<locals>.<lambda>4  s     r'   zAnywidget: z is not weakrefable, so it will not be garbage collected until the view is closed. Please consider adding `__slots__ = ('__weakref__',)` to your class definition.   ro   c                F    | j                   |<   j                  |       y r    )rY   
send_state)new_contentskeyr"   s     r%   
_on_changez+ReprMimeBundle.__init__.<locals>._on_changeJ  s    -9D%%c*OOC(r'   )r   r}   r   r}   r)   r{   )r]   copyrY   rX   r   _anywidget_idr^   rN   ref_on_obj_deleted_objrM   rs   rt   rR   _commset_disconnectorsdetermine_state_getter
_get_statedetermine_state_setter
_set_stater_   
isinstancer   r   r}   changedconnect)r"   r#   rU   r`   rV   r   valuer   s   ``      r%   rd   zReprMimeBundle.__init__$  s7    %8!(.B446$$%6c8JK
	+2;;sD<P<P+QDI s^
 .1U 1505++113 	)JC%"5|!DE),U!!#&&&=@ ) ')	))  	#DIMMcU #K K 		s   %D+ +.EEc                X    | j                          | j                  j                          y)z)Called when the python object is deleted.N)unsync_object_with_viewr   close)r"   r   s     r%   r   zReprMimeBundle._on_obj_deletedO  s    $$&

r'   c                   | j                         }|y|t        |t              r|hn
t        |      }i | j	                  ||      | j
                  }|(|j                         D ci c]  \  }}||v s|| }}}|syt        |      \  }}}t        | j                  dd      r$d||d}| j                  j                  ||       yyc c}}w )zSend state update to the front-end view.

        Parameters
        ----------
        include : set of str, optional
            If provided, only send the state for the keys in this set.  Otherwise,
            send all state.
        Nr$   kernelupdate)methodr@   buffer_paths)rC   buffers)r   r   r}   r   r   rY   r_   r   getattrr   send)	r"   r$   r#   r@   ra   rb   r   r   msgs	            r%   r   zReprMimeBundle.send_stateU  s     iik;#-gs#;wiWGN4??3?8ND<M<MN ',kkmDdaqG|QTDED (6e'<$|W4::x.%|TCJJOOgO6 / Es   *C7Cc                   | j                         }|y|d   d   }|d   dk(  r4d|v r/|d   }d|v rt        ||d   |d          | j                  ||       yy|d   d	k(  r| j                          yt	        d
|d    d      )zwCalled when a msg is received from the front-end.

        (assuming `sync_object_with_view` has been called.)
        NcontentrC   r   r   r@   r   r   request_statezUnrecognized method: zB.  Please report this at https://github.com/manzt/anywidget/issues)r   r   r   r   rv   )r"   r   r#   rC   r@   s        r%   _handle_msgzReprMimeBundle._handle_msgt  s    
 iik;9~f%>X%$W!T)tN';S^LU+	  (^.OO 'X'7 8< < r'   c                    | j                   ryt        | j                  j                  t	        | j                                     S )z=Called when _repr_mimebundle_ is called on the python object.N)model_id	repr_text)r^   r   r   comm_idreprr   )r"   kwargss     r%   r&   zReprMimeBundle.__call__  s0     ==

(:(:d499;FWXXr'   c                   |r5| j                   j                  | j                         | j                          |r| j                  r| j                         }|t        d      | j                  rt        j                  dd       yt        t        fD ]4  } ||| j                        }|s| j                  j                  |        y t        j                  d| dd       yyy)a  Connect the front-end to changes in the model, and vice versa.

        Parameters
        ----------
        py_to_js : bool, optional
            If True (the default), changes in the python model will be reflected in the
            front-end.
        js_to_py : bool, optional
            If True (the default), changes in the front-end will be reflected in the
            python model.
        NzCannot sync a deleted objectz$Refusing to re-sync a synced object.r   ro   zCould not find a notifier on z^ (e.g. psygnal, traitlets). Changes to the python object will not be reflected in the JS view.)r   on_msgr   r   r]   r   RuntimeErrorr   rs   rt   _connect_psygnal_connect_traitletsadd)r"   py_to_jsjs_to_pyr#   	connector
disconnects         r%   rq   z$ReprMimeBundle.sync_object_with_view  s     JJd../OO11))+C{"#ABB""DQRS /0BC 	&sDOO<
''++J7	 3C5 9   !	- 28r'   c                   | j                   j                  d       | j                  rOt        j                  t
              5   | j                  j                                 ddd       | j                  rNyy# 1 sw Y   xY w)zEDisconnect the view from changes in a model instance, and vice versa.N)r   r   r   rK   rL   rr   rP   )r"   s    r%   r   z&ReprMimeBundle.unsync_object_with_view  sb    

$!!$$Y/ ,)##'')+, !!, ,s    A88B)TNF)r#   r~   rU   rz   r`   zdict[str, Any] | NonerV   rz   r    )r   zweakref.ReferenceType | Noner)   r{   )r$   zstr | Iterable[str] | Noner)   r{   )r   r   r)   r{   )r   zSequence[str]r)   ztuple[dict, dict] | None)TT)r   rz   r   rz   r)   r{   r)   r{   )r+   r,   r-   r   rd   r   r   r   r&   rq   r   r!   r'   r%   r0   r0     s}    D %)-1)))) ")) +	))
 ))V7>FY 7;../3.	.`,r'   c                \    t        |       j                   dt        |       j                   S )z9Return a unique id for an object, to send to the JS side..)r|   r,   r+   r   s    r%   r   r     s)    3i""#1T#Y%7%7$899r'   c                *   t        t        |       t              rt        t        |       t              S t	        |       rd S t        |       rt        S t        |       rt        | d      rt        S t        S t        |       rt        S t        d| d      )a  Autodetect how `obj` can be serialized to a dict.

    This looks for various special methods and patterns on the object (e.g. dataclass,
    pydantic, etc...), and returns a callable that can be used to get the state of the
    object as a dict.

    As an escape hatch it first looks for a special method on the object called
    `_get_anywidget_state`.

    Returns
    -------
    state_getter : Callable[[object], dict]
        A callable that takes an object and returns a dict of its state.
    c                    t        |       S r    )r   r#   r$   s     r%   r   z(determine_state_getter.<locals>.<lambda>  s
    F3K r'   
model_dumpz,Cannot determine a state-getting method for zI. Please implement a `_get_anywidget_state()` method that returns a dict.)hasattrr|   _STATE_GETTER_NAMEr   r   _is_traitlets_object_get_traitlets_state_is_pydantic_model_get_pydantic_state_v2_get_pydantic_state_v1_is_msgspec_struct_get_msgspec_staterM   r   s    r%   r   r     s      tCy,- tCy"455C 0/C ###3%))%%#!! 
6sg >R 	R r'   c                N    |j                         D ]  \  }}t        | ||        y)z?A default state setter that just sets attributes on the object.N)r_   rw   )r#   r@   r   vals       r%   _default_set_stater     s'    KKM SS#r'   c                r    t        t        |       t              rt        t        |       t              S t        S )a7  Autodetect how `obj` can update its state from a dict.

    The default implementation just sets attributes on the object.

    Returns
    -------
    state_setter : Callable[[object, dict], None]
        A callable that takes an object and a dict of its state, and updates the object
        accordingly.
    )r   r|   _STATE_SETTER_NAMEr   r   r   s    r%   r   r     s+     tCy,-tCy"455r'   c                   t         rddl}nt        j                  j	                  d      }|yt        | dd      }t        ||j                        r|S t        j                  t        t        t              5  t        |       j                         D ]%  }t        ||j                        s|c cddd       S  	 ddd       y# 1 sw Y   yxY w)z*Look for a psygnal.SignalGroup on the obj.r   Npsygnalevents)r   r   sysmodulesgetr   r   SignalGrouprK   rL   ru   RecursionErrorrM   varsvalues)r#   r   r   attrs       r%   _get_psygnal_signal_groupr   *  s    ++//), S(D)F&'--. 
			
  I$$& 	D$ 3 34 	  s   63C*C7CCc                `    t        |       j                  dfd       dfd}|S y)a  Check if an object has a psygnal.SignalGroup, and connect it to send_state.

    Returns
    -------
    disconnect : Callable | None
        A callable that disconnects the psygnal.SignalGroup from send_state, or None
        if no psygnal.SignalGroup was found.
    Nc                @     | j                   j                  h       y r    )signalrg   )eventr   s    r%   _on_psygnal_eventz+_connect_psygnal.<locals>._on_psygnal_eventP  s    ))*+r'   c                 (    j                          y r    )r   )r   r   s   r%   _disconnectz%_connect_psygnal.<locals>._disconnectT  s    /0r'   )r   zpsygnal.EmissionInfor)   r{   r   )r   r   )r#   r   r   r   r   s    ` @@r%   r   r   C  s;     's+F		, 
	,	1 r'   c                t    t         j                  j                  d      }|t        | |j                        S dS )zAReturn `True` if an object is an instance of traitlets.HasTraits.	traitletsF)r   r   r   r   	HasTraits)r#   r   s     r%   r   r   ^  s1    ,I3<3H:c9../SeSr'   syncc                6    t         di} | j                  di |S )z0Get the state of a traitlets.HasTraits instance.Tr!   )_TRAITLETS_SYNC_FLAGtrait_values)r#   r$   r   s      r%   r   r   n  s$     #D)F3%f%%r'   c                    t        |       sydfd| j                  t        | j                  d                   t	        j
                  |       dfd}|S )	aI  Check if an object is a traitlets.HasTraits, and connect it to send_state.

    Only traits with tagged with `sync=True` will be synced.

    Returns
    -------
    disconnect : Callable | None
        A callable that disconnects the traitlets.HasTraits from send_state, or None
        if no traitlets.HasTraits was found.
    Nc                     | d   h       y )Nrg   r!   )changer   s    r%   _on_trait_changez,_connect_traitlets.<locals>._on_trait_change  s    F6N#$r'   T)r   )namesc                 <            } | | j                         y y r    )	unobserve)r#   r   obj_refs    r%   r   z'_connect_traitlets.<locals>._disconnect  s!    i?MM*+ r'   )r   r*   r)   r{   r   )r   observelisttraitsrN   r   )r#   r   r   r   r   s    ` @@r%   r   r   v  sS      $% KK SZZTZ-B(CKDkk#G,
 r'   c                t    t         j                  j                  d      }|t        | |j                        S dS )z@Return `True` if an object is an instance of pydantic.BaseModel.pydanticF)r   r   r   r   	BaseModel)r#   r   s     r%   r   r     s1    {{z*H2:2F:c8--.QEQr'   c                L    t        j                  | j                  |            S )zGet the state of a pydantic BaseModel instance.

    To take advantage of pydantic's support for custom encoders (with json_encoders)
    we call obj.json() here, and then cast back to a dict (which is what
    the comm expects).
    r   )jsonloadsr   s     r%   r   r     s     ::chhwh/00r'   c                (    | j                  d|      S )z4Get the state of a pydantic (v2) BaseModel instance.r   )moder$   )r   r   s     r%   r   r     s     >>vw>77r'   c                t    t         j                  j                  d      }|t        | |j                        S dS )z<Return `True` if an object is an instance of msgspec.Struct.msgspecF)r   r   r   r   Struct)r#   r   s     r%   r   r     s/    kkooi(G.5.A:c7>>*LuLr'   c                J    ddl }t        t         |j                  |             S )z+Get the state of a msgspec.Struct instance.r   N)r   r   r*   to_builtins)r#   r$   r   s      r%   r   r     s"    
 )g))#.//r'   )rA   r}   r?   r}   r)   comm.base_comm.BaseComm)r#   r~   r)   r  )r#   r~   r)   r}   )r#   r~   r)   r   )r#   r~   r@   r*   r)   r{   )r#   r~   r)   zCallable[[object, dict], None])r#   r~   r)   zpsygnal.SignalGroup | None)r#   r~   r   r   r)   zCallable | None)r#   r   r)   zTypeGuard[traitlets.HasTraits])r#   ztraitlets.HasTraitsr$   r(   r)   r.   )r#   r   r)   zTypeGuard[pydantic.BaseModel])r#   zpydantic.BaseModelr$   r(   r)   r.   )r#   r   r)   zTypeGuard[msgspec.Struct])r#   zmsgspec.Structr$   r(   r)   r*   )Lr   
__future__r   rK   r   r   rs   rN   dataclassesr   r   typingr   r   r   r	   r
   r   r   _file_contentsr   r   _utilr   r   r   r   r   r   r   r   _versionr   rD   r   r   r   r   typing_extensionsr   r   r   
_protocolsr   r   r.   __annotations____all__rZ   r   r   _TARGET_NAME_ANYWIDGET_MODEL_NAME_ANYWIDGET_VIEW_NAME_ANYWIDGET_JS_MODULErF   rG   rH   rR   r/   r0   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r!   r'   r%   <module>r     s  " #   
   ,   >	 	 	 0@@'LH L "L)!!#3
4 
+ + "   "  *(6(&5  $4E		.1		 .0* /*C CLQ, Q,n:
-`(26T  &	&'6&&@R	1		1&5	1	18	8&588M0r'   