o
    qoi                     @   s  d Z ddlZddlZddl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mZmZmZmZmZmZmZmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ dd	lmZ dd
lmZ ddlmZ ddlm Z  ddlm!Z! ddl"Z"g dZ#dZ$dZ%dZ&ddddZ'ddddZ(G dd dZ)e) Z*ej+ddG dd dZ,ej+G dd dZ-ej+ddG d d! d!Z.ej+ddG d"d# d#Z/ej+G d$d% d%Z0ee
gee1e1f f Z2eeee1 e2f  Z3dOd'e1d(e1fd)d*Z4G d+d, d,Z5		dPd-e
d.ee6 d/ee6 d(e"j7fd0d1Z8dQddd2d3d4eej9 d5ee
 d6ee
 d7e:d(e"j7f
d8d9Z;G d:d; d;eZ<d4ej9d5e
d(e
fd<d=Z=d>e
d?ee6 fd@dAZ>dBdC Z?dDdE Z@d>e
d(ee6 fdFdGZAd>e
d(ee6 fdHdIZBdJe
dKee6 dLee6 fdMdNZCdS )RzHProvides a renderer to visualize a DAG of `fdl.Buildable`s via Graphviz.    N)
AnyCallableDictList
NamedTupleOptionalSetTupleTypeUnion)config)daglish)diffing)graphviz_custom_object)partial)tag_type)tagging)formatting_utilities)daglish_legacy)	visualize)z#ffc0cbz#90ee90z#fff8dcz#ffa07az#add8e6z#ff8c00z#8fbc8fz#adff2fz#ff6347z#db7093z#f0e68cz#32cd32z#00bfffz#7b68eez#eeeeee	#00000030z#606060z#ffc0c0:#ffa0a0z#c0ffc0:#80c080z#dddddd:#bbbbbb)deladdNz	#ff000030z	#00a00030c                   @      e Zd ZdZdS )_TrimmedSentinelzSentinel object used to flag trimmed dictionaries when rendering diffs.

  `d` was trimmed if `_TRIMMED_SENTINEL in d`, and `d[_TRIMMED_SENTINEL]` is the
  number of items that were trimmed.
  N__name__
__module____qualname____doc__ r    r    H/home/ubuntu/.local/lib/python3.10/site-packages/fiddle/_src/graphviz.pyr   H   s    r   T)frozenc                   @   r   )_NoValuez=Sentinel object used by _ChangedValue to mark missing values.Nr   r    r    r    r!   r#   S   s    r#   c                   @   s2   e Zd ZU dZeeef ed< eeef ed< dS )_ChangedValuez5Node to visualize a value that was changed by a diff.	old_value	new_valueN)r   r   r   r   r   r   r#   __annotations__r    r    r    r!   r$   X   s   
 r$   c                   @      e Zd ZU dZejed< dS )	_AddedTagz'Node to visualize tags added by a diff.tagNr   r   r   r   r   TagTyper'   r    r    r    r!   r)   _      
 r)   c                   @   r(   )_RemovedTagz)Node to visualize tags removed by a diff.r*   Nr+   r    r    r    r!   r.   e   r-   r.   c                   @   sh   e Zd ZU dZeej ed< eed< eed< e	e
eeef f ed< e	e
eeejeef  f ed< dS )_ChangedBuildablez9Node to visualize a buildable that was changed by a diff.buildable_typeold_callablenew_callable	argumentstagsN)r   r   r   r   r
   
config_lib	Buildabler'   r   r   strr   r$   r   r   r,   r)   r.   r    r    r    r!   r/   k   s   
 $r/   皙?rgb_strreturnc                    sX    fddt dt dD }tj| \}}}t||| |}dddd |D  S )z%Adjust luminance by luminance_factor.c                    s"   g | ]}t  ||d   dqS )      )int).0ir9   r    r!   
