mercurial/crecord.py
changeset 43076 2372284d9457
parent 42659 701341f57ceb
child 43077 687b865b95ad
--- a/mercurial/crecord.py	Sat Oct 05 10:29:34 2019 -0400
+++ b/mercurial/crecord.py	Sun Oct 06 09:45:02 2019 -0400
@@ -24,49 +24,59 @@
     scmutil,
     util,
 )
-from .utils import (
-    stringutil,
-)
+from .utils import stringutil
+
 stringio = util.stringio
 
 # patch comments based on the git one
-diffhelptext = _("""# To remove '-' lines, make them ' ' lines (context).
+diffhelptext = _(
+    """# To remove '-' lines, make them ' ' lines (context).
 # To remove '+' lines, delete them.
 # Lines starting with # will be removed from the patch.
-""")
+"""
+)
 
-hunkhelptext = _("""#
+hunkhelptext = _(
+    """#
 # If the patch applies cleanly, the edited hunk will immediately be
 # added to the record list. If it does not apply cleanly, a rejects file
 # will be generated. You can use that when you try again. If all lines
 # of the hunk are removed, then the edit is aborted and the hunk is left
 # unchanged.
-""")
+"""
+)
 
-patchhelptext = _("""#
+patchhelptext = _(
+    """#
 # If the patch applies cleanly, the edited patch will immediately
 # be finalised. If it does not apply cleanly, rejects files will be
 # generated. You can use those when you try again.
-""")
+"""
+)
 
 try:
     import curses
+
     curses.error
 except ImportError:
     # I have no idea if wcurses works with crecord...
     try:
         import wcurses as curses
+
         curses.error
     except ImportError:
         # wcurses is not shipped on Windows by default, or python is not
         # compiled with curses
         curses = False
 
+
 class fallbackerror(error.Abort):
     """Error that indicates the client should try to fallback to text mode."""
+
     # Inherits from error.Abort so that existing behavior is preserved if the
     # calling code does not know how to fallback.
 
+
 def checkcurses(ui):
     """Return True if the user wants to use curses
 
@@ -75,6 +85,7 @@
     """
     return curses and ui.interface("chunkselector") == "curses"
 
+
 class patchnode(object):
     """abstract class for patch graph nodes
     (i.e. patchroot, header, hunk, hunkline)
@@ -152,7 +163,7 @@
                 # else return grandparent's next sibling (or None)
                 return self.parentitem().parentitem().nextsibling()
 
-            except AttributeError: # parent and/or grandparent was None
+            except AttributeError:  # parent and/or grandparent was None
                 return None
 
     def previtem(self):
@@ -167,11 +178,11 @@
         prevsibling = self.prevsibling()
         if prevsibling is not None:
             prevsiblinglastchild = prevsibling.lastchild()
-            if ((prevsiblinglastchild is not None) and
-                not prevsibling.folded):
+            if (prevsiblinglastchild is not None) and not prevsibling.folded:
                 prevsiblinglclc = prevsiblinglastchild.lastchild()
-                if ((prevsiblinglclc is not None) and
-                    not prevsiblinglastchild.folded):
+                if (
+                    prevsiblinglclc is not None
+                ) and not prevsiblinglastchild.folded:
                     return prevsiblinglclc
                 else:
                     return prevsiblinglastchild
@@ -181,16 +192,19 @@
         # try parent (or None)
         return self.parentitem()
 
-class patch(patchnode, list): # todo: rename patchroot
+
+class patch(patchnode, list):  # todo: rename patchroot
     """
     list of header objects representing the patch.
     """
+
     def __init__(self, headerlist):
         self.extend(headerlist)
         # add parent patch object reference to each header
         for header in self:
             header.patch = self
 
+
 class uiheader(patchnode):
     """patch header
 
@@ -266,8 +280,10 @@
     def __getattr__(self, name):
         return getattr(self.nonuiheader, name)
 
+
 class uihunkline(patchnode):
     "represents a changed line in a hunk"
+
     def __init__(self, linetext, hunk):
         self.linetext = linetext
         self.applied = True
@@ -284,7 +300,7 @@
         numlinesinhunk = len(self.hunk.changedlines)
         indexofthisline = self.hunk.changedlines.index(self)
 
-        if (indexofthisline < numlinesinhunk - 1):
+        if indexofthisline < numlinesinhunk - 1:
             nextline = self.hunk.changedlines[indexofthisline + 1]
             return nextline
         else:
