
    "                         S r SSKJr  SSKJr  SSKJr  SSKJr  SSKr " S S\5      r	S	 r
S
 rS rSrSS jrSrSS jrS rSS jrg)zLCode to transform the (cleaned-up) description of a dataflow into Graphviz.
    )absolute_import)division)unicode_literals)
exceptionsNc                   R    \ rS rSrSrS rS rS rS rS r	S r
SS
 jrS rS rSrg	)_Cluster   a
  Encapsulation of a single cluster in the final Step-Graph.

The cluster hierarchy represents pieces of the user_name. A given cluster is
either a leaf (it contains a single step and no sub-clusters) or a transform
(it contains no step and one or more sub-clusters).
c                 8    0 U l         Xl        X l        S U l        g N)_Cluster__children_Cluster__parent_Cluster__name_in_parent_Cluster__step)selfparentname_in_parents      1lib/googlecloudsdk/api_lib/dataflow/step_graph.py__init___Cluster.__init__"   s    DOM*DK    c                 $    U R                   (       + $ )zVA leaf cluster contains no sub-clusters.

Returns:
  True iff this is a leaf cluster.
)r   r   s    r   IsLeaf_Cluster.IsLeaf(   s     r   c                 2    [        U R                  5      S:H  $ )zkA singleton is any cluster that contains a single child.

Returns:
  True iff this is a singleton cluster.
   )lenr   r   s    r   IsSingleton_Cluster.IsSingleton0   s     t1$$r   c                 $    U R                   (       + $ )zVDetermine if this cluster is the root.

Returns:
  True iff this is the root cluster.
)r   r   s    r   IsRoot_Cluster.IsRoot8   s     }}r   c                     U R                   $ )zlReturn the step for this cluster.

Returns:
  The step for this cluster. May be None if this is not a leaf.
)r   r   s    r   GetStep_Cluster.GetStep@   s     ;;r   c                 \    U R                   (       a   eU R                  (       a   eXl        g)zSet the step for this cluster.

Can only be called on leaf nodes that have not yet had their step set.

Args:
  step: The step that this cluster represents.
N)r   r   )r   steps     r   SetStep_Cluster.SetStepH   s"     {{?Kr   Nc                     U R                   (       a  U R                   U:X  a  U R                  $ U R                   R                  U5      nU(       a  US-   U R                  -   $ U R                  $ )zReturn the name of this sub-cluster relative to the given ancestor.

Args:
  relative_to: The ancestor to output the name relative to.

Returns:
  The string representing the user_name component for this cluster.