<listcomp>~   s   " z_darken.<locals>.<listcomp>   r;   # c                 S   s   g | ]	}d  t|qS )z{:02x})formatr=   )r>   cr    r    r!   rA      s    )rangelencolorsys
rgb_to_hls
hls_to_rgbjoin)r9   luminance_factorrgbhlsr    r@   r!   _darken|   s   rR   c                   @   s  e Zd ZdZ			dAdededefdd	Zd
d Zde	de
fddZde	de
fddZde
dee	ge
f fddZdedfdede
de
fddZdejde
fddZde	dejfdd Zd!e	fd"d#Zde	fd$d%Zd&ejde
de
fd'd(Zdejde
de
fd)d*Zdejde
de
fd+d,Zefde	de
fd-d.Zde	fd/d0Zd1eee	 e e	 f de
fd2d3Z!dde"dfd4e#ee
e$f e	f d5e%e
 d6e%e
 d7ee	ge
f d8e%e#e
e&e'j( f  de
fd9d:Z)de
fd;d<Z*de	de
fd=d>Z+de
fd?d@Z,dS )B_GraphvizRendererzEEncapsulates state maintained while rendering a `Config` to Graphviz.N
   Finstance_colorsmax_sequence_elements_per_rowcurved_edgesc                 C   sd   |pt | _|| _ddddddi| _ddi| _dd	d
| _ddddd| _|r,d| jd< |   dS )a  Initializes the render.

    Args:
      instance_colors: Optional list of HTML hexadecimal color codes (e.g.
        '#a1b2c3') to override the default set used to assign colors to
        `fdl.Buildable` instances encountered during rendering. Colors are
        assigned in order (and repeated if there are more instances than
        provided colors); or a function that maps objects to tuples
        `(header_color, edge_color)`.
      max_sequence_elements_per_row: When rendering sequences, up to this many
        elements will be included in a single row of the output table, with
        additional rows added to render remaining elements.
      curved_edges: If true, then draw edges using curved splines.
    tabler   rB      )bordercellspacing
cellbordercellpaddingoverlapfalser   3)colorpenwidthCourier10none0)fontnamefontsizeshapemargincurvedsplinesN)_BUILDABLE_INSTANCE_COLORS_instance_colors_max_sequence_elements_per_row_attr_defaults_graph_attr
_edge_attr
_node_attr_clear)selfrU   rV   rW   r    r    r!   __init__   s&   

	
z_GraphvizRenderer.__init__c                 C   sD   t j| j| j| jd| _i | _d| _t	 | _
t	 | _t | _dS )z/Resets all state associated with this renderer.)
graph_attr	node_attr	edge_attrN)graphvizGraphrq   rs   rr   _dot_node_id_by_value_id_current_id	itertoolscount_config_counter_port_counterset_shared_value_ids)ru   r    r    r!   rt      s   

z_GraphvizRenderer._clearvaluer:   c                 C   s:   t | jr| |d S | jt| }| j|t| j  S )z-Returns the header color for the given value.r   )callablern   r}   idrH   )ru   r   node_idr    r    r!   _color   s   
z_GraphvizRenderer._colorc                 C   sL   t | jr| |d S | jt| }| j|t| j  }t|}| dS )z1Returns the color for an edge to the given value.rB   80)r   rn   r}   r   rH   rR   )ru   r   r   
node_colordarkened_edge_colorr    r    r!   _edge_color   s   

z_GraphvizRenderer._edge_colorr*   c                    sD   i | j i |}dd | D  dtdtf fdd}|S )a  Returns a function that creates HTML tags of type `tag`.

    Example:

        td = self.tag('td', colspan=2)
        td('cell contents') => '<td colspan="2">cell contents</td>

    Args:
      tag: The type of tag to create (e.g. 'table', 'font', etc).
      **kwargs: Attributes to apply to the tag. Tag-specific default values for
        attributes can be provided in `self._attr_defaults`. The values provided
        here in **kwargs take precedence over defaults.

    Returns:
      A function that can be called with contents to put inside the tag, and
      returns HTML markup enclosing the contents inside `tag`. If the given
      contents is a list or tuple, the list elements are automatically
      concatenated. Otherwise, the contents are simply formatted as a string.
    c                 S   s6   g | ]\}}|d urd| dd d| dndqS )N _-z=""rD   )replace)r>   keyr   r    r    r!   rA      s    $z)_GraphvizRenderer.tag.<locals>.<listcomp>contentsr:   c                    s:   t | ttfrd| } d d  d|  d dS )NrD   <>z</)