@@ -312,8 +328,10 @@
         # hunk-lines don't have children
         return None
 
+
 class uihunk(patchnode):
     """ui patch hunk, wraps a hunk and keep track of ui behavior """
+
     maxcontext = 3
 
     def __init__(self, hunk, header):
@@ -335,7 +353,7 @@
         numhunksinheader = len(self.header.hunks)
         indexofthishunk = self.header.hunks.index(self)
 
-        if (indexofthishunk < numhunksinheader - 1):
+        if indexofthishunk < numhunksinheader - 1:
             nexthunk = self.header.hunks[indexofthishunk + 1]
             return nexthunk
         else:
@@ -373,18 +391,29 @@
 
     def countchanges(self):
         """changedlines -> (n+,n-)"""
-        add = len([l for l in self.changedlines if l.applied
-                    and l.prettystr().startswith('+')])
-        rem = len([l for l in self.changedlines if l.applied
-                    and l.prettystr().startswith('-')])
+        add = len(
+            [
+                l
+                for l in self.changedlines
+                if l.applied and l.prettystr().startswith('+')
+            ]
+        )
+        rem = len(
+            [
+                l
+                for l in self.changedlines
+                if l.applied and l.prettystr().startswith('-')
+            ]
+        )
         return add, rem
 
     def getfromtoline(self):
         # calculate the number of removed lines converted to context lines
         removedconvertedtocontext = self.originalremoved - self.removed
 
-        contextlen = (len(self.before) + len(self.after) +
-                      removedconvertedtocontext)
+        contextlen = (
+            len(self.before) + len(self.after) + removedconvertedtocontext
+        )
         if self.after and self.after[-1] == '\\ No newline at end of file\n':
             contextlen -= 1
         fromlen = contextlen + self.removed
@@ -404,8 +433,12 @@
                 toline -= 1
 
         fromtoline = '@@ -%d,%d +%d,%d @@%s\n' % (
-            fromline, fromlen, toline, tolen,
-            self.proc and (' ' + self.proc))
+            fromline,
+            fromlen,
+            toline,
+            tolen,
+            self.proc and (' ' + self.proc),
+        )
         return fromtoline
 
     def write(self, fp):
@@ -477,8 +510,9 @@
                 adds.append(text[1:])
         hunk = ['-%s' % l for l in dels] + ['+%s' % l for l in adds]
         h = self._hunk
-        return patchmod.recordhunk(h.header, h.toline, h.fromline, h.proc,
-                                   h.before, hunk, h.after)
+        return patchmod.recordhunk(
+            h.header, h.toline, h.fromline, h.proc, h.before, hunk, h.after
+        )
 
     def __getattr__(self, name):
         return getattr(self._hunk, name)
@@ -486,6 +520,7 @@
     def __repr__(self):
         return r'<hunk %r@%d>' % (self.filename(), self.fromline)
 
+
 def filterpatch(ui, chunks, chunkselector, operation=None):
     """interactively filter patch chunks into applied-only chunks"""
     chunks = list(chunks)
@@ -502,8 +537,9 @@
     ret = chunkselector(ui, uiheaders, operation=operation)
     appliedhunklist = []
     for hdr in uiheaders:
-        if (hdr.applied and
-            (hdr.special() or len([h for h in hdr.hunks if h.applied]) > 0)):
+        if hdr.applied and (
+            hdr.special() or len([h for h in hdr.hunks if h.applied]) > 0
+        ):
             appliedhunklist.append(hdr)
             fixoffset = 0
             for hnk in hdr.hunks:
@@ -512,13 +548,14 @@
                     # adjust the 'to'-line offset of the hunk to be correct
                     # after de-activating some of the other hunks for this file
                     if fixoffset:
-                        #hnk = copy.copy(hnk) # necessary??
+                        # hnk = copy.copy(hnk) # necessary??
                         hnk.toline += fixoffset
                 else:
                     fixoffset += hnk.removed - hnk.added
 
     return (appliedhunklist, ret)
 
+
 def chunkselector(ui, headerlist, operation=None):
     """
     curses interface to get selection of chunks, and mark the applied flags
@@ -542,11 +579,14 @@
             signal.signal(signal.SIGTSTP, origsigtstp)
     return chunkselector.opts
 
+
 def testdecorator(testfn, f):
     def u(*args, **kwargs):
         return f(testfn, *args, **kwargs)
+
     return u
 
+
 def testchunkselector(testfn, ui, headerlist, operation=None):
     """
     test interface to get selection of chunks, and mark the applied flags
