D7515: pytype: [WIP] suppress various warnings inline to get a clean run

mharbison72 (Matt Harbison) phabricator at mercurial-scm.org
Sun Nov 24 00:52:04 UTC 2019


mharbison72 created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  This depends on D7295 <https://phab.mercurial-scm.org/D7295> and D7384 <https://phab.mercurial-scm.org/D7384>, which in turn was applied to f612a044a5ab <https://phab.mercurial-scm.org/rHGf612a044a5ab30babc85657a630d984f5c9d138b>.  It
  contains some things that are currently in flight, and I made no attempt to keep
  it under 80 columns or blacken it.  But it seems useful to share now, because it
  is so time consuming to get this far, and presumably much of this will entail
  actual fixes.
  
  I wish I had made a better effort to indicate what it was complaining about, so
  maybe any actual suppressions that are needed should be documented why?

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/bundlerepo.py
  mercurial/commands.py
  mercurial/dagparser.py
  mercurial/debugcommands.py
  mercurial/error.py
  mercurial/exchange.py
  mercurial/filemerge.py
  mercurial/hg.py
  mercurial/hgweb/server.py
  mercurial/hgweb/webcommands.py
  mercurial/hgweb/webutil.py
  mercurial/logcmdutil.py
  mercurial/manifest.py
  mercurial/obsutil.py
  mercurial/patch.py
  mercurial/profiling.py
  mercurial/pycompat.py
  mercurial/scmwindows.py
  mercurial/shelve.py
  mercurial/subrepo.py
  mercurial/ui.py
  mercurial/unionrepo.py
  mercurial/upgrade.py
  mercurial/verify.py
  mercurial/windows.py
  mercurial/wireprotoframing.py
  mercurial/wireprotoserver.py
  mercurial/wireprotov1peer.py
  mercurial/wireprotov1server.py
  mercurial/wireprotov2server.py
  tests/test-check-pytype.t

CHANGE DETAILS

diff --git a/tests/test-check-pytype.t b/tests/test-check-pytype.t
--- a/tests/test-check-pytype.t
+++ b/tests/test-check-pytype.t
@@ -9,25 +9,16 @@
 endeavor to empty this list out over time, as some of these are
 probably hiding real problems.
 
-
-  $ pytype mercurial \
-  >    -x mercurial/bundlerepo.py \
+  $ pytype -k mercurial \
   >    -x mercurial/chgserver.py \
   >    -x mercurial/context.py \
   >    -x mercurial/crecord.py \
   >    -x mercurial/encoding.py \
-  >    -x mercurial/error.py \
-  >    -x mercurial/exchange.py \
   >    -x mercurial/lsprof.py \
-  >    -x mercurial/policy.py
-  >    -x mercurial/pycompat.py \
   >    -x mercurial/urllibcompat.py \
   >    -x mercurial/i18n.py \
   >    -x mercurial/sslutil.py \
-  >    -x mercurial/scmwindows.py \
   >    -x mercurial/keepalive.py \
-  >    -x mercurial/windows.py \
-  >    -x mercurial/wireprotoframing.py \
   >    -x mercurial/utils/stringutil.py \
   >    -x mercurial/hgweb/server.py \
   >    -x mercurial/hgweb/wsgicgi.py \
@@ -35,4 +26,10 @@
   >    -x mercurial/interfaces \
   >    -x mercurial/cffi \
   >    -x mercurial/pure \
-  >    -x mercurial/thirdparty
+  >    -x mercurial/thirdparty \
+  >    -x mercurial/httppeer.py \
+  >    -x mercurial/repoview.py \
+  >    -x mercurial/localrepo.py \
+  >    -x mercurial/revlog.py \
+  >    -x mercurial/merge.py \
+  >    -x mercurial/testing/storage.py
diff --git a/mercurial/wireprotov2server.py b/mercurial/wireprotov2server.py
--- a/mercurial/wireprotov2server.py
+++ b/mercurial/wireprotov2server.py
@@ -88,7 +88,7 @@
     try:
         checkperm(rctx, req, b'pull' if permission == b'ro' else b'push')
     except hgwebcommon.ErrorResponse as e:
-        res.status = hgwebcommon.statusmessage(e.code, pycompat.bytestr(e))
+        res.status = hgwebcommon.statusmessage(e.code, pycompat.bytestr(e))  # pytype: disable=wrong-arg-types
         for k, v in e.headers:
             res.headers[k] = v
         res.setbodybytes(b'permission denied')
@@ -582,7 +582,7 @@
 
         caps[b'commands'][command] = {
             b'args': args,
-            b'permissions': [entry.permission],
+            b'permissions': [entry.permission],  # pytype: disable=unsupported-operands
         }
 
         if entry.extracapabilitiesfn:
@@ -609,7 +609,7 @@
                 if key in target:
                     entry[key] = target[key]
 
-            caps[b'redirect'][b'targets'].append(entry)
+            caps[b'redirect'][b'targets'].append(entry)  # pytype: disable=attribute-error
 
     return proto.addcapabilities(repo, caps)
 