/)r   r   Name)r   relative_toparent_names      r   r,   _Cluster.NameT   s[     MMt}};"""--$$[1K3!6!666"""r   c                     U R                   (       a   eXR                  ;  a  [        X5      U R                  U'   U R                  U   $ )zReturn the cluster representing the given piece_name within this cluster.

Args:
  piece_name: String representing the piece name of the desired child.
Returns:
  Cluster representing the child.
)r   r   r   )r   
piece_names     r   GetOrAddChild_Cluster.GetOrAddChildf   s<     {{?($,T$>dooj!??:&&r   c                 T    [        [        R                  " U R                  5      5      $ )z\Return the sub-clusters.

Returns:
  Sorted list of pairs for the children in this cluster.
)sortedsix	iteritemsr   r   s    r   Children_Cluster.Childrens   s     #--011r   )
__children__name_in_parent__parent__stepr   )__name__
__module____qualname____firstlineno____doc__r   r   r   r!   r$   r(   r,   r2   r8   __static_attributes__ r   r   r   r      s4    %
#$'2r   r   c                 Z   Sn/ n/ nU R                  S5       Hw  nXR                  S5      UR                  S5      -
  -  nUR                  U5        US:X  a'  UR                  SR                  U5      5        USS2	 Mf  UR                  S5        My     U(       a  UR                  U5        U$ )aA  Given a user name for a step, split it into the individual pieces.

Examples:
   _SplitStep('Transform/Step') = ['Transform', 'Step']
   _SplitStep('Read(gs://Foo)/Bar') = ['Read(gs://Foo)', 'Bar']

Args:
  user_name: The full user_name of the step.
Returns:
  A list representing the individual pieces of the step name.
r   r+   () N)splitcountappendjoin)	user_nameparensaccum
step_partspieces        r   
_SplitSteprR   |   s     &
%*s#e
kk#S!111F	LL{'
(ll3 $ e	r   c                     [        SS5      nU  HQ  n[        US   R                  SUS   5      5      nUnU H  nUR                  U5      nM     UR	                  U5        MS     U$ )a	  Extract a hierarchy from the steps provided.

The `step graph' is constructed as follows:

  1. Every node has a `name'. This is flat, something like "s1", "s100".
  2. Each node can depend on others. These edges are specified by "name".
  3. Each node can also have a user_name, like "Foo/Bar". This name creates
     a hierarchy of subgraphs (eg., Foo/Bar and Foo/Baz are in the same
     cluster).

Args:
  steps: A list of steps from the Job message.
Returns:
  A Cluster representing the root of the step hierarchy.
NrH   
propertiesrM   name)r   rR   getr2   r(   )stepsrootr'   	step_pathnoderQ   s         r   _UnflattenStepsToClustersr[      sl      
$	$d4-11+tF|LMID&d LL  
+r   c                     U R                  S5      (       a%  [        R                  " SR                  U 5      5      eSR                  U R	                  SS5      5      $ )a  Escape a string for use as in Graphviz.

Args:
  name: The string to escape.

Returns:
  The `name', with double-quotes escaped, and quotes around it.

Raises:
  exceptions.UnsupportedNameException: If the name is incompatible with
    Graphviz ID escaping.
\z0Unsupported name for Graphviz ID escaping: {0!r}z"{0}""z\")endswithr   UnsupportedNameExceptionformatreplace)rU   s    r   _EscapeGraphvizIdrc      sP     
]]4

-
-:AA$GI I	S%0	11r   zO{name} [label={user_name}, tooltip={full_name}, style=filled, fillcolor=white];c           
   #     #    U R                  5       (       aa  U R                  5       n[        R                  [	        US   5      [	        U R                  5       5      [	        U R                  US95      S9v   g U R                  5       (       d  U R                  5       (       a.  U R                  5        H  u  p4[        XAS9 H  nUv   M	     M     g U R                  5       nSR                  [	        SU-   5      5      v   Sv   Sv   S	v   S
R                  [	        U5      5      v   SR                  [	        U R                  U5      5      5      v   U R                  5        H  u  p7[        XpS9 H  nUv   M	     M     Sv   g 7f)NrU   )r-   )rU   	full_namerM   )r   zsubgraph {0} {{zcluster zstyle=filled;zbgcolor=white;zlabeljust=left;ztooltip={0};z
label={0};})
r   r$   _NODE_FORMATra   rc   r,   r   r!   r8   _YieldGraphvizClusters)clusterr   r'   
unused_key
subclusterlinere   subgroups           r   rh   rh      sQ    ^^??D


tF|,#GLLN3#GLLVL$DE  G G  0 0")"2"2"4
(C$
 D #5 I

"
"#4Z)5K#L
MM





 1) <
==


/V0DE
FF ' 0 0 2
(B$
 C !3 Is   FFzF{edge_source} -> {edge_dest} [taillabel={edge_output}, style={style}];c                 p    [         R                  [        US   5      [        U 5      [        US   5      US9$ )a-  Returns an edge from the output referred to by output_ref to step_name.

Args:
  step_name: String identifying the step with the dependency.
  output_ref: Output-reference dictionary to start the edge at.
  style: The style for the edge.

Returns:
  A string representing the edge in Graphviz format.
	step_nameoutput_name)edge_source	edge_destedge_outputstyle)_EDGE_FORMATra   rc   )ro   
output_refrt   s      r   _GraphvizEdgerw      sA     
		#J{$;<!),#J}$=>	 
 
 r   c              #   &  #    U S   nU S   R                  SS5      nU(       a  [        X5      v   U S   R                  S/ 5       H  n[        X5      v   M     U S   R                  S0 5      R                  5        H  n[        XSS9v   M     g7f)	zOutput Graphviz edges for the given step.

Args:
  step: Step to write edges for.

Yields:
  The Graphviz edge lines for the given step.
rU   rT   parallel_inputNinputsnon_parallel_inputsdashed)rt   )rV   rw   values)r'   ro   	par_inputother_input
side_inputs        r   _YieldGraphvizEdgesr      s      6l)< $$%5t<)
	
--,'++Hb9k
	
// : &**+@"ELLNj
	X
>> Os   BBc              #      #    SR                  [        U=(       d    S5      S9v   [        U 5      n[        U5       H  nUv   M	     Sv   U  H  n[	        U5       H  nUv   M	     M     Sv   g7f)a  Given a root cluster produce the Graphviz DOT format.

No attempt is made to produce `pretty' output.

Args:
  steps: A list of steps from the Job message.
  graph_name: The name of the graph to output.

Yields:
  The lines representing the step-graph in Graphviz format.
zstrict digraph {graph_name} {{G)
graph_namerH   rf   N)ra   rc   r[   rh   r   )rW   r   rX   rl   r'   s        r   YieldGraphvizr     sx      	)//":#45 	0 	7 7 
#5	)$$T*d
J + 	(d#D)j * 
 	)s   A-A/r   )solid)rB   
__future__r   r   r   googlecloudsdk.api_lib.dataflowr   r6   objectr   rR   r[   rc   rg   rh   ru   rw   r   r   rD   r   r   <module>r      s^    '  ' 6 
_2v _2D>42(( 
2<$?,r   