isinstancelisttuplerL   )r   
attributesr*   r    r!   tag_fn   s   
"z%_GraphvizRenderer.tag.<locals>.tag_fn)rp   getitemsr   r7   )ru   r*   kwargsattr_valuesr   r    r   r!   r*      s   z_GraphvizRenderer.tagr;   solidcolspanbgcolorstylec                 C   s(   |  d}| j d|||d}|||S )zConstructs a header table row.trtdr   r   r   )r*   )ru   headerr   r   r   r   	header_tdr    r    r!   _header_row   s   
z_GraphvizRenderer._header_rowr   c                 C   s   t |tjtjfrdS dS )Ndashedr   )r   r   Partial
ArgFactory)ru   r   r    r    r!   _config_header_style   s   z&_GraphvizRenderer._config_header_stylec                 C   s&   |  | | | | j}|   |S )zARenders the given value, recursively rendering any nested values.)_find_shared_value_ids_add_node_for_valuer|   rt   )ru   r   dotr    r    r!   render  s
   

z_GraphvizRenderer.renderrootc                    s&   t   fddt| dS )z@Adds ids of shared values in `root` to `self._shared_value_ids`.c                 3   s    ~ t |s	|S t|v r jt| |S t|tr-t|j	 t|j
 nt|tr9t|j t| d V S N)r   is_memoizabler   r   r   r   r$   r   traverse_with_pathr%   r&   r/   r3   pathr   ru   visitvisited_idsr    r!   r     s   


z7_GraphvizRenderer._find_shared_value_ids.<locals>.visitNr   r   r   )ru   r   r    r   r!   r     s   z(_GraphvizRenderer._find_shared_value_idsc                 C   s   t || jv r	dS | j}t| j| _| j| jt |< | || |}tjt	t
ttf}t||sZt|sZ| d}| d}| d}|| jt|j| |dd|||g}| jt| jd| d || _dS )	zAdds a node for `value` to the graphviz graph `self._dot`.

    Also sets self._node_id_by_value[id(value)] to the node's graphviz id,
    and sets `_current_id` to the node's graphviz id.

    Args:
      value: The value that should be rendered.
    NrX   r   r   rB   )r   r   r   r   )r   r}   r~   nextr   _render_valuer   r5   r6   dictr   r   r/   r   r   is_namedtuple_instancer*   r   typer   r|   noder7   )ru   r   last_id
html_labelalready_tabular_typesrX   r   r   r    r    r!   r   !  s.   	






z%_GraphvizRenderer._add_node_for_valuetagged_valuec                 C   s   | j ddd}|jj}ddd |jD }|t| d| d }| j|d	|d
d}|  d}|  d}	| j ddd}
| |j	}|||	|
|ggS )z0Returns an HTML string rendering `tagged_value`.font   
point_sizez, c                 s   s    | ]}t |jV  qd S r   )reprname)r>   r   r    r    r!   	<genexpr>E  s    z9_GraphvizRenderer._render_tagged_value.<locals>.<genexpr>z: &nbsp;rB   r   r   rX   r   r   leftalign)
r*   	__class__r   rL   r4   htmlescaper   _render_nested_valuer   )ru   r   r   	type_font	type_name	key_namestitler   rX   r   value_tdrendered_valuer    r    r!   _render_tagged_value@  s   

z&_GraphvizRenderer._render_tagged_valuec              
   C   s   |  |}| jddd}|jj}tt|dtt|dtt|}|t	| dd t	| }| j
|||d}|jrN| j|j|t|jd	}	|	S | d
}
| d}|
|| 
|dg}	|	S )8Returns an HTML string rendering the Buildable `config`.r   r   r   r   r   :r   r   r   )r   key_format_fnr4   rX   r?   no arguments)r   r*   r   r   getattrr5   get_callabler   r   r   r   __arguments___render_dictr7   __argument_tags__)ru   r   r   r   r   r   fn_or_cls_namer   r   labelrX   italicsr    r    r!   _render_configO  s6   


	