diff --git a/mercurial/wireprotov1server.py b/mercurial/wireprotov1server.py
--- a/mercurial/wireprotov1server.py
+++ b/mercurial/wireprotov1server.py
@@ -726,12 +726,13 @@
                         part.addparam(b'old', exc.old, mandatory=False)
                     if exc.ret is not None:
                         part.addparam(b'ret', exc.ret, mandatory=False)
-            except error.BundleValueError as exc:
+            except error.BundleValueError as exc:  # Should be BundleUnknownFeatureError
                 errpart = bundler.newpart(b'error:unsupportedcontent')
-                if exc.parttype is not None:
-                    errpart.addparam(b'parttype', exc.parttype)
-                if exc.params:
-                    errpart.addparam(b'params', b'\0'.join(exc.params))
+                # TODO: These are bugs!
+                if exc.parttype is not None:  # pytype: disable=attribute-error
+                    errpart.addparam(b'parttype', exc.parttype)  # pytype: disable=attribute-error
+                if exc.params:  # pytype: disable=attribute-error
+                    errpart.addparam(b'params', b'\0'.join(exc.params))  # pytype: disable=attribute-error
             except error.Abort as exc:
                 manargs = [(b'message', stringutil.forcebytestr(exc))]
                 advargs = []
diff --git a/mercurial/wireprotov1peer.py b/mercurial/wireprotov1peer.py
--- a/mercurial/wireprotov1peer.py
+++ b/mercurial/wireprotov1peer.py
@@ -60,12 +60,12 @@
 
     def plain(*args, **opts):
         batchable = f(*args, **opts)
-        encargsorres, encresref = next(batchable)
+        encargsorres, encresref = next(batchable)  # pytype: disable=attribute-error
         if not encresref:
             return encargsorres  # a local result in this case
         self = args[0]
         cmd = pycompat.bytesurl(f.__name__)  # ensure cmd is ascii bytestr
-        encresref.set(self._submitone(cmd, encargsorres))
+        encresref.set(self._submitone(cmd, encargsorres))  # pytype: disable=attribute-error
         return next(batchable)
 
     setattr(plain, 'batchable', f)
@@ -360,7 +360,7 @@
         self.requirecap(b'lookup', _(b'look up remote revision'))
         f = future()
         yield {b'key': encoding.fromlocal(key)}, f
-        d = f.value
+        d = f.value  # pytype: disable=attribute-error
         success, data = d[:-1].split(b" ", 1)
         if int(success):
             yield bin(data)
@@ -371,7 +371,7 @@
     def heads(self):
         f = future()
         yield {}, f
-        d = f.value
+        d = f.value  # pytype: disable=attribute-error
         try:
             yield wireprototypes.decodelist(d[:-1])
         except ValueError:
@@ -381,7 +381,7 @@
     def known(self, nodes):
         f = future()
         yield {b'nodes': wireprototypes.encodelist(nodes)}, f
-        d = f.value
+        d = f.value  # pytype: disable=attribute-error
         try:
             yield [bool(int(b)) for b in pycompat.iterbytestr(d)]
         except ValueError:
@@ -391,7 +391,7 @@
     def branchmap(self):
         f = future()
         yield {}, f
-        d = f.value
+        d = f.value  # pytype: disable=attribute-error
         try:
             branchmap = {}
             for branchpart in d.splitlines():
@@ -410,7 +410,7 @@
         f = future()
         self.ui.debug(b'preparing listkeys for "%s"\n' % namespace)
         yield {b'namespace': encoding.fromlocal(namespace)}, f
-        d = f.value
+        d = f.value  # pytype: disable=attribute-error
         self.ui.debug(
             b'received listkey for "%s": %i bytes\n' % (namespace, len(d))
         )
@@ -428,7 +428,7 @@
             b'old': encoding.fromlocal(old),
             b'new': encoding.fromlocal(new),
         }, f
-        d = f.value
+        d = f.value  # pytype: disable=attribute-error
         d, output = d.split(b'\n', 1)
         try:
             d = bool(int(d))
diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -234,10 +234,10 @@
     except hgwebcommon.ErrorResponse as e:
         for k, v in e.headers:
             res.headers[k] = v
-        res.status = hgwebcommon.statusmessage(e.code, pycompat.bytestr(e))
+        res.status = hgwebcommon.statusmessage(e.code, pycompat.bytestr(e))  # pytype: disable=wrong-arg-types
         # TODO This response body assumes the failed command was
         # "unbundle." That assumption is not always valid.
-        res.setbodybytes(b'0\n%s\n' % pycompat.bytestr(e))
+        res.setbodybytes(b'0\n%s\n' % pycompat.bytestr(e))  # pytype: disable=wrong-arg-types
 
     return True
 
@@ -248,7 +248,7 @@
     # Registered APIs are made available via config options of the name of
     # the protocol.
     for k, v in API_HANDLERS.items():
-        section, option = v[b'config']
+        section, option = v[b'config']  # pytype: disable=attribute-error
         if repo.ui.configbool(section, option):
             apis.add(k)
 
diff --git a/mercurial/wireprotoframing.py b/mercurial/wireprotoframing.py
--- a/mercurial/wireprotoframing.py
+++ b/mercurial/wireprotoframing.py
@@ -468,7 +468,8 @@
     ):
         value = getattr(location, a)
         if value is not None:
-            data[b'location'][pycompat.bytestr(a)] = value
+            data[b'location'][pycompat.bytestr(a
+            )] = value  # pytype: disable=unsupported-operands,wrong-arg-types
 
     payload = b''.join(cborutil.streamencode(data))
 
@@ -493,7 +494,7 @@
     m = {b'status': b'error', b'error': {b'message': message,}}
 
     if args:
-        m[b'error'][b'args'] = args
+        m[b'error'][b'args'] = args  # pytype: disable=unsupported-operands
 
     overall = b''.join(cborutil.streamencode(m))
 
@@ -759,7 +760,7 @@
 
 class zstdbaseencoder(object):
     def __init__(self, level):
-        from . import zstd
+        from . import zstd  # pytype: disable=import-error
 
         self._zstd = zstd
         cctx = zstd.ZstdCompressor(level=level)
@@ -787,7 +788,7 @@
 
 class zstdbasedecoder(object):
     def __init__(self, maxwindowsize):
-        from . import zstd
+        from . import zstd  # pytype: disable=import-error
 
         dctx = zstd.ZstdDecompressor(max_window_size=maxwindowsize)
         self._decompressor = dctx.decompressobj()
@@ -817,7 +818,7 @@
         return
 
     try:
-        from . import zstd
+        from . import zstd  # pytype: disable=import-error
 
         zstd.__version__
     except ImportError:
@@ -1370,8 +1371,8 @@
             self._state = b'idle'
 
         # Decode the payloads as CBOR.
-        entry[b'payload'].seek(0)
-        request = cborutil.decodeall(entry[b'payload'].getvalue())[0]
+        entry[b'payload'].seek(0)  # pytype: disable=attribute-error
+        request = cborutil.decodeall(entry[b'payload'].getvalue())[0]  # pytype: disable=attribute-error
 
         if b'name' not in request:
             self._state = b'errored'
@@ -1392,7 +1393,7 @@
                 b'command': request[b'name'],
                 b'args': request[b'args'],
                 b'redirect': request.get(b'redirect'),
-                b'data': entry[b'data'].getvalue() if entry[b'data'] else None,
+                b'data': entry[b'data'].getvalue() if entry[b'data'] else None,  # pytype: disable=attribute-error
             },
         )
 
diff --git a/mercurial/windows.py b/mercurial/windows.py
--- a/mercurial/windows.py
+++ b/mercurial/windows.py
@@ -26,11 +26,12 @@
 )
 
 try:
-    import _winreg as winreg
+    import _winreg as winreg  # pytype: disable=import-error
 
     winreg.CloseKey
 except ImportError:
-    import winreg
+    # py2 only
+    import winreg  # pytype: disable=import-error
 
 osutil = policy.importmod('osutil')
 
@@ -282,7 +283,7 @@
     # fileno(), usually set to -1.
     fno = getattr(fd, 'fileno', None)
     if fno is not None and fno() >= 0:
-        msvcrt.setmode(fno(), os.O_BINARY)
+        msvcrt.setmode(fno(), os.O_BINARY)  # pytype: disable=module-attr
 
 
 def pconvert(path):
diff --git a/mercurial/verify.py b/mercurial/verify.py
--- a/mercurial/verify.py
+++ b/mercurial/verify.py
@@ -81,7 +81,7 @@
 
     def _exc(self, linkrev, msg, inst, filename=None):
         """record exception raised during the verify process"""
-        fmsg = pycompat.bytestr(inst)
+        fmsg = pycompat.bytestr(inst)  # pytype: disable=wrong-arg-types
         if not fmsg:
             fmsg = pycompat.byterepr(inst)
         self._err(linkrev, b"%s: %s" % (msg, fmsg), filename)
@@ -431,7 +431,7 @@
                 filenodes.setdefault(f, {}).update(onefilenodes)
 
         if not dir and subdirnodes:
-            subdirprogress.complete()
+            subdirprogress.complete()  # pytype: disable=attribute-error
             if self.warnorphanstorefiles:
                 for f in sorted(storefiles):
                     self._warn(_(b"warning: orphan data file '%s'") % f)
diff --git a/mercurial/upgrade.py b/mercurial/upgrade.py
--- a/mercurial/upgrade.py
+++ b/mercurial/upgrade.py
@@ -818,7 +818,10 @@
     progress = None
 
     def oncopiedrevision(rl, rev, node):
-        progress.increment()
+        # XXX: It looks like there is no `else` where this is set, and it ends
+        #      up calling progress.complete() at the end of the loop (not
+        #      detected).
+        progress.increment()  # pytype: disable=attribute-error
 
     sidedatacompanion = getsidedatacompanion(srcrepo, dstrepo)
 
diff --git a/mercurial/unionrepo.py b/mercurial/unionrepo.py
--- a/mercurial/unionrepo.py
+++ b/mercurial/unionrepo.py
@@ -194,7 +194,7 @@
         self.repo2 = repo2
         self._url = url
 
-        self.ui.setconfig(b'phases', b'publish', False, b'unionrepo')
+        self.ui.setconfig(b'phases', b'publish', False, b'unionrepo')  # pytype: disable=attribute-error
 
     @localrepo.unfilteredpropertycache
     def changelog(self):
