changeset 52901:6ee3c401882b

vfs: avoid passing None to `shutil.rmtree()` for the exception handler Even though the code looks like it will handle it, pytype 2024.10.11 complains. So the simplest thing to do is pass along a no-op function that it would use internally if it was explicitly provided None. The specific error was: /home/mharbison/projects/mercurial/mercurial-devel/mercurial/vfs.py:360:20: error: in rmtree: Function _RmtreeType.__call__ was called with the wrong arguments [wrong-arg-types] Expected: (self, path, ignore_errors, *, dir_fd, onexc: Callable[[Callable, str, Exception], object]) Actually passed: (self, path, ignore_errors, onexc: Optional[Callable[[Any, bytes, Any], Any]]) Attributes of protocol Callable[[Callable, str, Exception], object] are not implemented on None: __call__ return shutil.rmtree( ~~~~~~~~~~~~~~ self.join(path), ignore_errors=ignore_errors, onexc=onexc ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ) ~~~~~~~~~~~~~ Note that it expects a str on the callback. I thought maybe there would be an @overload, and it could handle both. But looking at the code in Python 3.11, they call `os.fsdecode(path)` on some platforms when given bytes, and pass that str to the callback. So adjust the typehint accordingly, and leave a note.
author Matt Harbison <matt_harbison@yahoo.com>
date Tue, 11 Feb 2025 22:44:21 -0500
parents 0fd4b2af347b
children 3e8a3db5f5e8
files mercurial/vfs.py
diffstat 1 files changed, 9 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/vfs.py	Thu Feb 13 11:40:56 2025 -0500
+++ b/mercurial/vfs.py	Tue Feb 11 22:44:21 2025 -0500
@@ -343,7 +343,11 @@
         """
         if forcibly:
 
-            def onexc(function, path: bytes, excinfo):
+            def onexc(function: Callable, path: str, excinfo: Exception):
+                # Note: str is passed here even if bytes are passed to rmtree
+                # on platforms where `shutil._use_fd_functions == True`.  It is
+                # bytes otherwise.  Fortunately, the methods used here accept
+                # both.
                 if function is not os.remove:
                     raise
                 # read-only files cannot be unlinked under Windows
@@ -354,7 +358,10 @@
                 os.remove(path)
 
         else:
-            onexc = None
+
+            def onexc(*args):
+                pass
+
         try:
             # pytype: disable=wrong-keyword-args
             return shutil.rmtree(