comparison mercurial/vfs.py @ 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 5cc8deb96b48
children b6f24a92b399
comparison
equal deleted inserted replaced
52900:0fd4b2af347b 52901:6ee3c401882b
341 341
342 If ``forcibly``, this tries to remove READ-ONLY files, too. 342 If ``forcibly``, this tries to remove READ-ONLY files, too.
343 """ 343 """
344 if forcibly: 344 if forcibly:
345 345
346 def onexc(function, path: bytes, excinfo): 346 def onexc(function: Callable, path: str, excinfo: Exception):
347 # Note: str is passed here even if bytes are passed to rmtree
348 # on platforms where `shutil._use_fd_functions == True`. It is
349 # bytes otherwise. Fortunately, the methods used here accept
350 # both.
347 if function is not os.remove: 351 if function is not os.remove:
348 raise 352 raise
349 # read-only files cannot be unlinked under Windows 353 # read-only files cannot be unlinked under Windows
350 s = os.stat(path) 354 s = os.stat(path)
351 if (s.st_mode & stat.S_IWRITE) != 0: 355 if (s.st_mode & stat.S_IWRITE) != 0:
352 raise 356 raise
353 os.chmod(path, stat.S_IMODE(s.st_mode) | stat.S_IWRITE) 357 os.chmod(path, stat.S_IMODE(s.st_mode) | stat.S_IWRITE)
354 os.remove(path) 358 os.remove(path)
355 359
356 else: 360 else:
357 onexc = None 361
362 def onexc(*args):
363 pass
364
358 try: 365 try:
359 # pytype: disable=wrong-keyword-args 366 # pytype: disable=wrong-keyword-args
360 return shutil.rmtree( 367 return shutil.rmtree(
361 self.join(path), ignore_errors=ignore_errors, onexc=onexc 368 self.join(path), ignore_errors=ignore_errors, onexc=onexc
362 ) 369 )