@@ -219,7 +219,11 @@
 
     def file(self, f):
         return unionfilelog(
-            self.svfs, f, self.repo2.svfs, self.unfiltered()._clrev, self
+            self.svfs,  # pytype: disable=attribute-error
+            f,
+            self.repo2.svfs,
+            self.unfiltered()._clrev,  # pytype: disable=attribute-error
+            self
         )
 
     def close(self):
diff --git a/mercurial/ui.py b/mercurial/ui.py
--- a/mercurial/ui.py
+++ b/mercurial/ui.py
@@ -1626,8 +1626,8 @@
         # choices containing spaces, ASCII, or basically anything
         # except an ampersand followed by a character.
         m = re.match(br'(?s)(.+?)\$\$([^\$]*&[^ \$].*)', prompt)
-        msg = m.group(1)
-        choices = [p.strip(b' ') for p in m.group(2).split(b'$$')]
+        msg = m.group(1)  # pytype: disable=attribute-error
+        choices = [p.strip(b' ') for p in m.group(2).split(b'$$')]  # pytype: disable=attribute-error
 
         def choicetuple(s):
             ampidx = s.index(b'&')
@@ -1858,9 +1858,9 @@
                 # exclude frame where 'exc' was chained and rethrown from exctb
                 self.write_err(
                     b'Traceback (most recent call last):\n',
-                    b''.join(exctb[:-1]),
-                    b''.join(causetb),
-                    b''.join(exconly),
+                    b''.join(exctb[:-1]),  # pytype: disable=wrong-arg-types
+                    b''.join(causetb),  # pytype: disable=wrong-arg-types
+                    b''.join(exconly),  # pytype: disable=wrong-arg-types
                 )
             else:
                 output = traceback.format_exception(exc[0], exc[1], exc[2])
diff --git a/mercurial/subrepo.py b/mercurial/subrepo.py
--- a/mercurial/subrepo.py
+++ b/mercurial/subrepo.py
@@ -1864,7 +1864,7 @@
             if info.issym():
                 data = info.linkname
             else:
-                data = tar.extractfile(info).read()
+                data = tar.extractfile(info).read()  # pytype: disable=attribute-error
             archiver.addfile(prefix + bname, info.mode, info.issym(), data)
             total += 1
             progress.increment()
diff --git a/mercurial/shelve.py b/mercurial/shelve.py
--- a/mercurial/shelve.py
+++ b/mercurial/shelve.py
@@ -202,7 +202,7 @@
                 nodemod.bin(h) for h in d[b'nodestoremove'].split(b' ')
             ]
         except (ValueError, TypeError, KeyError) as err:
-            raise error.CorruptedState(pycompat.bytestr(err))
+            raise error.CorruptedState(pycompat.bytestr(err))  # pytype: disable=wrong-arg-types
 
     @classmethod
     def _getversion(cls, repo):
@@ -211,7 +211,7 @@
         try:
             version = int(fp.readline().strip())
         except ValueError as err:
-            raise error.CorruptedState(pycompat.bytestr(err))
+            raise error.CorruptedState(pycompat.bytestr(err))  # pytype: disable=wrong-arg-types
         finally:
             fp.close()
         return version
diff --git a/mercurial/scmwindows.py b/mercurial/scmwindows.py
--- a/mercurial/scmwindows.py
+++ b/mercurial/scmwindows.py
@@ -10,11 +10,12 @@
 )
 
 try:
-    import _winreg as winreg
+    import _winreg as winreg  # pytype: disable=import-error
 
     winreg.CloseKey
 except ImportError:
-    import winreg
+    # py2 only
+    import winreg  # pytype: disable=import-error
 
 # MS-DOS 'more' is the only pager available by default on Windows.
 fallbackpager = b'more'
diff --git a/mercurial/pycompat.py b/mercurial/pycompat.py
--- a/mercurial/pycompat.py
+++ b/mercurial/pycompat.py
@@ -99,7 +99,7 @@
         # Otherwise non-ASCII filenames in existing repositories would be
         # corrupted.
         # This must be set once prior to any fsencode/fsdecode calls.
-        sys._enablelegacywindowsfsencoding()
+        sys._enablelegacywindowsfsencoding()  # pytype: disable=module-attr
 
     fsencode = os.fsencode
     fsdecode = os.fsdecode
@@ -287,7 +287,7 @@
     def _wrapattrfunc(f):
         @functools.wraps(f)
         def w(object, name, *args):
-            return f(object, sysstr(name), *args)
+            return f(object, sysstr(name), *args)  # pytype: disable=wrong-arg-count
 
         return w
 
diff --git a/mercurial/profiling.py b/mercurial/profiling.py
--- a/mercurial/profiling.py
+++ b/mercurial/profiling.py
@@ -269,7 +269,7 @@
                 exception_type, exception_value, traceback
             )
             if self._output == b'blackbox':
-                val = b'Profile:\n%s' % self._fp.getvalue()
+                val = b'Profile:\n%s' % self._fp.getvalue()  # pytype: disable=attribute-error
                 # ui.log treats the input as a format string,
                 # so we need to escape any % signs.
                 val = val.replace(b'%', b'%%')
