mercurial/dagparser.py
changeset 34131 0fa781320203
parent 33716 c91013452b33
child 34137 a8994d08e4a2
equal deleted inserted replaced
34130:ada8a19672ab 34131:0fa781320203
    52     Examples
    52     Examples
    53     --------
    53     --------
    54 
    54 
    55     Example of a complex graph (output not shown for brevity):
    55     Example of a complex graph (output not shown for brevity):
    56 
    56 
    57         >>> len(list(parsedag("""
    57         >>> len(list(parsedag(b"""
    58         ...
    58         ...
    59         ... +3         # 3 nodes in linear run
    59         ... +3         # 3 nodes in linear run
    60         ... :forkhere  # a label for the last of the 3 nodes from above
    60         ... :forkhere  # a label for the last of the 3 nodes from above
    61         ... +5         # 5 more nodes on one branch
    61         ... +5         # 5 more nodes on one branch
    62         ... :mergethis # label again
    62         ... :mergethis # label again
    72         ... """)))
    72         ... """)))
    73         34
    73         34
    74 
    74 
    75     Empty list:
    75     Empty list:
    76 
    76 
    77         >>> list(parsedag(""))
    77         >>> list(parsedag(b""))
    78         []
    78         []
    79 
    79 
    80     A simple linear run:
    80     A simple linear run:
    81 
    81 
    82         >>> list(parsedag("+3"))
    82         >>> list(parsedag(b"+3"))
    83         [('n', (0, [-1])), ('n', (1, [0])), ('n', (2, [1]))]
    83         [('n', (0, [-1])), ('n', (1, [0])), ('n', (2, [1]))]
    84 
    84 
    85     Some non-standard ways to define such runs:
    85     Some non-standard ways to define such runs:
    86 
    86 
    87         >>> list(parsedag("+1+2"))
    87         >>> list(parsedag(b"+1+2"))
    88         [('n', (0, [-1])), ('n', (1, [0])), ('n', (2, [1]))]
    88         [('n', (0, [-1])), ('n', (1, [0])), ('n', (2, [1]))]
    89 
    89 
    90         >>> list(parsedag("+1*1*"))
    90         >>> list(parsedag(b"+1*1*"))
    91         [('n', (0, [-1])), ('n', (1, [0])), ('n', (2, [1]))]
    91         [('n', (0, [-1])), ('n', (1, [0])), ('n', (2, [1]))]
    92 
    92 
    93         >>> list(parsedag("*"))
    93         >>> list(parsedag(b"*"))
    94         [('n', (0, [-1]))]
    94         [('n', (0, [-1]))]
    95 
    95 
    96         >>> list(parsedag("..."))
    96         >>> list(parsedag(b"..."))
    97         [('n', (0, [-1])), ('n', (1, [0])), ('n', (2, [1]))]
    97         [('n', (0, [-1])), ('n', (1, [0])), ('n', (2, [1]))]
    98 
    98 
    99     A fork and a join, using numeric back references:
    99     A fork and a join, using numeric back references:
   100 
   100 
   101         >>> list(parsedag("+2*2*/2"))
   101         >>> list(parsedag(b"+2*2*/2"))
   102         [('n', (0, [-1])), ('n', (1, [0])), ('n', (2, [0])), ('n', (3, [2, 1]))]
   102         [('n', (0, [-1])), ('n', (1, [0])), ('n', (2, [0])), ('n', (3, [2, 1]))]
   103 
   103 
   104         >>> list(parsedag("+2<2+1/2"))
   104         >>> list(parsedag(b"+2<2+1/2"))
   105         [('n', (0, [-1])), ('n', (1, [0])), ('n', (2, [0])), ('n', (3, [2, 1]))]
   105         [('n', (0, [-1])), ('n', (1, [0])), ('n', (2, [0])), ('n', (3, [2, 1]))]
   106 
   106 
   107     Placing a label:
   107     Placing a label:
   108 
   108 
   109         >>> list(parsedag("+1 :mylabel +1"))
   109         >>> list(parsedag(b"+1 :mylabel +1"))
   110         [('n', (0, [-1])), ('l', (0, 'mylabel')), ('n', (1, [0]))]
   110         [('n', (0, [-1])), ('l', (0, 'mylabel')), ('n', (1, [0]))]
   111 
   111 
   112     An empty label (silly, really):
   112     An empty label (silly, really):
   113 
   113 
   114         >>> list(parsedag("+1:+1"))
   114         >>> list(parsedag(b"+1:+1"))
   115         [('n', (0, [-1])), ('l', (0, '')), ('n', (1, [0]))]
   115         [('n', (0, [-1])), ('l', (0, '')), ('n', (1, [0]))]
   116 
   116 
   117     Fork and join, but with labels instead of numeric back references:
   117     Fork and join, but with labels instead of numeric back references:
   118 
   118 
   119         >>> list(parsedag("+1:f +1:p2 *f */p2"))
   119         >>> list(parsedag(b"+1:f +1:p2 *f */p2"))
   120         [('n', (0, [-1])), ('l', (0, 'f')), ('n', (1, [0])), ('l', (1, 'p2')),
   120         [('n', (0, [-1])), ('l', (0, 'f')), ('n', (1, [0])), ('l', (1, 'p2')),
   121          ('n', (2, [0])), ('n', (3, [2, 1]))]
   121          ('n', (2, [0])), ('n', (3, [2, 1]))]
   122 
   122 
   123         >>> list(parsedag("+1:f +1:p2 <f +1 /p2"))
   123         >>> list(parsedag(b"+1:f +1:p2 <f +1 /p2"))
   124         [('n', (0, [-1])), ('l', (0, 'f')), ('n', (1, [0])), ('l', (1, 'p2')),
   124         [('n', (0, [-1])), ('l', (0, 'f')), ('n', (1, [0])), ('l', (1, 'p2')),
   125          ('n', (2, [0])), ('n', (3, [2, 1]))]
   125          ('n', (2, [0])), ('n', (3, [2, 1]))]
   126 
   126 
   127     Restarting from the root:
   127     Restarting from the root:
   128 
   128 
   129         >>> list(parsedag("+1 $ +1"))
   129         >>> list(parsedag(b"+1 $ +1"))
   130         [('n', (0, [-1])), ('n', (1, [-1]))]
   130         [('n', (0, [-1])), ('n', (1, [-1]))]
   131 
   131 
   132     Annotations, which are meant to introduce sticky state for subsequent nodes:
   132     Annotations, which are meant to introduce sticky state for subsequent nodes:
   133 
   133 
   134         >>> list(parsedag("+1 @ann +1"))
   134         >>> list(parsedag(b"+1 @ann +1"))
   135         [('n', (0, [-1])), ('a', 'ann'), ('n', (1, [0]))]
   135         [('n', (0, [-1])), ('a', 'ann'), ('n', (1, [0]))]
   136 
   136 
   137         >>> list(parsedag('+1 @"my annotation" +1'))
   137         >>> list(parsedag(b'+1 @"my annotation" +1'))
   138         [('n', (0, [-1])), ('a', 'my annotation'), ('n', (1, [0]))]
   138         [('n', (0, [-1])), ('a', 'my annotation'), ('n', (1, [0]))]
   139 
   139 
   140     Commands, which are meant to operate on the most recently created node:
   140     Commands, which are meant to operate on the most recently created node:
   141 
   141 
   142         >>> list(parsedag("+1 !cmd +1"))
   142         >>> list(parsedag(b"+1 !cmd +1"))
   143         [('n', (0, [-1])), ('c', 'cmd'), ('n', (1, [0]))]
   143         [('n', (0, [-1])), ('c', 'cmd'), ('n', (1, [0]))]
   144 
   144 
   145         >>> list(parsedag('+1 !"my command" +1'))
   145         >>> list(parsedag(b'+1 !"my command" +1'))
   146         [('n', (0, [-1])), ('c', 'my command'), ('n', (1, [0]))]
   146         [('n', (0, [-1])), ('c', 'my command'), ('n', (1, [0]))]
   147 
   147 
   148         >>> list(parsedag('+1 !!my command line\\n +1'))
   148         >>> list(parsedag(b'+1 !!my command line\\n +1'))
   149         [('n', (0, [-1])), ('C', 'my command line'), ('n', (1, [0]))]
   149         [('n', (0, [-1])), ('C', 'my command line'), ('n', (1, [0]))]
   150 
   150 
   151     Comments, which extend to the end of the line:
   151     Comments, which extend to the end of the line:
   152 
   152 
   153         >>> list(parsedag('+1 # comment\\n+1'))
   153         >>> list(parsedag(b'+1 # comment\\n+1'))
   154         [('n', (0, [-1])), ('n', (1, [0]))]
   154         [('n', (0, [-1])), ('n', (1, [0]))]
   155 
   155 
   156     Error:
   156     Error:
   157 
   157 
   158         >>> try: list(parsedag('+1 bad'))
   158         >>> try: list(parsedag(b'+1 bad'))
   159         ... except Exception, e: print(e)
   159         ... except Exception, e: print(e)
   160         invalid character in dag description: bad...
   160         invalid character in dag description: bad...
   161 
   161 
   162     '''
   162     '''
   163     if not desc:
   163     if not desc:
   411     Examples
   411     Examples
   412     --------
   412     --------
   413 
   413 
   414     Linear run:
   414     Linear run:
   415 
   415 
   416         >>> dagtext([('n', (0, [-1])), ('n', (1, [0]))])
   416         >>> dagtext([(b'n', (0, [-1])), (b'n', (1, [0]))])
   417         '+2'
   417         '+2'
   418 
   418 
   419     Two roots:
   419     Two roots:
   420 
   420 
   421         >>> dagtext([('n', (0, [-1])), ('n', (1, [-1]))])
   421         >>> dagtext([(b'n', (0, [-1])), (b'n', (1, [-1]))])
   422         '+1 $ +1'
   422         '+1 $ +1'
   423 
   423 
   424     Fork and join:
   424     Fork and join:
   425 
   425 
   426         >>> dagtext([('n', (0, [-1])), ('n', (1, [0])), ('n', (2, [0])),
   426         >>> dagtext([(b'n', (0, [-1])), (b'n', (1, [0])), (b'n', (2, [0])),
   427         ...          ('n', (3, [2, 1]))])
   427         ...          (b'n', (3, [2, 1]))])
   428         '+2 *2 */2'
   428         '+2 *2 */2'
   429 
   429 
   430     Fork and join with labels:
   430     Fork and join with labels:
   431 
   431 
   432         >>> dagtext([('n', (0, [-1])), ('l', (0, 'f')), ('n', (1, [0])),
   432         >>> dagtext([(b'n', (0, [-1])), (b'l', (0, b'f')), (b'n', (1, [0])),
   433         ...          ('l', (1, 'p2')), ('n', (2, [0])), ('n', (3, [2, 1]))])
   433         ...          (b'l', (1, b'p2')), (b'n', (2, [0])), (b'n', (3, [2, 1]))])
   434         '+1 :f +1 :p2 *f */p2'
   434         '+1 :f +1 :p2 *f */p2'
   435 
   435 
   436     Annotations:
   436     Annotations:
   437 
   437 
   438         >>> dagtext([('n', (0, [-1])), ('a', 'ann'), ('n', (1, [0]))])
   438         >>> dagtext([(b'n', (0, [-1])), (b'a', b'ann'), (b'n', (1, [0]))])
   439         '+1 @ann +1'
   439         '+1 @ann +1'
   440 
   440 
   441         >>> dagtext([('n', (0, [-1])),
   441         >>> dagtext([(b'n', (0, [-1])),
   442         ...          ('a', 'my annotation'),
   442         ...          (b'a', b'my annotation'),
   443         ...          ('n', (1, [0]))])
   443         ...          (b'n', (1, [0]))])
   444         '+1 @"my annotation" +1'
   444         '+1 @"my annotation" +1'
   445 
   445 
   446     Commands:
   446     Commands:
   447 
   447 
   448         >>> dagtext([('n', (0, [-1])), ('c', 'cmd'), ('n', (1, [0]))])
   448         >>> dagtext([(b'n', (0, [-1])), (b'c', b'cmd'), (b'n', (1, [0]))])
   449         '+1 !cmd +1'
   449         '+1 !cmd +1'
   450 
   450 
   451         >>> dagtext([('n', (0, [-1])), ('c', 'my command'), ('n', (1, [0]))])
   451         >>> dagtext([(b'n', (0, [-1])),
       
   452         ...          (b'c', b'my command'),
       
   453         ...          (b'n', (1, [0]))])
   452         '+1 !"my command" +1'
   454         '+1 !"my command" +1'
   453 
   455 
   454         >>> dagtext([('n', (0, [-1])),
   456         >>> dagtext([(b'n', (0, [-1])),
   455         ...          ('C', 'my command line'),
   457         ...          (b'C', b'my command line'),
   456         ...          ('n', (1, [0]))])
   458         ...          (b'n', (1, [0]))])
   457         '+1 !!my command line\\n+1'
   459         '+1 !!my command line\\n+1'
   458 
   460 
   459     Comments:
   461     Comments:
   460 
   462 
   461         >>> dagtext([('n', (0, [-1])), ('#', ' comment'), ('n', (1, [0]))])
   463         >>> dagtext([(b'n', (0, [-1])), (b'#', b' comment'), (b'n', (1, [0]))])
   462         '+1 # comment\\n+1'
   464         '+1 # comment\\n+1'
   463 
   465 
   464         >>> dagtext([])
   466         >>> dagtext([])
   465         ''
   467         ''
   466 
   468 
   467     Combining parsedag and dagtext:
   469     Combining parsedag and dagtext:
   468 
   470 
   469         >>> dagtext(parsedag('+1 :f +1 :p2 *f */p2'))
   471         >>> dagtext(parsedag(b'+1 :f +1 :p2 *f */p2'))
   470         '+1 :f +1 :p2 *f */p2'
   472         '+1 :f +1 :p2 *f */p2'
   471 
   473 
   472     '''
   474     '''
   473     return "\n".join(dagtextlines(dag,
   475     return "\n".join(dagtextlines(dag,
   474                                   addspaces,
   476                                   addspaces,