z _GraphvizRenderer._render_configc              	   C   s*  |  |}| jddd}|jj}| jddd}| d}| d}| jdtd	 d
}	| jdtd d
}
|j|ju rM|t| dd t|jj }n$||||t| d|	t|jj|d|
t|jjg}| j	|||d}|j
s| 	| dd}nd}| j|j
||t|jdS )r   r   r   r   rX   rf   )r\   r   r   r   r   r   r   r   &rarr;r   r?   r   N)r   footerr   r4   )r   r*   r0   r   _DIFF_FILL_COLORSr1   r2   r   r   r   r3   r   r7   r4   )ru   r   r   r   r   r   rX   r   r   td_oldtd_newr   r   r   r    r    r!   _render_changed_buildablel  s@   


z+_GraphvizRenderer._render_changed_buildablec                 C   s  |t ju r| ddS t|tjr|| S t|t jr#| ||S t|t	j
r/| ||S t|tr9| |S t|trD| ||S t|trX| j|| jt|j|ddS t|ro| j| | jt|j|dtdS t|ttfr|| ||S | |S )z)Returns an HTML string rendering `value`.r?   ztagging.NO_VALUEr   )r   )r   r   )r   NO_VALUEr*   r   r   CustomGraphvizBuildable__render_value__TaggedValueClsr   r5   r6   r   r$   _render_changed_valuer/   r   r   r   r   r   r   r   r   _asdictr7   r   r   _render_sequence_render_leaf)ru   r   ra   r    r    r!   r     s2   







z_GraphvizRenderer._render_valuec                 C   s   t jtf}t||ot|tj }t|| jv s|s| |S | 	| | j
t| }t| j}t| |d}| jj| j d| d| dfi | | |}| jd|d}| d}	| jd|| ||d}
||	|
d	S )
a  Returns an HTML string rendering `value` inside another object.

    If `value` is a `Buildable` or a shared memoizable value, then it is
    rendered as its own separate unnested graph node (if it hasn't been
    already). The nested rendering is then just a single-celled table whose
    color matches the header color of the separate node rendering. The nested
    cell is then connected via an edge to the separate rendering.

    Otherwise, this returns `self._render_value(value)`.

    Args:
      value: The nested value to render.

    Returns:
      The HTML markup for the rectangle (a single-celled table) that is
      connected by an edge to the node for `value`.
    )ra   r   z:crX   )r   r   r   )portr   r   rD   )r5   r6   r/   r   r   r   r   r   r   r   r}   r   r   r   r   r|   edger~   r   r*   r   )ru   r   buildable_typesis_standard_buildabler   r   
edge_attrsr   rX   r   r   r    r    r!   r     s$   



*

z&_GraphvizRenderer._render_nested_valuesequencec              	   C   sT  |  d}|  d}|  d}| j ddtd}| j ddd}| j dd	d
}t|j}	t|tjr2d}	|s<t|tjs<dS g g }
}t|D ]\}}|
|| 	| |||| qEt|tjrqt
|dg }|
|d | j}tt||}| j|	||dg}tdt||D ]}|||
|||  |||||  g q||S )z<Renders the given sequence (list or tuple) as an HTML table.rX   r   r   r   )r]   r   r      r   r;   )rowspanSequencez[]z...)r   r   )r*   _DEFAULT_HEADER_COLORr   r   r   r   
ListPrefix	enumerateappendr   r   ro   minrH   r   rG   extend)ru   r   ra   rX   r   r   index_td
index_fontellipsis_tdr   cellsindicesr?   r   
row_strider   rowsr    r    r!   r     s0   




0z"_GraphvizRenderer._render_sequencedict_r   r   r   r4   c                 C   s  |  d}|  d}| j ddtd}| j ddd}	|du ri }|dur&|gng }
| D ]0\}}|tu r5q,t||}| |}||d	}|rO| ||}|
	||||	|g q,t|v rt|
	| 
|  d
d|t  d |dur}|
	| ||
S )a?  Renders the given `dict_` as an HTML table.

    Args:
      dict_: The `dict` to render.
      header: A table row containing a header row to include. The table row's
        table cell should have colspan="2" to render properly in the table.
      footer: A table row containing a footer row to include.
      key_format_fn: A function to apply to dictionary keys to conver them into
        a string representation. Defaults to `repr`.
      tags: Optional tags for dictionary entries.

    Returns:
      The HTML markup for the resulting table representing `dict_`.
    rX   r   r   rightr   r   r   r   Nr    r?   z	(trimmed z	 item(s)))r*   r  r   _TRIMMED_SENTINELr   r   r   r   _render_tagsr  r   )ru   r  r   r   r   r4   rX   r   key_tdr   r  r   r   key_str	value_strkey_tagsr    r    r!   r     s2   