diff --git a/mercurial/patch.py b/mercurial/patch.py
--- a/mercurial/patch.py
+++ b/mercurial/patch.py
@@ -261,8 +261,8 @@
         ui.debug(b'Node ID: %s\n' % nodeid)
 
     if subject:
-        if subject.startswith(b'[PATCH'):
-            pend = subject.find(b']')
+        if subject.startswith(b'[PATCH'):  # pytype: disable=attribute-error
+            pend = subject.find(b']')  # pytype: disable=attribute-error
             if pend >= 0:
                 subject = subject[pend + 1 :].lstrip()
         subject = re.sub(br'\n[ \t]+', b' ', subject)
@@ -273,7 +273,7 @@
     ok_types = (b'text/plain', b'text/x-diff', b'text/x-patch')
     message = b''
     for part in msg.walk():
-        content_type = pycompat.bytestr(part.get_content_type())
+        content_type = pycompat.bytestr(part.get_content_type())  # pytype: disable=wrong-arg-types
         ui.debug(b'Content-Type: %s\n' % content_type)
         if content_type not in ok_types:
             continue
@@ -287,7 +287,7 @@
             ui.debug(b'found patch at byte %d\n' % m.start(0))
             diffs_seen += 1
             cfp = stringio()
-            for line in payload[: m.start(0)].splitlines():
+            for line in payload[: m.start(0)].splitlines():  # pytype: disable=attribute-error
                 if line.startswith(b'# HG changeset patch') and not hgpatch:
                     ui.debug(b'patch generated by hg export\n')
                     hgpatch = True
@@ -318,7 +318,7 @@
             message = cfp.getvalue()
             if tmpfp:
                 tmpfp.write(payload)
-                if not payload.endswith(b'\n'):
+                if not payload.endswith(b'\n'):  # pytype: disable=attribute-error
                     tmpfp.write(b'\n')
         elif not diffs_seen and message and content_type == b'text/plain':
             message += b'\n' + payload
@@ -963,7 +963,8 @@
         return self.files()[-1]
 
     def __repr__(self):
-        return b'<header %s>' % (b' '.join(map(repr, self.files())))
+        # XXX: This is a bug
+        return b'<header %s>' % (b' '.join(map(repr, self.files())))  # pytype: disable=wrong-arg-types
 
     def isnewfile(self):
         return any(self.newfile_re.match(h) for h in self.header)
diff --git a/mercurial/obsutil.py b/mercurial/obsutil.py
--- a/mercurial/obsutil.py
+++ b/mercurial/obsutil.py
@@ -800,7 +800,9 @@
 
     values = []
     for sset in fullsuccessorsets:
-        values.append({b'successors': sset, b'markers': sset.markers})
+        # This might be OK, because successorsets == [] falls into the else
+        # case above.
+        values.append({b'successors': sset, b'markers': sset.markers})  # pytype: disable=attribute-error
 
     return values
 
diff --git a/mercurial/manifest.py b/mercurial/manifest.py
--- a/mercurial/manifest.py
+++ b/mercurial/manifest.py
@@ -125,7 +125,7 @@
 def unhexlify(data, extra, pos, length):
     s = bin(data[pos : pos + length])
     if extra:
-        s += chr(extra & 0xFF)
+        s += chr(extra & 0xFF)  # pytype: disable=unsupported-operands
     return s
 
 
@@ -1624,8 +1624,10 @@
             _checkforbidden(added)
             # combine the changed lists into one sorted iterator
             work = heapq.merge(
-                [(x, False) for x in sorted(added)],
-                [(x, True) for x in sorted(removed)],
+                # XXX: writesubtree() below passes None.  Not clear if this
+                # branch can't happen because of `if` test above.
+                [(x, False) for x in sorted(added)],  # pytype: disable=wrong-arg-types
+                [(x, True) for x in sorted(removed)],  # pytype: disable=wrong-arg-types
             )
 
             arraytext, deltatext = m.fastdelta(self.fulltextcache[p1], work)
diff --git a/mercurial/logcmdutil.py b/mercurial/logcmdutil.py
--- a/mercurial/logcmdutil.py
+++ b/mercurial/logcmdutil.py
@@ -45,10 +45,12 @@
 if not globals():
     from typing import (
         Any,
+        Optional,
         Tuple,
+        Union,
     )
 
-    for t in (Any, Tuple):
+    for t in (Any, Optional, Tuple, Union):
         assert t
 
 
@@ -853,7 +855,7 @@
 
 
 def getrevs(repo, pats, opts):
