##// END OF EJS Templates
py3: keep stdout as defined by pycompat in procutil...
py3: keep stdout as defined by pycompat in procutil According to https://docs.python.org/3/library/functions.html#open, it's not possible to use 1 as buffering argument value in binary mode. This is probably why line buffering does not work well in python3. On the other hand, sys.stdout.buffer appears to be line-buffered already on python3. So by not replacing it, there should be no behavior change. This fixes buffering issue in "hg email" (confirmation prompt shown before information to be confirmed).

File last commit:

r43387:8ff1ecfa default
r43435:227ba1af default
Show More
dagparser.py
508 lines | 14.8 KiB | text/x-python | PythonLexer
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 # dagparser.py - parser and generator for concise description of DAGs
#
# Copyright 2010 Peter Arrenbrecht <peter@arrenbrecht.ch>
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
Gregory Szorc
dagparser: use absolute_import
r25941 from __future__ import absolute_import
import re
import string
from .i18n import _
Yuya Nishihara
py3: drop use of str() in dagparser.py
r34207 from . import (
error,
Yuya Nishihara
py3: wrap string constants in dagparser.py with bytestr()
r34208 pycompat,
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 )
Augie Fackler
formatting: blacken the codebase...
r43346 from .utils import stringutil
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335
def parsedag(desc):
'''parses a DAG from a concise textual description; generates events
"+n" is a linear run of n nodes based on the current default parent
"." is a single node based on the current default parent
"$" resets the default parent to -1 (implied at the start);
otherwise the default parent is always the last node created
"<p" sets the default parent to the backref p
"*p" is a fork at parent p, where p is a backref
"*p1/p2/.../pn" is a merge of parents p1..pn, where the pi are backrefs
"/p2/.../pn" is a merge of the preceding node and p2..pn
":name" defines a label for the preceding node; labels can be redefined
"@text" emits an annotation event for text
"!command" emits an action event for the current node
"!!my command\n" is like "!", but to the end of the line
"#...\n" is a comment up to the end of the line
Whitespace between the above elements is ignored.
A backref is either
* a number n, which references the node curr-n, where curr is the current
node, or
* the name of a label you placed earlier using ":name", or
* empty to denote the default parent.
All string valued-elements are either strictly alphanumeric, or must
be enclosed in double quotes ("..."), with "\" as escape character.
Generates sequence of
('n', (id, [parentids])) for node creation
('l', (id, labelname)) for labels on nodes
('a', text) for annotations
('c', command) for actions (!)
('C', command) for line actions (!!)
Examples
--------
Example of a complex graph (output not shown for brevity):
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> len(list(parsedag(b"""
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 ...
... +3 # 3 nodes in linear run
... :forkhere # a label for the last of the 3 nodes from above
... +5 # 5 more nodes on one branch
... :mergethis # label again
timeless@mozdev.org
en-us: labeled
r17500 ... <forkhere # set default parent to labeled fork node
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 ... +10 # 10 more nodes on a parallel branch
... @stable # following nodes will be annotated as "stable"
... +5 # 5 nodes in stable
... !addfile # custom command; could trigger new file in next node
... +2 # two more nodes
timeless@mozdev.org
en-us: labeled
r17500 ... /mergethis # merge last node with labeled node
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 ... +4 # 4 more nodes descending from merge node
...
... """)))
34
Empty list:
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> list(parsedag(b""))
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 []
A simple linear run:
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> list(parsedag(b"+3"))
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 [('n', (0, [-1])), ('n', (1, [0])), ('n', (2, [1]))]
Some non-standard ways to define such runs:
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> list(parsedag(b"+1+2"))
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 [('n', (0, [-1])), ('n', (1, [0])), ('n', (2, [1]))]
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> list(parsedag(b"+1*1*"))
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 [('n', (0, [-1])), ('n', (1, [0])), ('n', (2, [1]))]
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> list(parsedag(b"*"))
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 [('n', (0, [-1]))]
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> list(parsedag(b"..."))
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 [('n', (0, [-1])), ('n', (1, [0])), ('n', (2, [1]))]
A fork and a join, using numeric back references:
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> list(parsedag(b"+2*2*/2"))
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 [('n', (0, [-1])), ('n', (1, [0])), ('n', (2, [0])), ('n', (3, [2, 1]))]
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> list(parsedag(b"+2<2+1/2"))
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 [('n', (0, [-1])), ('n', (1, [0])), ('n', (2, [0])), ('n', (3, [2, 1]))]
Placing a label:
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> list(parsedag(b"+1 :mylabel +1"))
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 [('n', (0, [-1])), ('l', (0, 'mylabel')), ('n', (1, [0]))]
An empty label (silly, really):
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> list(parsedag(b"+1:+1"))
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 [('n', (0, [-1])), ('l', (0, '')), ('n', (1, [0]))]
Fork and join, but with labels instead of numeric back references:
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> list(parsedag(b"+1:f +1:p2 *f */p2"))
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 [('n', (0, [-1])), ('l', (0, 'f')), ('n', (1, [0])), ('l', (1, 'p2')),
('n', (2, [0])), ('n', (3, [2, 1]))]
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> list(parsedag(b"+1:f +1:p2 <f +1 /p2"))
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 [('n', (0, [-1])), ('l', (0, 'f')), ('n', (1, [0])), ('l', (1, 'p2')),
('n', (2, [0])), ('n', (3, [2, 1]))]
Restarting from the root:
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> list(parsedag(b"+1 $ +1"))
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 [('n', (0, [-1])), ('n', (1, [-1]))]
Annotations, which are meant to introduce sticky state for subsequent nodes:
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> list(parsedag(b"+1 @ann +1"))
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 [('n', (0, [-1])), ('a', 'ann'), ('n', (1, [0]))]
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> list(parsedag(b'+1 @"my annotation" +1'))
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 [('n', (0, [-1])), ('a', 'my annotation'), ('n', (1, [0]))]
Commands, which are meant to operate on the most recently created node:
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> list(parsedag(b"+1 !cmd +1"))
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 [('n', (0, [-1])), ('c', 'cmd'), ('n', (1, [0]))]
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> list(parsedag(b'+1 !"my command" +1'))
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 [('n', (0, [-1])), ('c', 'my command'), ('n', (1, [0]))]
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> list(parsedag(b'+1 !!my command line\\n +1'))
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 [('n', (0, [-1])), ('C', 'my command line'), ('n', (1, [0]))]
Comments, which extend to the end of the line:
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> list(parsedag(b'+1 # comment\\n+1'))
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 [('n', (0, [-1])), ('n', (1, [0]))]
Error:
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> try: list(parsedag(b'+1 bad'))
Yuya Nishihara
doctest: upgrade old-style "except" clause
r34140 ... except Exception as e: print(pycompat.sysstr(bytes(e)))
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 invalid character in dag description: bad...
'''
if not desc:
return
Yuya Nishihara
py3: wrap string constants in dagparser.py with bytestr()
r34208 wordchars = pycompat.bytestr(string.ascii_letters + string.digits)
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335
labels = {}
p1 = -1
r = 0
def resolve(ref):
if not ref:
return p1
Yuya Nishihara
py3: wrap string constants in dagparser.py with bytestr()
r34208 elif ref[0] in pycompat.bytestr(string.digits):
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 return r - int(ref)
else:
return labels[ref]
Yuya Nishihara
py3: iterate bytes as a byte string in dagparser.py
r34209 chiter = pycompat.iterbytestr(desc)
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335
def nextch():
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return next(chiter, b'\0')
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335
def nextrun(c, allow):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 s = b''
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 while c in allow:
s += c
c = nextch()
return c, s
def nextdelimited(c, limit, escape):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 s = b''
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 while c != limit:
if c == escape:
c = nextch()
s += c
c = nextch()
return nextch(), s
def nextstring(c):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if c == b'"':
return nextdelimited(nextch(), b'"', b'\\')
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 else:
return nextrun(c, wordchars)
c = nextch()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 while c != b'\0':
Yuya Nishihara
py3: wrap string constants in dagparser.py with bytestr()
r34208 while c in pycompat.bytestr(string.whitespace):
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 c = nextch()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if c == b'.':
yield b'n', (r, [p1])
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 p1 = r
r += 1
c = nextch()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elif c == b'+':
Yuya Nishihara
py3: wrap string constants in dagparser.py with bytestr()
r34208 c, digs = nextrun(nextch(), pycompat.bytestr(string.digits))
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 n = int(digs)
Gregory Szorc
global: use pycompat.xrange()...
r38806 for i in pycompat.xrange(0, n):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 yield b'n', (r, [p1])
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 p1 = r
r += 1
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elif c in b'*/':
if c == b'*':
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 c = nextch()
c, pref = nextstring(c)
prefs = [pref]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 while c == b'/':
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 c, pref = nextstring(nextch())
prefs.append(pref)
ps = [resolve(ref) for ref in prefs]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 yield b'n', (r, ps)
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 p1 = r
r += 1
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elif c == b'<':
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 c, ref = nextstring(nextch())
p1 = resolve(ref)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elif c == b':':
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 c, name = nextstring(nextch())
labels[name] = p1
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 yield b'l', (p1, name)
elif c == b'@':
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 c, text = nextstring(nextch())
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 yield b'a', text
elif c == b'!':
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 c = nextch()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if c == b'!':
cmd = b''
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 c = nextch()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 while c not in b'\n\r\0':
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 cmd += c
c = nextch()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 yield b'C', cmd
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 else:
c, cmd = nextstring(c)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 yield b'c', cmd
elif c == b'#':
while c not in b'\n\r\0':
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 c = nextch()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elif c == b'$':
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 p1 = -1
c = nextch()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elif c == b'\0':
Augie Fackler
formatting: blacken the codebase...
r43346 return # in case it was preceded by whitespace
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 s = b''
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 i = 0
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 while c != b'\0' and i < 10:
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 s += c
i += 1
c = nextch()
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 _(b'invalid character in dag description: %s...') % s
Augie Fackler
formatting: blacken the codebase...
r43346 )
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335
Augie Fackler
formatting: blacken the codebase...
r43346 def dagtextlines(
events,
addspaces=True,
wraplabels=False,
wrapannotations=False,
wrapcommands=False,
wrapnonlinear=False,
usedots=False,
maxlinewidth=70,
):
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 '''generates single lines for dagtext()'''
def wrapstring(text):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if re.match(b"^[0-9a-z]*$", text):
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 return text
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b'"' + text.replace(b'\\', b'\\\\').replace(b'"', b'\"') + b'"'
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335
def gen():
labels = {}
run = 0
wantr = 0
needroot = False
for kind, data in events:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if kind == b'n':
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 r, ps = data
# sanity check
if r != wantr:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b"expected id %i, got %i") % (wantr, r))
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 if not ps:
ps = [-1]
else:
for p in ps:
if p >= r:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"parent id %i is larger than "
b"current id %i"
Augie Fackler
formatting: blacken the codebase...
r43346 )
% (p, r)
)
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 wantr += 1
# new root?
p1 = r - 1
if len(ps) == 1 and ps[0] == -1:
if needroot:
if run:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 yield b'+%d' % run
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 run = 0
if wrapnonlinear:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 yield b'\n'
yield b'$'
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 p1 = -1
else:
needroot = True
if len(ps) == 1 and ps[0] == p1:
if usedots:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 yield b"."
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 else:
run += 1
else:
if run:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 yield b'+%d' % run
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 run = 0
if wrapnonlinear:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 yield b'\n'
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 prefs = []
for p in ps:
if p == p1:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 prefs.append(b'')
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 elif p in labels:
prefs.append(labels[p])
else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 prefs.append(b'%d' % (r - p))
yield b'*' + b'/'.join(prefs)
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 else:
if run:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 yield b'+%d' % run
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 run = 0
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if kind == b'l':
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 rid, name = data
labels[rid] = name
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 yield b':' + name
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 if wraplabels:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 yield b'\n'
elif kind == b'c':
yield b'!' + wrapstring(data)
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 if wrapcommands:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 yield b'\n'
elif kind == b'C':
yield b'!!' + data
yield b'\n'
elif kind == b'a':
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 if wrapannotations:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 yield b'\n'
yield b'@' + wrapstring(data)
elif kind == b'#':
yield b'#' + data
yield b'\n'
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 else:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 _(b"invalid event type in dag: ('%s', '%s')")
Augie Fackler
formatting: blacken the codebase...
r43346 % (
stringutil.escapestr(kind),
stringutil.escapestr(data),
)
)
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 if run:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 yield b'+%d' % run
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 line = b''
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 for part in gen():
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if part == b'\n':
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 if line:
yield line
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 line = b''
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 else:
if len(line) + len(part) >= maxlinewidth:
yield line
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 line = b''
elif addspaces and line and part != b'.':
line += b' '
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 line += part
if line:
yield line
Augie Fackler
formatting: blacken the codebase...
r43346
def dagtext(
dag,
addspaces=True,
wraplabels=False,
wrapannotations=False,
wrapcommands=False,
wrapnonlinear=False,
usedots=False,
maxlinewidth=70,
):
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 '''generates lines of a textual representation for a dag event stream
events should generate what parsedag() does, so:
('n', (id, [parentids])) for node creation
('l', (id, labelname)) for labels on nodes
('a', text) for annotations
('c', text) for commands
('C', text) for line commands ('!!')
('#', text) for comment lines
Parent nodes must come before child nodes.
Examples
--------
Linear run:
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> dagtext([(b'n', (0, [-1])), (b'n', (1, [0]))])
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 '+2'
Two roots:
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> dagtext([(b'n', (0, [-1])), (b'n', (1, [-1]))])
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 '+1 $ +1'
Fork and join:
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> dagtext([(b'n', (0, [-1])), (b'n', (1, [0])), (b'n', (2, [0])),
... (b'n', (3, [2, 1]))])
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 '+2 *2 */2'
Fork and join with labels:
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> dagtext([(b'n', (0, [-1])), (b'l', (0, b'f')), (b'n', (1, [0])),
... (b'l', (1, b'p2')), (b'n', (2, [0])), (b'n', (3, [2, 1]))])
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 '+1 :f +1 :p2 *f */p2'
Annotations:
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> dagtext([(b'n', (0, [-1])), (b'a', b'ann'), (b'n', (1, [0]))])
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 '+1 @ann +1'
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> dagtext([(b'n', (0, [-1])),
... (b'a', b'my annotation'),
... (b'n', (1, [0]))])
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 '+1 @"my annotation" +1'
Commands:
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> dagtext([(b'n', (0, [-1])), (b'c', b'cmd'), (b'n', (1, [0]))])
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 '+1 !cmd +1'
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> dagtext([(b'n', (0, [-1])),
... (b'c', b'my command'),
... (b'n', (1, [0]))])
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 '+1 !"my command" +1'
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> dagtext([(b'n', (0, [-1])),
... (b'C', b'my command line'),
... (b'n', (1, [0]))])
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 '+1 !!my command line\\n+1'
Comments:
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> dagtext([(b'n', (0, [-1])), (b'#', b' comment'), (b'n', (1, [0]))])
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 '+1 # comment\\n+1'
>>> dagtext([])
''
Combining parsedag and dagtext:
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> dagtext(parsedag(b'+1 :f +1 :p2 *f */p2'))
Peter Arrenbrecht
dagparser: parses and formats DAGs as concise text...
r11335 '+1 :f +1 :p2 *f */p2'
'''
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b"\n".join(
Augie Fackler
formatting: blacken the codebase...
r43346 dagtextlines(
dag,
addspaces,
wraplabels,
wrapannotations,
wrapcommands,
wrapnonlinear,
usedots,
maxlinewidth,
)
)