z_GraphvizRenderer._render_dictc              
   C   s  | j dddd}| j ddtd}|  d}| j dd	d
}| j dd	td d}| j dd	td d}|  d}	|||g}
t|tdD ]C}t|tr\|
||||	dt|j g qBt|trt|
||||	dt|j g qB|
||||	dt|g qB||
S )zBRenders the name and tags for a Buildable argument to HTML markup.rX   rf   rZ   r\   r   arial)facera   r   r   r  r   r   r  r   r?   )r   zTag: )	r*   
_TAG_COLORr   sortedr   r   r)   r  r.   )ru   arg_namer4   	tag_tabletag_fontr   r   add_tddel_tditalicr  r*   r    r    r!   r  -  s   


&
&$z_GraphvizRenderer._render_tagsc                 C   s   t |}t|S )z)Renders `value` as its `__repr__` string.)r   pretty_printr   r   )ru   r   r    r    r!   r   @  s   

z_GraphvizRenderer._render_leafc                 C   s   | j dddd}|  d}|  d}| j dtd d}| j dtd d}g }|jt kr7||| |j |jt krJ|jt krJ||d	 |jt kr[||| |j |||S )
z+Renders a `_ChangedValue` as an HTML table.rX   rf   r  r   r   r   r   r   r   )r*   r   r%   r#   r  r   r&   )ru   r   rX   r   r   td_deltd_addrowr    r    r!   r   E  s   

z'_GraphvizRenderer._render_changed_value)NrT   F)-r   r   r   r   InstanceColorsTyper=   boolrv   rt   r   r7   r   r   r   r*   r  r   r5   r6   r   rz   r{   r   r   r   r   r   r   r   r   r   r   r	   r   r   r   r   r   r   r   r,   r   r  r   r   r    r    r    r!   rS      s    
)
#



&2
"
/rS   r   	max_depthmax_str_lengthc                 C   sB   |durt j| t j| |dd} |durt j| |d} t | S )a"  Renders the given ``config`` as a ``graphviz.Graph``.

  Each config is rendered as a table of keys and values (with a header row).
  Any nested configs get their own separate table, with an edge pointing to
  their location in their parent config. If a config instance is present in
  multiple parent configs, it is only rendered once but will have multiple
  edges to parent configs.

  Args:
    config: The ``fdl.Buildable`` (or nested structure of ``fdl.Buildable``'s)
      to render.
    max_depth: Max depth of nodes to render.
    max_str_length: Max length of long string fields or object repr's in a
      config.

  Returns:
    A ``graphviz.Graph`` object containing the resulting rendering of
    ``config``. Standard ``graphviz`` methods can then be used to export this to
    a file.
  N)depth)trim)	threshold)r   trimmed
depth_overtrim_long_fieldsrS   r   )r   r*  r+  r    r    r!   r   W  s   r   F)oldnewr-  diffr2  r3  r-  c                C   s   | du r|du s|du s| dur|durt d| du r"t||} |du r+t| }t| |}t|}t|}|r?t|| tj	t
|| || d}t|dd|S )a[  Renders the given diff as a `graphviz.Graph`.

  Should be called using one of the following signatures:
    * `render_diff(diff=...)`
    * `render_diff(diff=..., old=...)`
    * `render_diff(old=..., new=...)`

  Args:
    diff: The diff to render.  If not specified, then the diff between `old` and
      `new` will be computed and rendered.
    old: The structure modified by the diff.  If not specified, then use a
      minimal config that can be used as the source for the diff.
    new: The result of the diff.  May not be specified if `diff` is specified.
    trim: If true, then trim any unchanged `Config` nodes in the rendered result
      (i.e., do not display their arguments).

  Returns:
    A `graphviz.Graph` object containing the resulting rendering of the diff.
    Standard `graphviz` methods can then be used to export this to a file.
  Nzrender_diff must be called with one of the following signatures:
  * render_diff(diff=...)
  * render_diff(diff=..., old=...)
  * render_diff(old=..., new=...))added_value_idsdeleted_value_idsT)rU   rW   )	TypeErrorr   