-    # type: (Any, Any, Any) -> Tuple[smartset.BaseSet, changesetdiffer]
+    # type: (Any, Any, Any) -> Tuple[smartset.baseset, Optional[changesetdiffer]]
     """Return (revs, differ) where revs is a smartset
 
     differ is a changesetdiffer with pre-configured file matcher.
@@ -898,7 +900,7 @@
 
     differ = changesetdiffer()
     differ._makefilematcher = filematcher
-    return revs, differ
+    return revs, differ  # pytype: disable=bad-return-type
 
 
 def _parselinerangeopt(repo, opts):
@@ -1016,7 +1018,7 @@
     # only set graph styling if HGPLAIN is not set.
     if ui.plain(b'graph'):
         # set all edge styles to |, the default pre-3.8 behaviour
-        styles.update(dict.fromkeys(styles, b'|'))
+        styles.update(dict.fromkeys(styles, b'|'))  # pytype: disable=attribute-error
     else:
         edgetypes = {
             b'parent': graphmod.PARENT,
@@ -1026,10 +1028,10 @@
         for name, key in edgetypes.items():
             # experimental config: experimental.graphstyle.*
             styles[key] = ui.config(
-                b'experimental', b'graphstyle.%s' % name, styles[key]
+                b'experimental', b'graphstyle.%s' % name, styles[key]  # pytype: disable=unsupported-operands
             )
             if not styles[key]:
-                styles[key] = None
+                styles[key] = None  # pytype: disable=unsupported-operands
 
         # experimental config: experimental.graphshorten
         state[b'graphshorten'] = ui.configbool(b'experimental', b'graphshorten')
diff --git a/mercurial/hgweb/webutil.py b/mercurial/hgweb/webutil.py
--- a/mercurial/hgweb/webutil.py
+++ b/mercurial/hgweb/webutil.py
@@ -873,7 +873,7 @@
         raise error.ParseError(_(b'not displayable without template'))
 
     def show(self, context, mapping):
-        return self.join(context, b'')
+        return self.join(context, mapping, b'')
 
     def tobool(self, context, mapping):
         return bool(self._vars)
diff --git a/mercurial/hgweb/webcommands.py b/mercurial/hgweb/webcommands.py
--- a/mercurial/hgweb/webcommands.py
+++ b/mercurial/hgweb/webcommands.py
@@ -1162,9 +1162,11 @@
         # would required a dedicated "revnav" class
         nav = templateutil.mappinglist([])
         if descend:
-            it = dagop.blockdescendants(fctx, *lrange)
+            # XXX: This seems correct, because lrange is a tuple of 2.
+            # Why not complain about formatlinerange() below?
+            it = dagop.blockdescendants(fctx, *lrange)  # pytype: disable=missing-parameter
         else:
-            it = dagop.blockancestors(fctx, *lrange)
+            it = dagop.blockancestors(fctx, *lrange)  # pytype: disable=missing-parameter
         for i, (c, lr) in enumerate(it, 1):
             diffs = None
             if patch:
diff --git a/mercurial/hgweb/server.py b/mercurial/hgweb/server.py
--- a/mercurial/hgweb/server.py
+++ b/mercurial/hgweb/server.py
@@ -426,9 +426,11 @@
         except AttributeError:
             reload(sys)
         oldenc = sys.getdefaultencoding()
-        sys.setdefaultencoding(b"latin1")  # or any full 8-bit encoding
+        # or any full 8-bit encoding
+        sys.setdefaultencoding(b"latin1")  # pytype: disable=module-attr
+        import mimetypes
         mimetypes.init()
-        sys.setdefaultencoding(oldenc)
+        sys.setdefaultencoding(oldenc)  # pytype: disable=module-attr
 
     address = ui.config(b'web', b'address')
     port = util.getport(ui.config(b'web', b'port'))
diff --git a/mercurial/hg.py b/mercurial/hg.py
--- a/mercurial/hg.py
+++ b/mercurial/hg.py
@@ -65,7 +65,8 @@
     # Python 2 raises TypeError, Python 3 ValueError.
     except (TypeError, ValueError) as e:
         raise error.Abort(
-            _(b'invalid path %s: %s') % (path, pycompat.bytestr(e))
+            _(b'invalid path %s: %s') % (path, pycompat.bytestr(e  # pytype: disable=wrong-arg-types
+            ))
         )
 
     return isfile and bundlerepo or localrepo
diff --git a/mercurial/filemerge.py b/mercurial/filemerge.py
--- a/mercurial/filemerge.py
+++ b/mercurial/filemerge.py
@@ -119,7 +119,7 @@
         """
         return not (
             fctx.isabsent()
-            and fctx.ctx() == self.ctx()
+            and fctx.ctx() == self._ctx
             and fctx.path() == self.path()
         )
 
@@ -693,7 +693,7 @@
     ui.status(t.renderdefault(props))
 
 
-def _xmerge(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None):
+def _xmerge(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels):
     tool, toolpath, binary, symlink, scriptfn = toolconf
     uipathfn = scmutil.getuipathfn(repo)
     if fcd.isabsent() or fco.isabsent():
diff --git a/mercurial/exchange.py b/mercurial/exchange.py
--- a/mercurial/exchange.py
+++ b/mercurial/exchange.py
@@ -1941,7 +1941,7 @@
             # make sure to always includes bookmark data when migrating
             # `hg incoming --bundle` to using this function.
             pullop.stepsdone.add(b'request-bookmarks')
-            kwargs.setdefault(b'listkeys', []).append(b'bookmarks')
+            kwargs.setdefault(b'listkeys', []).append(b'bookmarks')  # pytype: disable=attribute-error
 
     # If this is a full pull / clone and the server supports the clone bundles
     # feature, tell the server whether we attempted a clone bundle. The
