Patchwork D5064: style: run black on a subset of mercurial

login
register
mail settings
Submitter phabricator
Date Oct. 13, 2018, 10:07 a.m.
Message ID <differential-rev-PHID-DREV-nkml4kjt3p7av36ismpx-req@phab.mercurial-scm.org>
Download mbox | patch
Permalink /patch/35862/
State New
Headers show

Comments

phabricator - Oct. 13, 2018, 10:07 a.m.
mjpieters created this revision.
mjpieters added reviewers: indygreg, durin42.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  This applied black to the 20 smallest files in mercurial/:
  
    ls -S1 mercurial/*.py | tail -n20 | xargs black

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D5064

AFFECTED FILES
  mercurial/cacheutil.py
  mercurial/diffhelper.py
  mercurial/dirstateguard.py
  mercurial/httpconnection.py
  mercurial/i18n.py
  mercurial/lsprofcalltree.py
  mercurial/mergeutil.py
  mercurial/minifileset.py
  mercurial/node.py
  mercurial/policy.py
  mercurial/pushkey.py
  mercurial/rcutil.py
  mercurial/rewriteutil.py
  mercurial/scmposix.py
  mercurial/scmwindows.py
  mercurial/stack.py
  mercurial/state.py
  mercurial/txnutil.py
  pyproject.toml

CHANGE DETAILS




To: mjpieters, indygreg, durin42, #hg-reviewers
Cc: mercurial-devel
phabricator - Oct. 13, 2018, 10:12 a.m.
mjpieters added a comment.


  The `import` parentheses collapsing is described here: https://github.com/ambv/black#parentheses. The behavior is not configurable.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D5064

To: mjpieters, indygreg, durin42, #hg-reviewers
Cc: mercurial-devel
phabricator - Oct. 13, 2018, 1:23 p.m.
indygreg added inline comments.

INLINE COMMENTS

> check-commit:43
> -    (r"\n\+\n( |\+)\n", "adds double empty line"),
> -    (r"\n \n\+\n", "adds double empty line"),
>      # Forbid "_" in function name.

I think we'll want to send this chunk as a separate commit, as it is a policy change. I'd be happy to accept that patch today.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D5064

To: mjpieters, indygreg, durin42, #hg-reviewers
Cc: mercurial-devel
phabricator - Nov. 14, 2018, 1:20 a.m.
indygreg added a comment.


  Where do we stand on the intent to mass reformat the code base?
  
  I'm not super thrilled at some of black's decisions (like using double quotes for all strings and merging imports into the same line which leads to excessive code churn later). But the exact style doesn't matter as much as having it be consistent. So I'm willing to go with black if we feel it's the best tool for the job. I'm not sure what the alternatives are these days.

INLINE COMMENTS

> mergeutil.py:18
> +        raise error.Abort(
> +            _("unresolved merge conflicts " "(see 'hg help resolve')")
> +        )

I'm surprised by this result. I'd like to think the reformatting tool would be smarter than this.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D5064

To: mjpieters, indygreg, durin42, #hg-reviewers
Cc: mercurial-devel
phabricator - Nov. 14, 2018, 6:41 a.m.
av6 added a comment.


  I look at the changes and see nitpicks at best. On the one hand, black proved better than any linter that we can already write consistent code. On the other, if black were a linter... I'd switch to flake8, which at least is configurable <https://www.mercurial-scm.org/repo/evolve/file/tip/setup.cfg#l1>.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D5064

To: mjpieters, indygreg, durin42, #hg-reviewers
Cc: av6, mercurial-devel
phabricator - Nov. 20, 2018, 1:47 p.m.
mjpieters added a comment.


  In https://phab.mercurial-scm.org/D5064#78545, @av6 wrote:
  
  > I look at the changes and see nitpicks at best. On the one hand, black proved better than any linter that we can already write consistent code. On the other, if black were a linter... I'd switch to flake8, which at least is configurable <https://www.mercurial-scm.org/repo/evolve/file/tip/setup.cfg#l1>.
  
  
  The whole **point** of black is that it is not configurable. Configurable means you still have to argue about style and decide on a configuration.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D5064

To: mjpieters, indygreg, durin42, #hg-reviewers
Cc: av6, mercurial-devel
phabricator - Nov. 27, 2018, 3:49 p.m.
durin42 added a comment.


  In https://phab.mercurial-scm.org/D5064#78780, @mjpieters wrote:
  
  > In https://phab.mercurial-scm.org/D5064#78545, @av6 wrote:
  >
  > > I look at the changes and see nitpicks at best. On the one hand, black proved better than any linter that we can already write consistent code. On the other, if black were a linter... I'd switch to flake8, which at least is configurable <https://www.mercurial-scm.org/repo/evolve/file/tip/setup.cfg#l1>.
  >
  >
  > The whole **point** of black is that it is not configurable. Configurable means you still have to argue about style and decide on a configuration.
  
  
  Yep. I find I care less about style decisions when the computer is able to make them for me: eg I prefer ' to ", but since black can fix that and I don't have to type the " myself, I don't really care.
  
  Does anyone strongly object, or do we want to embrace black and the formatting changes it implies?

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D5064

To: mjpieters, indygreg, durin42, #hg-reviewers
Cc: av6, mercurial-devel
phabricator - Nov. 27, 2018, 6:31 p.m.
mharbison72 added a comment.


  In https://phab.mercurial-scm.org/D5064#78990, @durin42 wrote:
  
  > Does anyone strongly object, or do we want to embrace black and the formatting changes it implies?
  
  
  Is there a fix extension configuration (and I guess precommit hook- I've never used it) for this?  If so, maybe it should go on the ContributingChanges page.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D5064

To: mjpieters, indygreg, durin42, #hg-reviewers
Cc: mharbison72, av6, mercurial-devel
phabricator - Nov. 29, 2018, 9:46 p.m.
durin42 added a comment.


  In https://phab.mercurial-scm.org/D5064#78994, @mharbison72 wrote:
  
  > In https://phab.mercurial-scm.org/D5064#78990, @durin42 wrote:
  >
  > > Does anyone strongly object, or do we want to embrace black and the formatting changes it implies?
  >
  >
  > Is there a fix extension configuration (and I guess precommit hook- I've never used it) for this?  If so, maybe it should go on the ContributingChanges page.
  
  
  My plan was to put an `hg fix` configuration in contrib and mention it in ContributingChanges. I'd advise against a hook for this, but if someone else wanted to write one I'd at least drop it in contrib as an example...

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D5064

To: mjpieters, indygreg, durin42, #hg-reviewers
Cc: mharbison72, av6, mercurial-devel
phabricator - Jan. 9, 2019, 8:30 p.m.
durin42 added a comment.


  Per mailing list thread, I've sent out https://phab.mercurial-scm.org/D5539 to show what yapf would want to do.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D5064

To: mjpieters, indygreg, durin42, #hg-reviewers
Cc: mharbison72, av6, mercurial-devel

Patch

diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,2 @@ 
+[tool.black]
+line-length = 80
diff --git a/mercurial/txnutil.py b/mercurial/txnutil.py
--- a/mercurial/txnutil.py
+++ b/mercurial/txnutil.py
@@ -9,27 +9,27 @@ 
 
 import errno
 
-from . import (
-    encoding,
-)
+from . import encoding
+
 
 def mayhavepending(root):
-    '''return whether 'root' may have pending changes, which are
+    """return whether 'root' may have pending changes, which are
     visible to this process.
-    '''
-    return root == encoding.environ.get('HG_PENDING')
+    """
+    return root == encoding.environ.get("HG_PENDING")
+
 
 def trypending(root, vfs, filename, **kwargs):
-    '''Open  file to be read according to HG_PENDING environment variable
+    """Open  file to be read according to HG_PENDING environment variable
 
     This opens '.pending' of specified 'filename' only when HG_PENDING
     is equal to 'root'.
 
     This returns '(fp, is_pending_opened)' tuple.
-    '''
+    """
     if mayhavepending(root):
         try:
-            return (vfs('%s.pending' % filename, **kwargs), True)
+            return (vfs("%s.pending" % filename, **kwargs), True)
         except IOError as inst:
             if inst.errno != errno.ENOENT:
                 raise
diff --git a/mercurial/state.py b/mercurial/state.py
--- a/mercurial/state.py
+++ b/mercurial/state.py
@@ -19,13 +19,9 @@ 
 
 from __future__ import absolute_import
 
-from . import (
-    error,
-    util,
-)
-from .utils import (
-    cborutil,
-)
+from . import error, util
+from .utils import cborutil
+
 
 class cmdstate(object):
     """a wrapper class to store the state of commands like `rebase`, `graft`,
@@ -58,23 +54,25 @@ 
         we use third-party library cbor to serialize data to write in the file.
         """
         if not isinstance(version, int):
-            raise error.ProgrammingError("version of state file should be"
-                                         " an integer")
+            raise error.ProgrammingError(
+                "version of state file should be" " an integer"
+            )
 
-        with self._repo.vfs(self.fname, 'wb', atomictemp=True) as fp:
-            fp.write('%d\n' % version)
+        with self._repo.vfs(self.fname, "wb", atomictemp=True) as fp:
+            fp.write("%d\n" % version)
             for chunk in cborutil.streamencode(data):
                 fp.write(chunk)
 
     def _read(self):
         """reads the state file and returns a dictionary which contain
         data in the same format as it was before storing"""
-        with self._repo.vfs(self.fname, 'rb') as fp:
+        with self._repo.vfs(self.fname, "rb") as fp:
             try:
                 int(fp.readline())
             except ValueError:
-                raise error.CorruptedState("unknown version of state file"
-                                           " found")
+                raise error.CorruptedState(
+                    "unknown version of state file" " found"
+                )
 
             return cborutil.decodeall(fp.read())[0]
 
diff --git a/mercurial/stack.py b/mercurial/stack.py
--- a/mercurial/stack.py
+++ b/mercurial/stack.py
@@ -7,10 +7,8 @@ 
 
 from __future__ import absolute_import
 
-from . import (
-    revsetlang,
-    scmutil,
-)
+from . import revsetlang, scmutil
+
 
 def getstack(repo, rev=None):
     """return a sorted smartrev of the stack containing either rev if it is
@@ -20,9 +18,9 @@ 
     the revision and are not merges.
     """
     if rev is None:
-        rev = '.'
+        rev = "."
 
-    revspec = 'reverse(only(%s) and not public() and not ::merge())'
+    revspec = "reverse(only(%s) and not public() and not ::merge())"
     revset = revsetlang.formatspec(revspec, rev)
     revisions = scmutil.revrange(repo, [revset])
     revisions.sort()
diff --git a/mercurial/scmwindows.py b/mercurial/scmwindows.py
--- a/mercurial/scmwindows.py
+++ b/mercurial/scmwindows.py
@@ -2,60 +2,59 @@ 
 
 import os
 
-from . import (
-    encoding,
-    pycompat,
-    util,
-    win32,
-)
+from . import encoding, pycompat, util, win32
 
 try:
     import _winreg as winreg
+
     winreg.CloseKey
 except ImportError:
     import winreg
 
 # MS-DOS 'more' is the only pager available by default on Windows.
-fallbackpager = 'more'
+fallbackpager = "more"
+
 
 def systemrcpath():
-    '''return default os-specific hgrc search path'''
+    """return default os-specific hgrc search path"""
     rcpath = []
     filename = win32.executablepath()
     # Use mercurial.ini found in directory with hg.exe
-    progrc = os.path.join(os.path.dirname(filename), 'mercurial.ini')
+    progrc = os.path.join(os.path.dirname(filename), "mercurial.ini")
     rcpath.append(progrc)
     # Use hgrc.d found in directory with hg.exe
-    progrcd = os.path.join(os.path.dirname(filename), 'hgrc.d')
+    progrcd = os.path.join(os.path.dirname(filename), "hgrc.d")
     if os.path.isdir(progrcd):
         for f, kind in util.listdir(progrcd):
-            if f.endswith('.rc'):
+            if f.endswith(".rc"):
                 rcpath.append(os.path.join(progrcd, f))
     # else look for a system rcpath in the registry
-    value = util.lookupreg('SOFTWARE\\Mercurial', None,
-                           winreg.HKEY_LOCAL_MACHINE)
+    value = util.lookupreg(
+        "SOFTWARE\\Mercurial", None, winreg.HKEY_LOCAL_MACHINE
+    )
     if not isinstance(value, str) or not value:
         return rcpath
     value = util.localpath(value)
     for p in value.split(pycompat.ospathsep):
-        if p.lower().endswith('mercurial.ini'):
+        if p.lower().endswith("mercurial.ini"):
             rcpath.append(p)
         elif os.path.isdir(p):
             for f, kind in util.listdir(p):
-                if f.endswith('.rc'):
+                if f.endswith(".rc"):
                     rcpath.append(os.path.join(p, f))
     return rcpath
 
+
 def userrcpath():
-    '''return os-specific hgrc search path to the user dir'''
-    home = os.path.expanduser('~')
-    path = [os.path.join(home, 'mercurial.ini'),
-            os.path.join(home, '.hgrc')]
-    userprofile = encoding.environ.get('USERPROFILE')
+    """return os-specific hgrc search path to the user dir"""
+    home = os.path.expanduser("~")
+    path = [os.path.join(home, "mercurial.ini"), os.path.join(home, ".hgrc")]
+    userprofile = encoding.environ.get("USERPROFILE")
     if userprofile and userprofile != home:
-        path.append(os.path.join(userprofile, 'mercurial.ini'))
-        path.append(os.path.join(userprofile, '.hgrc'))
+        path.append(os.path.join(userprofile, "mercurial.ini"))
+        path.append(os.path.join(userprofile, ".hgrc"))
     return path
 
+
 def termsize(ui):
     return win32.termsize()
diff --git a/mercurial/scmposix.py b/mercurial/scmposix.py
--- a/mercurial/scmposix.py
+++ b/mercurial/scmposix.py
@@ -6,59 +6,66 @@ 
 import os
 import sys
 
-from . import (
-    encoding,
-    pycompat,
-    util,
-)
+from . import encoding, pycompat, util
 
 # BSD 'more' escapes ANSI color sequences by default. This can be disabled by
 # $MORE variable, but there's no compatible option with Linux 'more'. Given
 # OS X is widely used and most modern Unix systems would have 'less', setting
 # 'less' as the default seems reasonable.
-fallbackpager = 'less'
+fallbackpager = "less"
+
 
 def _rcfiles(path):
-    rcs = [os.path.join(path, 'hgrc')]
-    rcdir = os.path.join(path, 'hgrc.d')
+    rcs = [os.path.join(path, "hgrc")]
+    rcdir = os.path.join(path, "hgrc.d")
     try:
-        rcs.extend([os.path.join(rcdir, f)
-                    for f, kind in util.listdir(rcdir)
-                    if f.endswith(".rc")])
+        rcs.extend(
+            [
+                os.path.join(rcdir, f)
+                for f, kind in util.listdir(rcdir)
+                if f.endswith(".rc")
+            ]
+        )
     except OSError:
         pass
     return rcs
 
+
 def systemrcpath():
     path = []
-    if pycompat.sysplatform == 'plan9':
-        root = 'lib/mercurial'
+    if pycompat.sysplatform == "plan9":
+        root = "lib/mercurial"
     else:
-        root = 'etc/mercurial'
+        root = "etc/mercurial"
     # old mod_python does not set sys.argv
-    if len(getattr(sys, 'argv', [])) > 0:
+    if len(getattr(sys, "argv", [])) > 0:
         p = os.path.dirname(os.path.dirname(pycompat.sysargv[0]))
-        if p != '/':
+        if p != "/":
             path.extend(_rcfiles(os.path.join(p, root)))
-    path.extend(_rcfiles('/' + root))
+    path.extend(_rcfiles("/" + root))
     return path
 
+
 def userrcpath():
-    if pycompat.sysplatform == 'plan9':
-        return [encoding.environ['home'] + '/lib/hgrc']
+    if pycompat.sysplatform == "plan9":
+        return [encoding.environ["home"] + "/lib/hgrc"]
     elif pycompat.isdarwin:
-        return [os.path.expanduser('~/.hgrc')]
+        return [os.path.expanduser("~/.hgrc")]
     else:
-        confighome = encoding.environ.get('XDG_CONFIG_HOME')
+        confighome = encoding.environ.get("XDG_CONFIG_HOME")
         if confighome is None or not os.path.isabs(confighome):
-            confighome = os.path.expanduser('~/.config')
+            confighome = os.path.expanduser("~/.config")
 
-        return [os.path.expanduser('~/.hgrc'),
-                os.path.join(confighome, 'hg', 'hgrc')]
+        return [
+            os.path.expanduser("~/.hgrc"),
+            os.path.join(confighome, "hg", "hgrc"),
+        ]
+
 
 def termsize(ui):
     try:
         import termios
+
         TIOCGWINSZ = termios.TIOCGWINSZ  # unavailable on IRIX (issue3449)
     except (AttributeError, ImportError):
         return 80, 24
@@ -71,8 +78,8 @@ 
                 continue
             if not os.isatty(fd):
                 continue
-            arri = fcntl.ioctl(fd, TIOCGWINSZ, '\0' * 8)
-            height, width = array.array(r'h', arri)[:2]
+            arri = fcntl.ioctl(fd, TIOCGWINSZ, "\0" * 8)
+            height, width = array.array(r"h", arri)[:2]
             if width > 0 and height > 0:
                 return width, height
         except ValueError:
diff --git a/mercurial/rewriteutil.py b/mercurial/rewriteutil.py
--- a/mercurial/rewriteutil.py
+++ b/mercurial/rewriteutil.py
@@ -9,14 +9,10 @@ 
 
 from .i18n import _
 
-from . import (
-    error,
-    node,
-    obsolete,
-    revset,
-)
+from . import error, node, obsolete, revset
 
-def precheck(repo, revs, action='rewrite'):
+
+def precheck(repo, revs, action="rewrite"):
     """check if revs can be rewritten
     action is used to control the error message.
 
@@ -27,7 +23,7 @@ 
         hint = _("no changeset checked out")
         raise error.Abort(msg, hint=hint)
 
-    publicrevs = repo.revs('%ld and public()', revs)
+    publicrevs = repo.revs("%ld and public()", revs)
     if len(repo[None].parents()) > 1:
         raise error.Abort(_("cannot %s while merging") % action)
 
@@ -40,6 +36,7 @@ 
     if newunstable:
         raise error.Abort(_("cannot %s changeset with children") % action)
 
+
 def disallowednewunstable(repo, revs):
     """Checks whether editing the revs will create new unstable changesets and
     are we allowed to create them.
diff --git a/mercurial/rcutil.py b/mercurial/rcutil.py
--- a/mercurial/rcutil.py
+++ b/mercurial/rcutil.py
@@ -9,11 +9,7 @@ 
 
 import os
 
-from . import (
-    encoding,
-    pycompat,
-    util,
-)
+from . import encoding, pycompat, util
 
 if pycompat.iswindows:
     from . import scmwindows as scmplatform
@@ -24,46 +20,50 @@ 
 systemrcpath = scmplatform.systemrcpath
 userrcpath = scmplatform.userrcpath
 
+
 def _expandrcpath(path):
-    '''path could be a file or a directory. return a list of file paths'''
+    """path could be a file or a directory. return a list of file paths"""
     p = util.expandpath(path)
     if os.path.isdir(p):
         join = os.path.join
-        return [join(p, f) for f, k in util.listdir(p) if f.endswith('.rc')]
+        return [join(p, f) for f, k in util.listdir(p) if f.endswith(".rc")]
     return [p]
 
+
 def envrcitems(env=None):
-    '''Return [(section, name, value, source)] config items.
+    """Return [(section, name, value, source)] config items.
 
     The config items are extracted from environment variables specified by env,
     used to override systemrc, but not userrc.
 
     If env is not provided, encoding.environ will be used.
-    '''
+    """
     if env is None:
         env = encoding.environ
     checklist = [
-        ('EDITOR', 'ui', 'editor'),
-        ('VISUAL', 'ui', 'editor'),
-        ('PAGER', 'pager', 'pager'),
+        ("EDITOR", "ui", "editor"),
+        ("VISUAL", "ui", "editor"),
+        ("PAGER", "pager", "pager"),
     ]
     result = []
     for envname, section, configname in checklist:
         if envname not in env:
             continue
-        result.append((section, configname, env[envname], '$%s' % envname))
+        result.append((section, configname, env[envname], "$%s" % envname))
     return result
 
+
 def defaultrcpath():
-    '''return rc paths in default.d'''
+    """return rc paths in default.d"""
     path = []
-    defaultpath = os.path.join(util.datapath, 'default.d')
+    defaultpath = os.path.join(util.datapath, "default.d")
     if os.path.isdir(defaultpath):
         path = _expandrcpath(defaultpath)
     return path
 
+
 def rccomponents():
-    '''return an ordered [(type, obj)] about where to load configs.
+    """return an ordered [(type, obj)] about where to load configs.
 
     respect $HGRCPATH. if $HGRCPATH is empty, only .hg/hgrc of current repo is
     used. if $HGRCPATH is not set, the platform default will be used.
@@ -73,26 +73,27 @@ 
     type could be either 'path' or 'items', if type is 'path', obj is a string,
     and is the config file path. if type is 'items', obj is a list of (section,
     name, value, source) that should fill the config directly.
-    '''
-    envrc = ('items', envrcitems())
+    """
+    envrc = ("items", envrcitems())
 
-    if 'HGRCPATH' in encoding.environ:
+    if "HGRCPATH" in encoding.environ:
         # assume HGRCPATH is all about user configs so environments can be
         # overridden.
         _rccomponents = [envrc]
-        for p in encoding.environ['HGRCPATH'].split(pycompat.ospathsep):
+        for p in encoding.environ["HGRCPATH"].split(pycompat.ospathsep):
             if not p:
                 continue
-            _rccomponents.extend(('path', p) for p in _expandrcpath(p))
+            _rccomponents.extend(("path", p) for p in _expandrcpath(p))
     else:
-        normpaths = lambda paths: [('path', os.path.normpath(p)) for p in paths]
+        normpaths = lambda paths: [("path", os.path.normpath(p)) for p in paths]
         _rccomponents = normpaths(defaultrcpath() + systemrcpath())
         _rccomponents.append(envrc)
         _rccomponents.extend(normpaths(userrcpath()))
     return _rccomponents
 
+
 def defaultpagerenv():
-    '''return a dict of default environment variables and their values,
+    """return a dict of default environment variables and their values,
     intended to be set before starting a pager.
-    '''
-    return {'LESS': 'FRX', 'LV': '-c'}
+    """
+    return {"LESS": "FRX", "LV": "-c"}
diff --git a/mercurial/pushkey.py b/mercurial/pushkey.py
--- a/mercurial/pushkey.py
+++ b/mercurial/pushkey.py
@@ -7,55 +7,60 @@ 
 
 from __future__ import absolute_import
 
-from . import (
-    bookmarks,
-    encoding,
-    obsolete,
-    phases,
-)
+from . import bookmarks, encoding, obsolete, phases
+
 
 def _nslist(repo):
     n = {}
     for k in _namespaces:
         n[k] = ""
     if not obsolete.isenabled(repo, obsolete.exchangeopt):
-        n.pop('obsolete')
+        n.pop("obsolete")
     return n
 
-_namespaces = {"namespaces": (lambda *x: False, _nslist),
-               "bookmarks": (bookmarks.pushbookmark, bookmarks.listbookmarks),
-               "phases": (phases.pushphase, phases.listphases),
-               "obsolete": (obsolete.pushmarker, obsolete.listmarkers),
-              }
+
+_namespaces = {
+    "namespaces": (lambda *x: False, _nslist),
+    "bookmarks": (bookmarks.pushbookmark, bookmarks.listbookmarks),
+    "phases": (phases.pushphase, phases.listphases),
+    "obsolete": (obsolete.pushmarker, obsolete.listmarkers),
+}
+
 
 def register(namespace, pushkey, listkeys):
     _namespaces[namespace] = (pushkey, listkeys)
 
+
 def _get(namespace):
     return _namespaces.get(namespace, (lambda *x: False, lambda *x: {}))
 
+
 def push(repo, namespace, key, old, new):
-    '''should succeed iff value was old'''
+    """should succeed iff value was old"""
     pk = _get(namespace)[0]
     return pk(repo, key, old, new)
 
+
 def list(repo, namespace):
-    '''return a dict'''
+    """return a dict"""
     lk = _get(namespace)[1]
     return lk(repo)
 
+
 encode = encoding.fromlocal
 
 decode = encoding.tolocal
 
+
 def encodekeys(keys):
     """encode the content of a pushkey namespace for exchange over the wire"""
-    return '\n'.join(['%s\t%s' % (encode(k), encode(v)) for k, v in keys])
+    return "\n".join(["%s\t%s" % (encode(k), encode(v)) for k, v in keys])
+
 
 def decodekeys(data):
     """decode the content of a pushkey namespace from exchange over the wire"""
     result = {}
     for l in data.splitlines():
-        k, v = l.split('\t')
+        k, v = l.split("\t")
         result[decode(k)] = decode(v)
     return result
diff --git a/mercurial/policy.py b/mercurial/policy.py
--- a/mercurial/policy.py
+++ b/mercurial/policy.py
@@ -21,79 +21,86 @@ 
 # By default, fall back to the pure modules so the in-place build can
 # run without recompiling the C extensions. This will be overridden by
 # __modulepolicy__ generated by setup.py.
-policy = b'allow'
+policy = b"allow"
 _packageprefs = {
     # policy: (versioned package, pure package)
-    b'c': (r'cext', None),
-    b'allow': (r'cext', r'pure'),
-    b'cffi': (r'cffi', None),
-    b'cffi-allow': (r'cffi', r'pure'),
-    b'py': (None, r'pure'),
+    b"c": (r"cext", None),
+    b"allow": (r"cext", r"pure"),
+    b"cffi": (r"cffi", None),
+    b"cffi-allow": (r"cffi", r"pure"),
+    b"py": (None, r"pure"),
 }
 
 try:
     from . import __modulepolicy__
+
     policy = __modulepolicy__.modulepolicy
 except ImportError:
     pass
 
 # PyPy doesn't load C extensions.
 #
 # The canonical way to do this is to test platform.python_implementation().
 # But we don't import platform and don't bloat for it here.
-if r'__pypy__' in sys.builtin_module_names:
-    policy = b'cffi'
+if r"__pypy__" in sys.builtin_module_names:
+    policy = b"cffi"
 
 # Environment variable can always force settings.
 if sys.version_info[0] >= 3:
-    if r'HGMODULEPOLICY' in os.environ:
-        policy = os.environ[r'HGMODULEPOLICY'].encode(r'utf-8')
+    if r"HGMODULEPOLICY" in os.environ:
+        policy = os.environ[r"HGMODULEPOLICY"].encode(r"utf-8")
 else:
-    policy = os.environ.get(r'HGMODULEPOLICY', policy)
+    policy = os.environ.get(r"HGMODULEPOLICY", policy)
+
 
 def _importfrom(pkgname, modname):
     # from .<pkgname> import <modname> (where . is looked through this module)
     fakelocals = {}
     pkg = __import__(pkgname, globals(), fakelocals, [modname], level=1)
     try:
         fakelocals[modname] = mod = getattr(pkg, modname)
     except AttributeError:
-        raise ImportError(r'cannot import name %s' % modname)
+        raise ImportError(r"cannot import name %s" % modname)
     # force import; fakelocals[modname] may be replaced with the real module
-    getattr(mod, r'__doc__', None)
+    getattr(mod, r"__doc__", None)
     return fakelocals[modname]
 
+
 # keep in sync with "version" in C modules
 _cextversions = {
-    (r'cext', r'base85'): 1,
-    (r'cext', r'bdiff'): 3,
-    (r'cext', r'mpatch'): 1,
-    (r'cext', r'osutil'): 4,
-    (r'cext', r'parsers'): 11,
+    (r"cext", r"base85"): 1,
+    (r"cext", r"bdiff"): 3,
+    (r"cext", r"mpatch"): 1,
+    (r"cext", r"osutil"): 4,
+    (r"cext", r"parsers"): 11,
 }
 
 # map import request to other package or module
 _modredirects = {
-    (r'cext', r'charencode'): (r'cext', r'parsers'),
-    (r'cffi', r'base85'): (r'pure', r'base85'),
-    (r'cffi', r'charencode'): (r'pure', r'charencode'),
-    (r'cffi', r'parsers'): (r'pure', r'parsers'),
+    (r"cext", r"charencode"): (r"cext", r"parsers"),
+    (r"cffi", r"base85"): (r"pure", r"base85"),
+    (r"cffi", r"charencode"): (r"pure", r"charencode"),
+    (r"cffi", r"parsers"): (r"pure", r"parsers"),
 }
 
+
 def _checkmod(pkgname, modname, mod):
     expected = _cextversions.get((pkgname, modname))
-    actual = getattr(mod, r'version', None)
+    actual = getattr(mod, r"version", None)
     if actual != expected:
-        raise ImportError(r'cannot import module %s.%s '
-                          r'(expected version: %d, actual: %r)'
-                          % (pkgname, modname, expected, actual))
+        raise ImportError(
+            r"cannot import module %s.%s "
+            r"(expected version: %d, actual: %r)"
+            % (pkgname, modname, expected, actual)
+        )
+
 
 def importmod(modname):
     """Import module according to policy and check API version"""
     try:
         verpkg, purepkg = _packageprefs[policy]
     except KeyError:
-        raise ImportError(r'invalid HGMODULEPOLICY %r' % policy)
+        raise ImportError(r"invalid HGMODULEPOLICY %r" % policy)
     assert verpkg or purepkg
     if verpkg:
         pn, mn = _modredirects.get((verpkg, modname), (verpkg, modname))
diff --git a/mercurial/node.py b/mercurial/node.py
--- a/mercurial/node.py
+++ b/mercurial/node.py
@@ -20,28 +20,30 @@ 
     except binascii.Error as e:
         raise TypeError(e)
 
+
 nullrev = -1
 # In hex, this is '0000000000000000000000000000000000000000'
 nullid = b"\0" * 20
 nullhex = hex(nullid)
 
 # Phony node value to stand-in for new files in some uses of
 # manifests.
 # In hex, this is '2121212121212121212121212121212121212121'
-newnodeid = '!!!!!!!!!!!!!!!!!!!!'
+newnodeid = "!!!!!!!!!!!!!!!!!!!!"
 # In hex, this is '3030303030303030303030303030306164646564'
-addednodeid = '000000000000000added'
+addednodeid = "000000000000000added"
 # In hex, this is '3030303030303030303030306d6f646966696564'
-modifiednodeid = '000000000000modified'
+modifiednodeid = "000000000000modified"
 
 wdirfilenodeids = {newnodeid, addednodeid, modifiednodeid}
 
 # pseudo identifiers for working directory
 # (they are experimental, so don't add too many dependencies on them)
-wdirrev = 0x7fffffff
+wdirrev = 0x7FFFFFFF
 # In hex, this is 'ffffffffffffffffffffffffffffffffffffffff'
 wdirid = b"\xff" * 20
 wdirhex = hex(wdirid)
 
+
 def short(node):
     return hex(node[:6])
diff --git a/mercurial/minifileset.py b/mercurial/minifileset.py
--- a/mercurial/minifileset.py
+++ b/mercurial/minifileset.py
@@ -8,69 +8,72 @@ 
 from __future__ import absolute_import
 
 from .i18n import _
-from . import (
-    error,
-    fileset,
-    filesetlang,
-    pycompat,
-)
+from . import error, fileset, filesetlang, pycompat
+
 
 def _sizep(x):
     # i18n: "size" is a keyword
     expr = filesetlang.getstring(x, _("size requires an expression"))
     return fileset.sizematcher(expr)
 
+
 def _compile(tree):
     if not tree:
         raise error.ParseError(_("missing argument"))
     op = tree[0]
-    if op == 'withstatus':
+    if op == "withstatus":
         return _compile(tree[1])
-    elif op in {'symbol', 'string', 'kindpat'}:
-        name = filesetlang.getpattern(tree, {'path'}, _('invalid file pattern'))
-        if name.startswith('**'): # file extension test, ex. "**.tar.gz"
+    elif op in {"symbol", "string", "kindpat"}:
+        name = filesetlang.getpattern(tree, {"path"}, _("invalid file pattern"))
+        if name.startswith("**"):  # file extension test, ex. "**.tar.gz"
             ext = name[2:]
             for c in pycompat.bytestr(ext):
-                if c in '*{}[]?/\\':
-                    raise error.ParseError(_('reserved character: %s') % c)
+                if c in "*{}[]?/\\":
+                    raise error.ParseError(_("reserved character: %s") % c)
             return lambda n, s: n.endswith(ext)
-        elif name.startswith('path:'): # directory or full path test
-            p = name[5:] # prefix
+        elif name.startswith("path:"):  # directory or full path test
+            p = name[5:]  # prefix
             pl = len(p)
-            f = lambda n, s: n.startswith(p) and (len(n) == pl
-                                                  or n[pl:pl + 1] == '/')
+            f = lambda n, s: n.startswith(p) and (
+                len(n) == pl or n[pl : pl + 1] == "/"
+            )
             return f
-        raise error.ParseError(_("unsupported file pattern: %s") % name,
-                               hint=_('paths must be prefixed with "path:"'))
-    elif op in {'or', 'patterns'}:
+        raise error.ParseError(
+            _("unsupported file pattern: %s") % name,
+            hint=_('paths must be prefixed with "path:"'),
+        )
+    elif op in {"or", "patterns"}:
         funcs = [_compile(x) for x in tree[1:]]
         return lambda n, s: any(f(n, s) for f in funcs)
-    elif op == 'and':
+    elif op == "and":
         func1 = _compile(tree[1])
         func2 = _compile(tree[2])
         return lambda n, s: func1(n, s) and func2(n, s)
-    elif op == 'not':
+    elif op == "not":
         return lambda n, s: not _compile(tree[1])(n, s)
-    elif op == 'func':
+    elif op == "func":
         symbols = {
-            'all': lambda n, s: True,
-            'none': lambda n, s: False,
-            'size': lambda n, s: _sizep(tree[2])(s),
+            "all": lambda n, s: True,
+            "none": lambda n, s: False,
+            "size": lambda n, s: _sizep(tree[2])(s),
         }
 
         name = filesetlang.getsymbol(tree[1])
         if name in symbols:
             return symbols[name]
 
         raise error.UnknownIdentifier(name, symbols.keys())
-    elif op == 'minus':     # equivalent to 'x and not y'
+    elif op == "minus":  # equivalent to 'x and not y'
         func1 = _compile(tree[1])
         func2 = _compile(tree[2])
         return lambda n, s: func1(n, s) and not func2(n, s)
-    elif op == 'list':
-        raise error.ParseError(_("can't use a list in this context"),
-                               hint=_('see \'hg help "filesets.x or y"\''))
-    raise error.ProgrammingError('illegal tree: %r' % (tree,))
+    elif op == "list":
+        raise error.ParseError(
+            _("can't use a list in this context"),
+            hint=_("see 'hg help \"filesets.x or y\"'"),
+        )
+    raise error.ProgrammingError("illegal tree: %r" % (tree,))
+
 
 def compile(text):
     """generate a function (path, size) -> bool from filter specification.
diff --git a/mercurial/mergeutil.py b/mercurial/mergeutil.py
--- a/mercurial/mergeutil.py
+++ b/mercurial/mergeutil.py
@@ -9,14 +9,16 @@ 
 
 from .i18n import _
 
-from . import (
-    error,
-)
+from . import error
+
 
 def checkunresolved(ms):
     if list(ms.unresolved()):
-        raise error.Abort(_("unresolved merge conflicts "
-                            "(see 'hg help resolve')"))
-    if ms.mdstate() != 's' or list(ms.driverresolved()):
-        raise error.Abort(_('driver-resolved merge conflicts'),
-                          hint=_('run "hg resolve --all" to resolve'))
+        raise error.Abort(
+            _("unresolved merge conflicts " "(see 'hg help resolve')")
+        )
+    if ms.mdstate() != "s" or list(ms.driverresolved()):
+        raise error.Abort(
+            _("driver-resolved merge conflicts"),
+            hint=_('run "hg resolve --all" to resolve'),
+        )
diff --git a/mercurial/lsprofcalltree.py b/mercurial/lsprofcalltree.py
--- a/mercurial/lsprofcalltree.py
+++ b/mercurial/lsprofcalltree.py
@@ -12,27 +12,29 @@ 
 
 from __future__ import absolute_import
 
-from . import (
-    pycompat,
-)
+from . import pycompat
+
 
 def label(code):
     if isinstance(code, str):
         # built-in functions ('~' sorts at the end)
-        return '~' + pycompat.sysbytes(code)
+        return "~" + pycompat.sysbytes(code)
     else:
-        return '%s %s:%d' % (pycompat.sysbytes(code.co_name),
-                             pycompat.sysbytes(code.co_filename),
-                             code.co_firstlineno)
+        return "%s %s:%d" % (
+            pycompat.sysbytes(code.co_name),
+            pycompat.sysbytes(code.co_filename),
+            code.co_firstlineno,
+        )
+
 
 class KCacheGrind(object):
     def __init__(self, profiler):
         self.data = profiler.getstats()
         self.out_file = None
 
     def output(self, out_file):
         self.out_file = out_file
-        out_file.write(b'events: Ticks\n')
+        out_file.write(b"events: Ticks\n")
         self._print_summary()
         for entry in self.data:
             self._entry(entry)
@@ -42,24 +44,24 @@ 
         for entry in self.data:
             totaltime = int(entry.totaltime * 1000)
             max_cost = max(max_cost, totaltime)
-        self.out_file.write(b'summary: %d\n' % max_cost)
+        self.out_file.write(b"summary: %d\n" % max_cost)
 
     def _entry(self, entry):
         out_file = self.out_file
 
         code = entry.code
         if isinstance(code, str):
-            out_file.write(b'fi=~\n')
+            out_file.write(b"fi=~\n")
         else:
-            out_file.write(b'fi=%s\n' % pycompat.sysbytes(code.co_filename))
+            out_file.write(b"fi=%s\n" % pycompat.sysbytes(code.co_filename))
 
-        out_file.write(b'fn=%s\n' % label(code))
+        out_file.write(b"fn=%s\n" % label(code))
 
         inlinetime = int(entry.inlinetime * 1000)
         if isinstance(code, str):
-            out_file.write(b'0 %d\n' % inlinetime)
+            out_file.write(b"0 %d\n" % inlinetime)
         else:
-            out_file.write(b'%d %d\n' % (code.co_firstlineno, inlinetime))
+            out_file.write(b"%d %d\n" % (code.co_firstlineno, inlinetime))
 
         # recursive calls are counted in entry.calls
         if entry.calls:
@@ -75,19 +77,20 @@ 
         for subentry in calls:
             self._subentry(lineno, subentry)
 
-        out_file.write(b'\n')
+        out_file.write(b"\n")
 
     def _subentry(self, lineno, subentry):
         out_file = self.out_file
         code = subentry.code
-        out_file.write(b'cfn=%s\n' % label(code))
+        out_file.write(b"cfn=%s\n" % label(code))
         if isinstance(code, str):
-            out_file.write(b'cfi=~\n')
-            out_file.write(b'calls=%d 0\n' % subentry.callcount)
+            out_file.write(b"cfi=~\n")
+            out_file.write(b"calls=%d 0\n" % subentry.callcount)
         else:
-            out_file.write(b'cfi=%s\n' % pycompat.sysbytes(code.co_filename))
-            out_file.write(b'calls=%d %d\n' % (
-                subentry.callcount, code.co_firstlineno))
+            out_file.write(b"cfi=%s\n" % pycompat.sysbytes(code.co_filename))
+            out_file.write(
+                b"calls=%d %d\n" % (subentry.callcount, code.co_firstlineno)
+            )
 
         totaltime = int(subentry.totaltime * 1000)
-        out_file.write(b'%d %d\n' % (lineno, totaltime))
+        out_file.write(b"%d %d\n" % (lineno, totaltime))
diff --git a/mercurial/i18n.py b/mercurial/i18n.py
--- a/mercurial/i18n.py
+++ b/mercurial/i18n.py
@@ -12,49 +12,52 @@ 
 import os
 import sys
 
-from . import (
-    encoding,
-    pycompat,
-)
+from . import encoding, pycompat
 
 # modelled after templater.templatepath:
-if getattr(sys, 'frozen', None) is not None:
+if getattr(sys, "frozen", None) is not None:
     module = pycompat.sysexecutable
 else:
     module = pycompat.fsencode(__file__)
 
 _languages = None
-if (pycompat.iswindows
-    and 'LANGUAGE' not in encoding.environ
-    and 'LC_ALL' not in encoding.environ
-    and 'LC_MESSAGES' not in encoding.environ
-    and 'LANG' not in encoding.environ):
+if (
+    pycompat.iswindows
+    and "LANGUAGE" not in encoding.environ
+    and "LC_ALL" not in encoding.environ
+    and "LC_MESSAGES" not in encoding.environ
+    and "LANG" not in encoding.environ
+):
     # Try to detect UI language by "User Interface Language Management" API
     # if no locale variables are set. Note that locale.getdefaultlocale()
     # uses GetLocaleInfo(), which may be different from UI language.
     # (See http://msdn.microsoft.com/en-us/library/dd374098(v=VS.85).aspx )
     try:
         import ctypes
+
         langid = ctypes.windll.kernel32.GetUserDefaultUILanguage()
         _languages = [locale.windows_locale[langid]]
     except (ImportError, AttributeError, KeyError):
         # ctypes not found or unknown langid
         pass
 
 _ugettext = None
 
+
 def setdatapath(datapath):
     datapath = pycompat.fsdecode(datapath)
-    localedir = os.path.join(datapath, r'locale')
-    t = gettextmod.translation(r'hg', localedir, _languages, fallback=True)
+    localedir = os.path.join(datapath, r"locale")
+    t = gettextmod.translation(r"hg", localedir, _languages, fallback=True)
     global _ugettext
     try:
         _ugettext = t.ugettext
     except AttributeError:
         _ugettext = t.gettext
 
+
 _msgcache = {}  # encoding: {message: translation}
 
+
 def gettext(message):
     """Translate message.
 
@@ -73,12 +76,12 @@ 
     if message not in cache:
         if type(message) is pycompat.unicode:
             # goofy unicode docstrings in test
-            paragraphs = message.split(u'\n\n')
+            paragraphs = message.split(u"\n\n")
         else:
-            paragraphs = [p.decode("ascii") for p in message.split('\n\n')]
+            paragraphs = [p.decode("ascii") for p in message.split("\n\n")]
         # Be careful not to translate the empty string -- it holds the
         # meta data of the .po file.
-        u = u'\n\n'.join([p and _ugettext(p) or u'' for p in paragraphs])
+        u = u"\n\n".join([p and _ugettext(p) or u"" for p in paragraphs])
         try:
             # encoding.tolocal cannot be used since it will first try to
             # decode the Unicode string. Calling u.decode(enc) really
@@ -92,12 +95,16 @@ 
             cache[message] = message
     return cache[message]
 
+
 def _plain():
-    if ('HGPLAIN' not in encoding.environ
-        and 'HGPLAINEXCEPT' not in encoding.environ):
+    if (
+        "HGPLAIN" not in encoding.environ
+        and "HGPLAINEXCEPT" not in encoding.environ
+    ):
         return False
-    exceptions = encoding.environ.get('HGPLAINEXCEPT', '').strip().split(',')
-    return 'i18n' not in exceptions
+    exceptions = encoding.environ.get("HGPLAINEXCEPT", "").strip().split(",")
+    return "i18n" not in exceptions
+
 
 if _plain():
     _ = lambda message: message
diff --git a/mercurial/httpconnection.py b/mercurial/httpconnection.py
--- a/mercurial/httpconnection.py
+++ b/mercurial/httpconnection.py
@@ -13,10 +13,7 @@ 
 import os
 
 from .i18n import _
-from . import (
-    pycompat,
-    util,
-)
+from . import pycompat, util
 
 urlerr = util.urlerr
 urlreq = util.urlreq
@@ -43,8 +40,9 @@ 
         # requires authentication. Since we can't know until we try
         # once whether authentication will be required, just lie to
         # the user and maybe the push succeeds suddenly at 50%.
-        self._progress = ui.makeprogress(_('sending'), unit=_('kb'),
-                                         total=(self.length // 1024 * 2))
+        self._progress = ui.makeprogress(
+            _("sending"), unit=_("kb"), total=(self.length // 1024 * 2)
+        )
 
     def read(self, *args, **kwargs):
         ret = self._data.read(*args, **kwargs)
@@ -61,49 +59,58 @@ 
     def __exit__(self, exc_type, exc_val, exc_tb):
         self.close()
 
+
 # moved here from url.py to avoid a cycle
 def readauthforuri(ui, uri, user):
     uri = pycompat.bytesurl(uri)
     # Read configuration
     groups = {}
-    for key, val in ui.configitems('auth'):
-        if key in ('cookiefile',):
+    for key, val in ui.configitems("auth"):
+        if key in ("cookiefile",):
             continue
 
-        if '.' not in key:
+        if "." not in key:
             ui.warn(_("ignoring invalid [auth] key '%s'\n") % key)
             continue
-        group, setting = key.rsplit('.', 1)
+        group, setting = key.rsplit(".", 1)
         gdict = groups.setdefault(group, {})
-        if setting in ('username', 'cert', 'key'):
+        if setting in ("username", "cert", "key"):
             val = util.expandpath(val)
         gdict[setting] = val
 
     # Find the best match
-    scheme, hostpath = uri.split('://', 1)
+    scheme, hostpath = uri.split("://", 1)
     bestuser = None
     bestlen = 0
     bestauth = None
     for group, auth in groups.iteritems():
-        if user and user != auth.get('username', user):
+        if user and user != auth.get("username", user):
             # If a username was set in the URI, the entry username
             # must either match it or be unset
             continue
-        prefix = auth.get('prefix')
+        prefix = auth.get("prefix")
         if not prefix:
             continue
-        p = prefix.split('://', 1)
+        p = prefix.split("://", 1)
         if len(p) > 1:
             schemes, prefix = [p[0]], p[1]
         else:
-            schemes = (auth.get('schemes') or 'https').split()
-        if (prefix == '*' or hostpath.startswith(prefix)) and \
-            (len(prefix) > bestlen or (len(prefix) == bestlen and \
-                not bestuser and 'username' in auth)) \
-             and scheme in schemes:
+            schemes = (auth.get("schemes") or "https").split()
+        if (
+            (prefix == "*" or hostpath.startswith(prefix))
+            and (
+                len(prefix) > bestlen
+                or (
+                    len(prefix) == bestlen
+                    and not bestuser
+                    and "username" in auth
+                )
+            )
+            and scheme in schemes
+        ):
             bestlen = len(prefix)
             bestauth = group, auth
-            bestuser = auth.get('username')
+            bestuser = auth.get("username")
             if user and not bestuser:
-                auth['username'] = user
+                auth["username"] = user
     return bestauth
diff --git a/mercurial/dirstateguard.py b/mercurial/dirstateguard.py
--- a/mercurial/dirstateguard.py
+++ b/mercurial/dirstateguard.py
@@ -9,14 +9,11 @@ 
 
 from .i18n import _
 
-from . import (
-    error,
-    narrowspec,
-    util,
-)
+from . import error, narrowspec, util
+
 
 class dirstateguard(util.transactional):
-    '''Restore dirstate at unexpected failure.
+    """Restore dirstate at unexpected failure.
 
     At the construction, this class does:
 
@@ -27,49 +24,57 @@ 
     is invoked before ``close()``.
 
     This just removes the backup file at ``close()`` before ``release()``.
-    '''
+    """
 
     def __init__(self, repo, name):
         self._repo = repo
         self._active = False
         self._closed = False
-        self._backupname = 'dirstate.backup.%s.%d' % (name, id(self))
-        self._narrowspecbackupname = ('narrowspec.backup.%s.%d' %
-                                      (name, id(self)))
+        self._backupname = "dirstate.backup.%s.%d" % (name, id(self))
+        self._narrowspecbackupname = "narrowspec.backup.%s.%d" % (
+            name,
+            id(self),
+        )
         repo.dirstate.savebackup(repo.currenttransaction(), self._backupname)
         narrowspec.savebackup(repo, self._narrowspecbackupname)
         self._active = True
 
     def __del__(self):
-        if self._active: # still active
+        if self._active:  # still active
             # this may occur, even if this class is used correctly:
             # for example, releasing other resources like transaction
             # may raise exception before ``dirstateguard.release`` in
             # ``release(tr, ....)``.
             self._abort()
 
     def close(self):
-        if not self._active: # already inactivated
-            msg = (_("can't close already inactivated backup: %s")
-                   % self._backupname)
+        if not self._active:  # already inactivated
+            msg = (
+                _("can't close already inactivated backup: %s")
+                % self._backupname
+            )
             raise error.Abort(msg)
 
-        self._repo.dirstate.clearbackup(self._repo.currenttransaction(),
-                                         self._backupname)
+        self._repo.dirstate.clearbackup(
+            self._repo.currenttransaction(), self._backupname
+        )
         narrowspec.clearbackup(self._repo, self._narrowspecbackupname)
         self._active = False
         self._closed = True
 
     def _abort(self):
         narrowspec.restorebackup(self._repo, self._narrowspecbackupname)
-        self._repo.dirstate.restorebackup(self._repo.currenttransaction(),
-                                           self._backupname)
+        self._repo.dirstate.restorebackup(
+            self._repo.currenttransaction(), self._backupname
+        )
         self._active = False
 
     def release(self):
         if not self._closed:
-            if not self._active: # already inactivated
-                msg = (_("can't release already inactivated backup: %s")
-                       % self._backupname)
+            if not self._active:  # already inactivated
+                msg = (
+                    _("can't release already inactivated backup: %s")
+                    % self._backupname
+                )
                 raise error.Abort(msg)
             self._abort()
diff --git a/mercurial/diffhelper.py b/mercurial/diffhelper.py
--- a/mercurial/diffhelper.py
+++ b/mercurial/diffhelper.py
@@ -9,10 +9,8 @@ 
 
 from .i18n import _
 
-from . import (
-    error,
-    pycompat,
-)
+from . import error, pycompat
+
 
 def addlines(fp, hunk, lena, lenb, a, b):
     """Read lines from fp into the hunk
@@ -30,38 +28,40 @@ 
         for i in pycompat.xrange(num):
             s = fp.readline()
             if not s:
-                raise error.ParseError(_('incomplete hunk'))
+                raise error.ParseError(_("incomplete hunk"))
             if s == "\\ No newline at end of file\n":
                 fixnewline(hunk, a, b)
                 continue
-            if s == '\n' or s == '\r\n':
+            if s == "\n" or s == "\r\n":
                 # Some patches may be missing the control char
                 # on empty lines. Supply a leading space.
-                s = ' ' + s
+                s = " " + s
             hunk.append(s)
-            if s.startswith('+'):
+            if s.startswith("+"):
                 b.append(s[1:])
-            elif s.startswith('-'):
+            elif s.startswith("-"):
                 a.append(s)
             else:
                 b.append(s[1:])
                 a.append(s)
 
+
 def fixnewline(hunk, a, b):
     """Fix up the last lines of a and b when the patch has no newline at EOF"""
     l = hunk[-1]
     # tolerate CRLF in last line
-    if l.endswith('\r\n'):
+    if l.endswith("\r\n"):
         hline = l[:-2]
     else:
         hline = l[:-1]
 
-    if hline.startswith((' ', '+')):
+    if hline.startswith((" ", "+")):
         b[-1] = hline[1:]
-    if hline.startswith((' ', '-')):
+    if hline.startswith((" ", "-")):
         a[-1] = hline
     hunk[-1] = hline
 
+
 def testhunk(a, b, bstart):
     """Compare the lines in a with the lines in b
 
diff --git a/mercurial/cacheutil.py b/mercurial/cacheutil.py
--- a/mercurial/cacheutil.py
+++ b/mercurial/cacheutil.py
@@ -8,14 +8,15 @@ 
 
 from . import repoview
 
+
 def cachetocopy(srcrepo):
     """return the list of cache file valuable to copy during a clone"""
     # In local clones we're copying all nodes, not just served
     # ones. Therefore copy all branch caches over.
-    cachefiles = ['branch2']
-    cachefiles += ['branch2-%s' % f for f in repoview.filtertable]
-    cachefiles += ['rbc-names-v1', 'rbc-revs-v1']
-    cachefiles += ['tags2']
-    cachefiles += ['tags2-%s' % f for f in repoview.filtertable]
-    cachefiles += ['hgtagsfnodes1']
+    cachefiles = ["branch2"]
+    cachefiles += ["branch2-%s" % f for f in repoview.filtertable]
+    cachefiles += ["rbc-names-v1", "rbc-revs-v1"]
+    cachefiles += ["tags2"]
+    cachefiles += ["tags2-%s" % f for f in repoview.filtertable]
+    cachefiles += ["hgtagsfnodes1"]
     return cachefiles