build_diffskeleton_from_diff _record_changed_values_from_diff_find_old_value_ids_find_new_value_ids
_trim_diff	functoolsr   _diff_colorrS   r   )r4  r2  r3  r-  r   old_value_idsnew_value_ids
fill_colorr    r    r!   render_diffy  s0   


rC  c                   @   s&   e Zd ZU dZeed< ee ed< dS )_OldAndNewSharedValueszA NamedTuple that pairs an `old` structure with a diff's new shared values.

  This is used as a top-level node to traverse all the values that are relevant
  to rendering a diff.
  r2  new_shared_valuesN)r   r   r   r   r   r'   r   r    r    r    r!   rD    s   
 rD  c                    s   t | |} tt| jD ]}|jdd  | qi g   fdd}dd | jD }t||}t	
||j} D ]\}}t|t jt jfrZt|jrZt|j |_q?|S )a  Returns a copy of `old`, with `_ChangedValue` nodes used to show changes.

  Args:
    diff: A `Diff` describing changes to `old`.
    old: A nested structure.

  Returns:
    A copy of `old`, where any value that is changed by the diff is replaced
    by a `_ChangedValue` object, which points to both the new and the old value.
    Note: the nested structure returned by `record_changes` may contain cycles
    if you traverse through `_ChangedValue` objects.
  Nc           	      3   sF   d V }dd | D } t |tjr'tt|t|t||jt|j	d}t
|r7tjdi | }n	t |tr@t|}| D ]}|dD ]}|jd }t |tjrbt |tjrb|j|_qJt |tjrz|j|jt }|t|j  qJt |tj!r|jr|j|jt }|"|j g |t#|j  qJt |tj$rt% }nt |tr|j&|j }n|'|}t(|t% } )||f t |tj*r|||j+< qJt |tj,r|||j-< qJt |tj.rt |tr||j&|j< qJt/||j| qJt0d| qBt
|rt|di |j1}nt |trt||}|t2|< |S )Nc                 S   s*   g | ]}|r|d  j dkr|dd qS )r   r2  rB   N)r   )r>   pr    r    r!   rA     s   * zK_record_changed_values_from_diff.<locals>.record_change.<locals>.<listcomp>)r0   r1   r2   r3   r4   r    rF  zUnexpected PathElement )3r   r5   r6   r/   r   r   r   copydeepcopyr   r   r   typesSimpleNamespacer   r   r   r   targetr   ModifyValuer   BuildableFnOrClsr&   r2   AddTagr4   
setdefaultr   r   r   r)   r*   	RemoveTagdifference_updater.   SetValuer#   r3   followr$   r  IndexindexKeyr   Attrsetattr
ValueError__dict__r   )	pathsoriginal_valuetransformed_valuer   changepath_eltr4   	old_childchildchanged_valueschanges_by_parentoriginal_to_transformedr    r!   record_change  sn   

	





)z7_record_changed_values_from_diff.<locals>.record_changec                 S   s   g | ]}t |d dqS )r&   N)r   )r>   r_  r    r    r!   rA         z4_record_changed_values_from_diff.<locals>.<listcomp>)r   resolve_diff_referencescollectionsdefaultdictr   changesrL  r  rD  r   memoized_traverser2  r   rS  rM  r   r   r&   r   )r4  r2  r_  rg  
new_valuesold_and_newresultchanged_valuer    rc  r!   r:    s    

M
r:  structure_with_changed_valuesr@  c                    s0   t |  dtjf fdd}tj||  dS )ah  Trims unchanged values from `structure_with_changed_values`.

  Trims unchanged arguments w/ unmemoizable type (int, str, etc.).
  Trims all arguments from `_ChangedBuildable`s with no changes.
  A `_ChangedBuildable` is considered to have no changes if:

  * It exists in old_value_ids (i.e., it was not added).
  * Its tags and callable have not changed.
  * None of its arguments contain a `_ChangedValue` or a `ChangedBuildable`
    with changes.

  Args:
    structure_with_changed_values: The structure to trim.  Mutated in place.
    old_value_ids: ids of all objects reachable via _ChangedValue.old_value.
  statec           	         s   t | v } | r*t | }t|}t| tr&t | v r&t| | |p)|S t| trE 	| j