@@ -2181,7 +2181,7 @@
     )
     if not user_includes:
         raise error.Abort(
-            _(b"{} configuration for user {} is empty").format(
+            _(b"%s configuration for user %s is empty") % (
                 _NARROWACL_SECTION, username
             )
         )
@@ -2202,7 +2202,7 @@
 
     if invalid_includes:
         raise error.Abort(
-            _(b"The following includes are not accessible for {}: {}").format(
+            _(b"The following includes are not accessible for %s: %s") % (
                 username, invalid_includes
             )
         )
@@ -2476,7 +2476,7 @@
     **kwargs
 ):
     """add a changegroup part to the requested bundle"""
-    if not kwargs.get('cg', True):
+    if not kwargs.get('cg', True) or not b2caps:
         return
 
     version = b'01'
@@ -2538,7 +2538,7 @@
     """add a bookmark part to the requested bundle"""
     if not kwargs.get('bookmarks', False):
         return
-    if b'bookmarks' not in b2caps:
+    if not b2caps or b'bookmarks' not in b2caps:
         raise error.Abort(_(b'no common bookmarks exchange method'))
     books = bookmod.listbinbookmarks(repo)
     data = bookmod.binaryencode(books)
@@ -2579,7 +2579,7 @@
 ):
     """add phase heads part to the requested bundle"""
     if kwargs.get('phases', False):
-        if not b'heads' in b2caps.get(b'phases'):
+        if not b2caps or not b'heads' in b2caps.get(b'phases'):
             raise error.Abort(_(b'no common phases exchange method'))
         if heads is None:
             heads = repo.heads()
@@ -2643,7 +2643,7 @@
     # Don't send unless:
     # - changeset are being exchanged,
     # - the client supports it.
-    if not (kwargs.get('cg', True) and b'hgtagsfnodes' in b2caps):
+    if not b2caps or not (kwargs.get('cg', True) and b'hgtagsfnodes' in b2caps):
         return
 
     outgoing = _computeoutgoing(repo, heads, common)
@@ -2677,6 +2677,7 @@
     # - narrow bundle isn't in play (not currently compatible).
     if (
         not kwargs.get('cg', True)
+        or not b2caps
         or b'rev-branch-cache' not in b2caps
         or kwargs.get('narrow', False)
         or repo.ui.has_section(_NARROWACL_SECTION)
@@ -2746,9 +2747,9 @@
                             lockandtr[0] = repo.wlock()
                         lockandtr[1] = repo.lock()
                         lockandtr[2] = repo.transaction(source)
-                        lockandtr[2].hookargs[b'source'] = source
-                        lockandtr[2].hookargs[b'url'] = url
-                        lockandtr[2].hookargs[b'bundle2'] = b'1'
+                        lockandtr[2].hookargs[b'source'] = source  # pytype: disable=attribute-error
+                        lockandtr[2].hookargs[b'url'] = url  # pytype: disable=attribute-error
+                        lockandtr[2].hookargs[b'bundle2'] = b'1'  # pytype: disable=attribute-error
                     return lockandtr[2]
 
                 # Do greedy locking by default until we're satisfied with lazy
diff --git a/mercurial/error.py b/mercurial/error.py
--- a/mercurial/error.py
+++ b/mercurial/error.py
@@ -35,7 +35,7 @@
 
     def __init__(self, *args, **kw):
         self.hint = kw.pop('hint', None)
-        super(Hint, self).__init__(*args, **kw)
+        super(Hint, self).__init__(*args, **kw)  # pytype: disable=wrong-arg-count
 
 
 class StorageError(Hint, Exception):
diff --git a/mercurial/debugcommands.py b/mercurial/debugcommands.py
--- a/mercurial/debugcommands.py
+++ b/mercurial/debugcommands.py
@@ -386,7 +386,8 @@
         return b'{%s}' % (
             b', '.join(b'%s: %s' % (k, thing[k]) for k in sorted(thing))
         )
-    return pycompat.bytestr(repr(thing))
+    return pycompat.bytestr(repr(thing)  # pytype: disable=wrong-arg-types
+    )
 
 
 def _debugbundle2(ui, gen, all=None, **opts):
@@ -2180,7 +2181,8 @@
                 tr.close()
             except ValueError as exc:
                 raise error.Abort(
-                    _(b'bad obsmarker input: %s') % pycompat.bytestr(exc)
+                    _(b'bad obsmarker input: %s') % pycompat.bytestr(exc  # pytype: disable=wrong-arg-types
+                    )
                 )
             finally:
                 tr.release()
@@ -2861,7 +2863,8 @@
     def fmtchunktype(chunktype):
         if chunktype == b'empty':
             return b'    %s     : ' % chunktype
-        elif chunktype in pycompat.bytestr(string.ascii_letters):
+        elif chunktype in pycompat.bytestr(string.ascii_letters   # pytype: disable=wrong-arg-types
+        ):
             return b'    0x%s (%s)  : ' % (hex(chunktype), chunktype)
         else:
             return b'    0x%s      : ' % hex(chunktype)
diff --git a/mercurial/dagparser.py b/mercurial/dagparser.py
--- a/mercurial/dagparser.py
+++ b/mercurial/dagparser.py
@@ -169,8 +169,8 @@
         return
 
     wordchars = pycompat.bytestr(
-        string.ascii_letters + string.digits
-    )  # pytype: disable=wrong-arg-types
+        string.ascii_letters + string.digits  # pytype: disable=wrong-arg-types
+    )
 
     labels = {}
     p1 = -1