@@ -557,6 +597,7 @@
     class dummystdscr(object):
         def clear(self):
             pass
+
         def refresh(self):
             pass
 
@@ -570,13 +611,15 @@
                 break
     return chunkselector.opts
 
-_headermessages = { # {operation: text}
+
+_headermessages = {  # {operation: text}
     'apply': _('Select hunks to apply'),
     'discard': _('Select hunks to discard'),
     'keep': _('Select hunks to keep'),
     None: _('Select hunks to record'),
 }
 
+
 class curseschunkselector(object):
     def __init__(self, headerlist, ui, operation=None):
         # put the headers into a patch object
@@ -691,7 +734,7 @@
         a hunk is currently selected, then select the next hunk, if one exists,
         or if not, the next header if one exists.
         """
-        #self.startprintline += 1 #debug
+        # self.startprintline += 1 #debug
         currentitem = self.currentselecteditem
 
         nextitem = currentitem.nextitem()
@@ -872,19 +915,20 @@
             nosiblingsapplied = not (True in siblingappliedstatus)
 
             siblingspartialstatus = [hnk.partial for hnk in item.header.hunks]
-            somesiblingspartial = (True in siblingspartialstatus)
+            somesiblingspartial = True in siblingspartialstatus
 
-            #cases where applied or partial should be removed from header
+            # cases where applied or partial should be removed from header
 
             # if no 'sibling' hunks are applied (including this hunk)
             if nosiblingsapplied:
                 if not item.header.special():
                     item.header.applied = False
                     item.header.partial = False
-            else: # some/all parent siblings are applied
+            else:  # some/all parent siblings are applied
                 item.header.applied = True
-                item.header.partial = (somesiblingspartial or
-                                        not allsiblingsapplied)
+                item.header.partial = (
+                    somesiblingspartial or not allsiblingsapplied
+                )
 
         elif isinstance(item, uihunkline):
             siblingappliedstatus = [ln.applied for ln in item.hunk.changedlines]
@@ -898,18 +942,20 @@
             elif allsiblingsapplied:
                 item.hunk.applied = True
                 item.hunk.partial = False
-            else: # some siblings applied
+            else:  # some siblings applied
                 item.hunk.applied = True
                 item.hunk.partial = True
 
-            parentsiblingsapplied = [hnk.applied for hnk
-                                     in item.hunk.header.hunks]
+            parentsiblingsapplied = [
+                hnk.applied for hnk in item.hunk.header.hunks
+            ]
             noparentsiblingsapplied = not (True in parentsiblingsapplied)
             allparentsiblingsapplied = not (False in parentsiblingsapplied)
 
-            parentsiblingspartial = [hnk.partial for hnk
-                                     in item.hunk.header.hunks]
-            someparentsiblingspartial = (True in parentsiblingspartial)
+            parentsiblingspartial = [
+                hnk.partial for hnk in item.hunk.header.hunks
+            ]
+            someparentsiblingspartial = True in parentsiblingspartial
 
             # if all parent hunks are not applied, un-apply header
             if noparentsiblingsapplied:
@@ -917,14 +963,15 @@
                     item.hunk.header.applied = False
                     item.hunk.header.partial = False
             # set the applied and partial status of the header if needed
-            else: # some/all parent siblings are applied
+            else:  # some/all parent siblings are applied
                 item.hunk.header.applied = True
-                item.hunk.header.partial = (someparentsiblingspartial or
-                                            not allparentsiblingsapplied)
+                item.hunk.header.partial = (
+                    someparentsiblingspartial or not allparentsiblingsapplied
+                )
 
     def toggleall(self):
         "toggle the applied flag of all items."
-        if self.waslasttoggleallapplied: # then unapply them this time
+        if self.waslasttoggleallapplied:  # then unapply them this time
             for item in self.headerlist:
                 if item.applied:
                     self.toggleapply(item)
@@ -936,8 +983,10 @@
 
     def toggleallbetween(self):
         "toggle applied on or off for all items in range [lastapplied,current]."
-        if (not self.lastapplieditem or
-            self.currentselecteditem == self.lastapplieditem):
+        if (
+            not self.lastapplieditem
+            or self.currentselecteditem == self.lastapplieditem
+        ):
             # Treat this like a normal 'x'/' '
             self.toggleapply()
             return
@@ -985,7 +1034,7 @@
                 item.neverunfolded = False
 
             # also fold any foldable children of the parent/current item
-            if isinstance(item, uiheader): # the original or 'new' item
+            if isinstance(item, uiheader):  # the original or 'new' item
                 for child in item.allchildren():
                     child.folded = not item.folded
 
@@ -1004,11 +1053,22 @@
         # turn tabs into spaces
         instr = instr.expandtabs(4)
         strwidth = encoding.colwidth(instr)
-        numspaces = (width - ((strwidth + xstart) % width))
+        numspaces = width - ((strwidth + xstart) % width)
         return instr + " " * numspaces
 
-    def printstring(self, window, text, fgcolor=None, bgcolor=None, pair=None,
-        pairname=None, attrlist=None, towin=True, align=True, showwhtspc=False):
+    def printstring(
+        self,
+        window,
+        text,
+        fgcolor=None,
+        bgcolor=None,
+        pair=None,
+        pairname=None,
+        attrlist=None,
+        towin=True,
+        align=True,
+        showwhtspc=False,
+    ):
         """
         print the string, text, with the specified colors and attributes, to
         the specified curses window object.
@@ -1030,8 +1090,11 @@
         # preprocess the text, converting tabs to spaces
         text = text.expandtabs(4)
         # strip \n, and convert control characters to ^[char] representation
-        text = re.sub(br'[\x00-\x08\x0a-\x1f]',
-                lambda m:'^' + chr(ord(m.group()) + 64), text.strip('\n'))
+        text = re.sub(
+            br'[\x00-\x08\x0a-\x1f]',
+            lambda m: '^' + chr(ord(m.group()) + 64),
+            text.strip('\n'),
+        )
 
         if pair is not None:
             colorpair = pair
@@ -1060,11 +1123,11 @@
                     colorpair |= textattr
 
         y, xstart = self.chunkpad.getyx()
-        t = "" # variable for counting lines printed
+        t = ""  # variable for counting lines printed
         # if requested, show trailing whitespace
         if showwhtspc:
             origlen = len(text)
-            text = text.rstrip(' \n') # tabs have already been expanded
+            text = text.rstrip(' \n')  # tabs have already been expanded
             strippedlen = len(text)
             numtrailingspaces = origlen - strippedlen
 
@@ -1073,11 +1136,11 @@
         t += text
 
         if showwhtspc:
-                wscolorpair = colorpair | curses.A_REVERSE
-                if towin:
-                    for i in range(numtrailingspaces):
-                        window.addch(curses.ACS_CKBOARD, wscolorpair)
-                t += " " * numtrailingspaces
+            wscolorpair = colorpair | curses.A_REVERSE
+            if towin:
+                for i in range(numtrailingspaces):
+                    window.addch(curses.ACS_CKBOARD, wscolorpair)
+            t += " " * numtrailingspaces
 
         if align:
             if towin:
@@ -1102,8 +1165,10 @@
         # Format the selected label into a place as long as the longer of the
         # two possible labels.  This may vary by language.
         spacelen = max(len(spaceselect), len(spacedeselect))
-        selectedlabel = '%-*s' % (spacelen,
-                                  spacedeselect if selected else spaceselect)
+        selectedlabel = '%-*s' % (
+            spacelen,
+            spacedeselect if selected else spaceselect,
+        )
         segments = [
             _headermessages[self.operation],
             '-',
@@ -1160,10 +1225,14 @@
         try:
             self.printitem()
             self.updatescroll()
-            self.chunkpad.refresh(self.firstlineofpadtoprint, 0,
-                                  self.numstatuslines, 0,
-                                  self.yscreensize - self.numstatuslines,
-                                  self.xscreensize)
+            self.chunkpad.refresh(
+                self.firstlineofpadtoprint,
+                0,
+                self.numstatuslines,
+                0,
+                self.yscreensize - self.numstatuslines,
+                self.xscreensize,
+            )
         except curses.error:
             pass
 
@@ -1195,13 +1264,14 @@
                 if isinstance(item, uiheader):
                     # add two more spaces for headers
                     checkbox += "  "
-        except AttributeError: # not foldable
+        except AttributeError:  # not foldable
             checkbox += "  "
 
         return checkbox
 
-    def printheader(self, header, selected=False, towin=True,
-                    ignorefolding=False):
+    def printheader(
+        self, header, selected=False, towin=True, ignorefolding=False
+    ):
         """
         print the header to the pad.  if countlines is True, don't print
         anything, but just count the number of lines which would be printed.
@@ -1213,11 +1283,13 @@
 
         if chunkindex != 0 and not header.folded:
             # add separating line before headers
-            outstr += self.printstring(self.chunkpad, '_' * self.xscreensize,
-                                       towin=towin, align=False)
+            outstr += self.printstring(
+                self.chunkpad, '_' * self.xscreensize, towin=towin, align=False
+            )
         # select color-pair based on if the header is selected
-        colorpair = self.getcolorpair(name=selected and "selected" or "normal",
-                                      attrlist=[curses.A_BOLD])
+        colorpair = self.getcolorpair(
+            name=selected and "selected" or "normal", attrlist=[curses.A_BOLD]
+        )
 
         # print out each line of the chunk, expanding it to screen width
 
@@ -1229,19 +1301,22 @@
             linestr = checkbox + textlist[0]
         else:
             linestr = checkbox + header.filename()
-        outstr += self.printstring(self.chunkpad, linestr, pair=colorpair,
-                                   towin=towin)
+        outstr += self.printstring(
+            self.chunkpad, linestr, pair=colorpair, towin=towin
+        )
         if not header.folded or ignorefolding:
             if len(textlist) > 1:
                 for line in textlist[1:]:
-                    linestr = " "*(indentnumchars + len(checkbox)) + line
-                    outstr += self.printstring(self.chunkpad, linestr,
-                                               pair=colorpair, towin=towin)
+                    linestr = " " * (indentnumchars + len(checkbox)) + line
+                    outstr += self.printstring(
+                        self.chunkpad, linestr, pair=colorpair, towin=towin
+                    )
 
         return outstr
 
-    def printhunklinesbefore(self, hunk, selected=False, towin=True,
-                             ignorefolding=False):
+    def printhunklinesbefore(
+        self, hunk, selected=False, towin=True, ignorefolding=False
+    ):
         "includes start/end line indicator"
         outstr = ""
         # where hunk is in list of siblings
@@ -1249,22 +1324,26 @@
 
         if hunkindex != 0:
             # add separating line before headers
-            outstr += self.printstring(self.chunkpad, ' '*self.xscreensize,
-                                       towin=towin, align=False)
+            outstr += self.printstring(
+                self.chunkpad, ' ' * self.xscreensize, towin=towin, align=False
+            )
 
-        colorpair = self.getcolorpair(name=selected and "selected" or "normal",
-                                      attrlist=[curses.A_BOLD])
+        colorpair = self.getcolorpair(
+            name=selected and "selected" or "normal", attrlist=[curses.A_BOLD]
+        )
 
         # print out from-to line with checkbox
         checkbox = self.getstatusprefixstring(hunk)
 
-        lineprefix = " "*self.hunkindentnumchars + checkbox
+        lineprefix = " " * self.hunkindentnumchars + checkbox
         frtoline = "   " + hunk.getfromtoline().strip("\n")
 
-        outstr += self.printstring(self.chunkpad, lineprefix, towin=towin,
-                                   align=False) # add uncolored checkbox/indent
-        outstr += self.printstring(self.chunkpad, frtoline, pair=colorpair,
-                                   towin=towin)
+        outstr += self.printstring(
+            self.chunkpad, lineprefix, towin=towin, align=False
+        )  # add uncolored checkbox/indent
+        outstr += self.printstring(
+            self.chunkpad, frtoline, pair=colorpair, towin=towin
+        )
 
         if hunk.folded and not ignorefolding:
             # skip remainder of output
@@ -1272,7 +1351,7 @@
 
         # print out lines of the chunk preceeding changed-lines
         for line in hunk.before:
-            linestr = " "*(self.hunklineindentnumchars + len(checkbox)) + line
+            linestr = " " * (self.hunklineindentnumchars + len(checkbox)) + line
             outstr += self.printstring(self.chunkpad, linestr, towin=towin)
 
         return outstr
@@ -1285,7 +1364,7 @@
         # a bit superfluous, but to avoid hard-coding indent amount
         checkbox = self.getstatusprefixstring(hunk)
         for line in hunk.after:
-            linestr = " "*(self.hunklineindentnumchars + len(checkbox)) + line
+            linestr = " " * (self.hunklineindentnumchars + len(checkbox)) + line
             outstr += self.printstring(self.chunkpad, linestr, towin=towin)
 
         return outstr
@@ -1306,15 +1385,18 @@
         elif linestr.startswith("\\"):
             colorpair = self.getcolorpair(name="normal")
 
-        lineprefix = " "*self.hunklineindentnumchars + checkbox
-        outstr += self.printstring(self.chunkpad, lineprefix, towin=towin,
-                                   align=False) # add uncolored checkbox/indent
-        outstr += self.printstring(self.chunkpad, linestr, pair=colorpair,
-                                   towin=towin, showwhtspc=True)
+        lineprefix = " " * self.hunklineindentnumchars + checkbox
+        outstr += self.printstring(
+            self.chunkpad, lineprefix, towin=towin, align=False
+        )  # add uncolored checkbox/indent
+        outstr += self.printstring(
+            self.chunkpad, linestr, pair=colorpair, towin=towin, showwhtspc=True
+        )
         return outstr
 
-    def printitem(self, item=None, ignorefolding=False, recursechildren=True,
-                  towin=True):
+    def printitem(
+        self, item=None, ignorefolding=False, recursechildren=True, towin=True
+    ):
         """
         use __printitem() to print the the specified item.applied.
         if item is not specified, then print the entire patch.
@@ -1327,12 +1409,13 @@
             self.linesprintedtopadsofar = 0
 
         outstr = []
-        self.__printitem(item, ignorefolding, recursechildren, outstr,
-                                  towin=towin)
+        self.__printitem(
+            item, ignorefolding, recursechildren, outstr, towin=towin
+        )
         return ''.join(outstr)
 
     def outofdisplayedarea(self):
-        y, _ = self.chunkpad.getyx() # cursor location
+        y, _ = self.chunkpad.getyx()  # cursor location
         # * 2 here works but an optimization would be the max number of
         # consecutive non selectable lines
         # i.e the max number of context line for any hunk in the patch
@@ -1341,18 +1424,21 @@
         return y < miny or y > maxy
 
     def handleselection(self, item, recursechildren):
-        selected = (item is self.currentselecteditem)
+        selected = item is self.currentselecteditem
         if selected and recursechildren:
             # assumes line numbering starting from line 0
             self.selecteditemstartline = self.linesprintedtopadsofar
-            selecteditemlines = self.getnumlinesdisplayed(item,
-                                                          recursechildren=False)
-            self.selecteditemendline = (self.selecteditemstartline +
-                                        selecteditemlines - 1)
+            selecteditemlines = self.getnumlinesdisplayed(
+                item, recursechildren=False
+            )
+            self.selecteditemendline = (
+                self.selecteditemstartline + selecteditemlines - 1
+            )
         return selected
 
-    def __printitem(self, item, ignorefolding, recursechildren, outstr,
-                    towin=True):
+    def __printitem(
+        self, item, ignorefolding, recursechildren, outstr, towin=True
+    ):
         """
         recursive method for printing out patch/header/hunk/hunk-line data to
         screen.  also returns a string with all of the content of the displayed
@@ -1373,36 +1459,52 @@
         if isinstance(item, patch):
             if recursechildren:
                 for hdr in item:
-                    self.__printitem(hdr, ignorefolding,
-                            recursechildren, outstr, towin)
+                    self.__printitem(
+                        hdr, ignorefolding, recursechildren, outstr, towin
+                    )
         # todo: eliminate all isinstance() calls
         if isinstance(item, uiheader):
-            outstr.append(self.printheader(item, selected, towin=towin,
-                                       ignorefolding=ignorefolding))
+            outstr.append(
+                self.printheader(
+                    item, selected, towin=towin, ignorefolding=ignorefolding
+                )
+            )
             if recursechildren:
                 for hnk in item.hunks:
-                    self.__printitem(hnk, ignorefolding,
-                            recursechildren, outstr, towin)
-        elif (isinstance(item, uihunk) and
-              ((not item.header.folded) or ignorefolding)):
+                    self.__printitem(
+                        hnk, ignorefolding, recursechildren, outstr, towin
+                    )
+        elif isinstance(item, uihunk) and (
+            (not item.header.folded) or ignorefolding
+        ):
             # print the hunk data which comes before the changed-lines
-            outstr.append(self.printhunklinesbefore(item, selected, towin=towin,
-                                                ignorefolding=ignorefolding))
+            outstr.append(
+                self.printhunklinesbefore(
+                    item, selected, towin=towin, ignorefolding=ignorefolding
+                )
+            )
             if recursechildren:
                 for l in item.changedlines:
-                    self.__printitem(l, ignorefolding,
-                            recursechildren, outstr, towin)
-                outstr.append(self.printhunklinesafter(item, towin=towin,
-                                                ignorefolding=ignorefolding))
-        elif (isinstance(item, uihunkline) and
-              ((not item.hunk.folded) or ignorefolding)):
-            outstr.append(self.printhunkchangedline(item, selected,
-                towin=towin))
+                    self.__printitem(
+                        l, ignorefolding, recursechildren, outstr, towin
+                    )
+                outstr.append(
+                    self.printhunklinesafter(
+                        item, towin=towin, ignorefolding=ignorefolding
+                    )
+                )
+        elif isinstance(item, uihunkline) and (
+            (not item.hunk.folded) or ignorefolding
+        ):
+            outstr.append(
+                self.printhunkchangedline(item, selected, towin=towin)
+            )
 
         return outstr
 
-    def getnumlinesdisplayed(self, item=None, ignorefolding=False,
-                             recursechildren=True):
+    def getnumlinesdisplayed(
+        self, item=None, ignorefolding=False, recursechildren=True
+    ):
         """
         return the number of lines which would be displayed if the item were
         to be printed to the display.  the item will not be printed to the
@@ -1413,8 +1515,9 @@
         """
 
         # temporarily disable printing to windows by printstring
-        patchdisplaystring = self.printitem(item, ignorefolding,
-                                            recursechildren, towin=False)
+        patchdisplaystring = self.printitem(
+            item, ignorefolding, recursechildren, towin=False
+        )
         numlines = len(patchdisplaystring) // self.xscreensize
         return numlines
 
@@ -1429,8 +1532,9 @@
         except curses.error:
             pass
 
-    def getcolorpair(self, fgcolor=None, bgcolor=None, name=None,
-                     attrlist=None):
+    def getcolorpair(
+        self, fgcolor=None, bgcolor=None, name=None, attrlist=None
+    ):
         """
         get a curses color pair, adding it to self.colorpairs if it is not
         already defined.  an optional string, name, can be passed as a shortcut
@@ -1460,8 +1564,9 @@
                 pairindex = len(self.colorpairs) + 1
                 if self.usecolor:
                     curses.init_pair(pairindex, fgcolor, bgcolor)
-                    colorpair = self.colorpairs[(fgcolor, bgcolor)] = (
-                        curses.color_pair(pairindex))
+                    colorpair = self.colorpairs[
+                        (fgcolor, bgcolor)
+                    ] = curses.color_pair(pairindex)
                     if name is not None:
                         self.colorpairnames[name] = curses.color_pair(pairindex)
                 else:
@@ -1521,12 +1626,14 @@
                       c : confirm selected changes
                       r : review/edit and confirm selected changes
                       q : quit without confirming (no changes will be made)
-                      ? : help (what you're currently reading)""")
+                      ? : help (what you're currently reading)"""
+        )
 
         helpwin = curses.newwin(self.yscreensize, 0, 0, 0)
         helplines = helptext.split("\n")
-        helplines = helplines + [" "]*(
-            self.yscreensize - self.numstatuslines - len(helplines) - 1)
+        helplines = helplines + [" "] * (
+            self.yscreensize - self.numstatuslines - len(helplines) - 1
+        )
         try:
             for line in helplines:
                 self.printstring(helpwin, line, pairname="legend")
@@ -1548,7 +1655,7 @@
         self.commenttext = self.ui.edit(self.commenttext, self.ui.username())
         curses.cbreak()
         self.stdscr.refresh()
-        self.stdscr.keypad(1) # allow arrow-keys to continue to function
+        self.stdscr.keypad(1)  # allow arrow-keys to continue to function
 
     def handlefirstlineevent(self):
         """
@@ -1613,7 +1720,7 @@
         """ask for 'y' to be pressed to confirm selected. return True if
         confirmed."""
         confirmtext = _(
-"""If you answer yes to the following, your currently chosen patch chunks
+            """If you answer yes to the following, your currently chosen patch chunks
 will be loaded into an editor. To modify the patch, make the changes in your
 editor and save. To accept the current patch as-is, close the editor without
 saving.
@@ -1622,7 +1729,8 @@
       failing to follow this rule will result in the commit aborting.
 
 are you sure you want to review/edit and confirm the selected changes [yn]?
-""")
+"""
+        )
         with self.ui.timeblockedsection('crecord'):
             response = self.confirmationwindow(confirmtext)
         if response is None:
@@ -1642,15 +1750,19 @@
 
         if opts.get('amend') is None:
             opts['amend'] = True
-            msg = _("Amend option is turned on -- committing the currently "
-                    "selected changes will not create a new changeset, but "
-                    "instead update the most recently committed changeset.\n\n"
-                    "Press any key to continue.")
+            msg = _(
+                "Amend option is turned on -- committing the currently "
+                "selected changes will not create a new changeset, but "
+                "instead update the most recently committed changeset.\n\n"
+                "Press any key to continue."
+            )
         elif opts.get('amend') is True:
             opts['amend'] = None
-            msg = _("Amend option is turned off -- committing the currently "
-                    "selected changes will create a new changeset.\n\n"
-                    "Press any key to continue.")
+            msg = _(
+                "Amend option is turned off -- committing the currently "
+                "selected changes will create a new changeset.\n\n"
+                "Press any key to continue."
+            )
         if not test:
             self.confirmationwindow(msg)
 
@@ -1668,6 +1780,7 @@
         """
         edit the currently selected chunk
         """
+
         def updateui(self):
             self.numpadlines = self.getnumlinesdisplayed(ignorefolding=True) + 1
             self.chunkpad = curses.newpad(self.numpadlines, self.xscreensize)
@@ -1703,8 +1816,11 @@
                 self.stdscr.refresh()
 
             # remove comment lines
-            patch = [line + '\n' for line in patch.splitlines()
-                     if not line.startswith('#')]
+            patch = [
+                line + '\n'
+                for line in patch.splitlines()
+                if not line.startswith('#')
+            ]
             return patchmod.parsepatch(patch)
 
         if item is None:
@@ -1728,7 +1844,7 @@
         header = item.header
         editedhunkindex = header.hunks.index(item)
         hunksbefore = header.hunks[:editedhunkindex]
-        hunksafter = header.hunks[editedhunkindex + 1:]
+        hunksafter = header.hunks[editedhunkindex + 1 :]
         newpatchheader = newpatches[0]
         newhunks = [uihunk(h, header) for h in newpatchheader.hunks]
         newadded = sum([h.added for h in newhunks])
@@ -1831,8 +1947,7 @@
 
         origsigwinch = sentinel = object()
         if util.safehasattr(signal, 'SIGWINCH'):
-            origsigwinch = signal.signal(signal.SIGWINCH,
-                                         self.sigwinchhandler)
+            origsigwinch = signal.signal(signal.SIGWINCH, self.sigwinchhandler)
         try:
             return self._main(stdscr)
         finally:
@@ -1867,14 +1982,15 @@
         # available colors: black, blue, cyan, green, magenta, white, yellow
         # init_pair(color_id, foreground_color, background_color)
         self.initcolorpair(None, None, name="normal")
-        self.initcolorpair(curses.COLOR_WHITE, curses.COLOR_MAGENTA,
-                           name="selected")
+        self.initcolorpair(
+            curses.COLOR_WHITE, curses.COLOR_MAGENTA, name="selected"
+        )
         self.initcolorpair(curses.COLOR_RED, None, name="deletion")
         self.initcolorpair(curses.COLOR_GREEN, None, name="addition")
         self.initcolorpair(curses.COLOR_WHITE, curses.COLOR_BLUE, name="legend")
         # newwin([height, width,] begin_y, begin_x)
         self.statuswin = curses.newwin(self.numstatuslines, 0, 0, 0)
-        self.statuswin.keypad(1) # interpret arrow-key, etc. esc sequences
+        self.statuswin.keypad(1)  # interpret arrow-key, etc. esc sequences
 
         # figure out how much space to allocate for the chunk-pad which is
         # used for displaying the patch
@@ -1889,11 +2005,13 @@
             self.chunkpad = curses.newpad(self.numpadlines, self.xscreensize)
         except curses.error:
             self.initexc = fallbackerror(
-                _('this diff is too large to be displayed'))
+                _('this diff is too large to be displayed')
+            )
             return
         # initialize selecteditemendline (initial start-line is 0)
         self.selecteditemendline = self.getnumlinesdisplayed(
-            self.currentselecteditem, recursechildren=False)
+            self.currentselecteditem, recursechildren=False
+        )
 
         while True:
             self.updatescreen()
@@ -1909,7 +2027,8 @@
                 break
 
         if self.commenttext != "":
-            whitespaceremoved = re.sub(br"(?m)^\s.*(\n|$)", b"",
-                                       self.commenttext)
+            whitespaceremoved = re.sub(
+                br"(?m)^\s.*(\n|$)", b"", self.commenttext
+            )
             if whitespaceremoved != "":
                 self.opts['message'] = self.commenttext