diff mercurial/patch.py @ 52910:9b85f6efcc1d

typing: add a cast to `mercurial.patch` to unconfuse pytype 2024.10.11 I've seen this in other, more modern versions of pytype than what we use in CI- it thinks the return of `get_payload()` is `Message | bytes`, and then complains about `if not payload.endswith(b'\n')` below, saying `Message` doesn't have that function. That's correct, but according to the table in `get_payload()` that documents what the method returns, the only possible values are `bytes | None` when `decode=True` and the `i` argument isn't passed. And `None` isn't possible if we trust the `Content-Type` header. While here, I added a type hint for the `part` variable, since PyCharm couldn't figure out what was going on here, and that made navigating to the code impossible.
author Matt Harbison <matt_harbison@yahoo.com>
date Tue, 11 Feb 2025 21:21:17 -0500
parents 279e217d6041
children
line wrap: on
line diff
--- a/mercurial/patch.py	Sun Feb 16 01:20:24 2025 +0100
+++ b/mercurial/patch.py	Tue Feb 11 21:21:17 2025 -0500
@@ -46,6 +46,8 @@
 )
 
 if typing.TYPE_CHECKING:
+    import email
+
     from typing import (
         Any,
         Iterator,
@@ -279,12 +281,18 @@
     diffs_seen = 0
     ok_types = (b'text/plain', b'text/x-diff', b'text/x-patch')
     message = b''
+
+    part: email.message.Message
     for part in msg.walk():
         content_type = pycompat.bytestr(part.get_content_type())
         ui.debug(b'Content-Type: %s\n' % content_type)
         if content_type not in ok_types:
             continue
-        payload = part.get_payload(decode=True)
+
+        # When decode=True, the only possible return types are bytes or None
+        # for a multipart message.  But it can't be multipart here, because the
+        # Content-Type was just checked.
+        payload = typing.cast(bytes, part.get_payload(decode=True))
         m = diffre.search(payload)
         if m:
             hgpatch = False