td  	| jtd dS t| tr~ fdd| j D }| j| jk}tdd | jD }t|pm|pm|}t | v rzt| j| |p}|S |S )z&Returns true if any child has changed.r%   r&   Tc                    s   g | ]}  |td qS )args)callr   rX  )r>   argrs  r    r!   rA   N  s    z-_trim_diff.<locals>.visit.<locals>.<listcomp>c                 s   s    | ]
}t |ttfV  qd S r   )r   r)   r.   )r>   r*   r    r    r!   r   S  s    
z,_trim_diff.<locals>.visit.<locals>.<genexpr>)r   is_traversabler   yield_map_child_valuesanyr   r   
_trim_dictr$   ru  r%   r   rX  r&   r/   r3   valuesr1   r2   r4   )	r   rs  parents_changedchild_resultsany_changedargs_changedcallable_changedtags_changedchangedchanged_parent_idsr@  rw  r!   r   @  s0   




z_trim_diff.<locals>.visitN))_find_mutable_values_with_changed_parentsr   StateMemoizedTraversalrun)rr  r@  r   r    r  r!   r=  -  s
   r=  c                    s,   t   dtjf fdd}tj||   S )z@Returns a set of ids of mutable objects whose parent(s) changed.rs  c                    s   | | r|| D ]}q
d S t| trN| j| jusJ t| jr* t	| j t| jr8 t	| j |
| jtd |
| jtd dS t| trd| j D ]}|
|td qXd S d S )Nr%   r&   Trt  )rx  ry  r   r$   r%   r&   r   r   r   r   ru  rX  r/   r3   r|  )r   rs  r   rv  rp  r    r!   r   c  s$   


z8_find_mutable_values_with_changed_parents.<locals>.visit)r   r   r  r  r  )rr  r   r    r  r!   r  _  s   r  c                 C   sR   dd t |  |D }t| t| }|dkr'|   | | || t< dS dS )a  Trims unchanged items from a dictionary, for diff rendering.

  Args:
    value: The dictionary to trim.  Modified in-place.  If any items are
      trimmed, then `value[_TRIMMED_SENTINEL]` is set to the number trimmed.
    val_changed: A list of booleans, corresponding 1:1 with the entries in
      `value` (in the order they are returned by `value.items()`), indicating
      which items were changed.  Any unchanged items are trimmed.
  c                 S   s   g | ]\}}|r|qS r    r    )r>   itemr  r    r    r!   rA     rh  z_trim_dict.<locals>.<listcomp>r   N)zipr   rH   clearupdater  )r   val_changedkeepnum_trimmedr    r    r!   r{  x  s   

r{  c                    $   t    fddt|   S )zAReturns ids of all objects reachable via _ChangedValue.new_value.c                 3   d    ~ t | v r
d S t|trt|j nt|tr#t|j t	|r/ 
t | d V S r   )r   r   r$   r   r   r&   r/   r3   r   r   r   r   rA  r   r    r!   r        


z"_find_new_value_ids.<locals>.visitr   rr  r    r  r!   r<       r<  c                    r  )zAReturns ids of all objects reachable via _ChangedValue.old_value.c                 3   r  r   )r   r   r$   r   r   r%   r/   r3   r   r   r   r   r@  r   r    r!   r     r  z"_find_old_value_ids.<locals>.visitr   r  r    r  r!   r;    r  r;  r   r5  r6  c                 C   sH   t | |v rtd td fS t | |v rtd td fS td td fS )z;Returns the color to use for `value` when rendering a diff.r   r   N)r   r   _DIFF_EDGE_COLORS)r   r5  r6  r    r    r!   r?    s
   r?  )r8   )NNr   )Dr   rj  rI   rH  dataclassesr>  r   r   rJ  typingr   r   r   r   r   r   r   r	   r
   r   fiddle._srcr   r5   r   r   r   r   r   r   fiddle._src.codegenr   fiddle._src.experimentalr   r   rz   rm   r  _DEFAULT_EDGE_COLORr  r   r  r   r  	dataclassr#   r$   r)   r.   r/   r7   InstanceColorFuncr(  rR   rS   r=   r{   r   Diffr)  rC  rD  r:  r=  r  r{  r<  r;  r?  r    r    r    r!   <module>   s   0



   X
"
1
y2