@@ -180,8 +180,8 @@
         if not ref:
             return p1
         elif ref[0] in pycompat.bytestr(
-            string.digits
-        ):  # pytype: disable=wrong-arg-types
+            string.digits  # pytype: disable=wrong-arg-types
+        ):
             return r - int(ref)
         else:
             return labels[ref]
@@ -216,8 +216,8 @@
     c = nextch()
     while c != b'\0':
         while c in pycompat.bytestr(
-            string.whitespace
-        ):  # pytype: disable=wrong-arg-types
+            string.whitespace  # pytype: disable=wrong-arg-types
+        ):
             c = nextch()
         if c == b'.':
             yield b'n', (r, [p1])
@@ -226,8 +226,8 @@
             c = nextch()
         elif c == b'+':
             c, digs = nextrun(
-                nextch(), pycompat.bytestr(string.digits)
-            )  # pytype: disable=wrong-arg-types
+                nextch(), pycompat.bytestr(string.digits)  # pytype: disable=wrong-arg-types
+            )
             n = int(digs)
             for i in pycompat.xrange(0, n):
                 yield b'n', (r, [p1])
diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -3400,7 +3400,8 @@
         regexp = util.re.compile(pattern, reflags)
     except re.error as inst:
         ui.warn(
-            _(b"grep: invalid match pattern: %s\n") % pycompat.bytestr(inst)
+            _(b"grep: invalid match pattern: %s\n") % pycompat.bytestr(inst  # pytype: disable=wrong-arg-types
+            )
         )
         return 1
     sep, eol = b':', b'\n'
diff --git a/mercurial/bundlerepo.py b/mercurial/bundlerepo.py
--- a/mercurial/bundlerepo.py
+++ b/mercurial/bundlerepo.py
@@ -253,11 +253,13 @@
         self._tempparent = tempparent
         self._url = url
 
-        self.ui.setconfig(b'phases', b'publish', False, b'bundlerepo')
+        # These types are OK because the class is a dynamically generated type.
+        # It would be better to somehow mark that `self` is interfaces.repository.ilocalrepositorymain
+        self.ui.setconfig(b'phases', b'publish', False, b'bundlerepo')  # pytype: disable=attribute-error
 
         self.tempfile = None
         f = util.posixfile(bundlepath, b"rb")
-        bundle = exchange.readbundle(self.ui, f, bundlepath)
+        bundle = exchange.readbundle(self.ui, f, bundlepath)  # pytype: disable=attribute-error
 
         if isinstance(bundle, bundle2.unbundle20):
             self._bundlefile = bundle
@@ -289,7 +291,7 @@
                 f = self._writetempbundle(
                     bundle.read, b'.hg10un', header=b'HG10UN'
                 )
-                bundle = exchange.readbundle(self.ui, f, bundlepath, self.vfs)
+                bundle = exchange.readbundle(self.ui, f, bundlepath, self.vfs)  # pytype: disable=attribute-error
 
             self._bundlefile = bundle
             self._cgunpacker = bundle
@@ -327,7 +329,7 @@
     def _writetempbundle(self, readfn, suffix, header=b''):
         """Write a temporary file to disk
         """
-        fdtemp, temp = self.vfs.mkstemp(prefix=b"hg-bundle-", suffix=suffix)
+        fdtemp, temp = self.vfs.mkstemp(prefix=b"hg-bundle-", suffix=suffix)  # pytype: disable=attribute-error
         self.tempfile = temp
 
         with os.fdopen(fdtemp, 'wb') as fptemp:
@@ -338,7 +340,7 @@
                     break
                 fptemp.write(chunk)
 
-        return self.vfs.open(self.tempfile, mode=b"rb")
+        return self.vfs.open(self.tempfile, mode=b"rb")  # pytype: disable=attribute-error
 
     @localrepo.unfilteredpropertycache
     def _phasecache(self):
@@ -410,7 +412,7 @@
             linkmapper = self.unfiltered().changelog.rev
             return bundlefilelog(self.svfs, f, self._cgunpacker, linkmapper)
         else:
-            return super(bundlerepository, self).file(f)
+            return super(bundlerepository, self).file(f)  # pytype: disable=attribute-error
 
     def close(self):
         """Close assigned bundle file immediately."""
@@ -438,7 +440,7 @@
             self.ui.warn(msg % nodemod.hex(p1))
         if self.changelog.repotiprev < p2rev:
             self.ui.warn(msg % nodemod.hex(p2))
-        return super(bundlerepository, self).setparents(p1, p2)
+        return super(bundlerepository, self).setparents(p1, p2)  # pytype: disable=attribute-error
 
 
 def instance(ui, path, create, intents=None, createopts=None):



To: mharbison72, #hg-reviewers
Cc: mercurial-devel


More information about the Mercurial-devel mailing list