typing: correct pytype mistakes in `mercurial/vfs.py`
authorMatt Harbison <matt_harbison@yahoo.com>
Fri, 20 Sep 2024 16:36:28 -0400
changeset 51891 ad83e4f9b40e
parent 51890 38720073aa34
child 51892 fa9e8a6521c1
typing: correct pytype mistakes in `mercurial/vfs.py` With the previous changes in this series (prior to merging the *.pyi file), this wasn't too bad- the only definitively wrong things were the `data` argument to `writelines()`, and the return type on `backgroundclosing()` (both of these errors were dropped in the previous commit; for some reason pytype doesn't like `contextlib._GeneratorContextManager`, even though that's what it determined it is): File "/mnt/c/Users/Matt/hg/mercurial/vfs.py", line 411, in abstractvfs: Bad return type 'contextlib._GeneratorContextManager' for generator function abstractvfs.backgroundclosing [bad-yield-annotation] Expected Generator, Iterable or Iterator PyCharm thinks this is `Generator[backgroundfilecloser], Any, None]`, which can be reduced to `Iterator[backgroundfilecloser]`, but pytype flagged the line that calls `yield` without an argument unless it's also `Optional`. PyCharm is happy either way. For some reason, `Iterable` didn't work for pytype: File "/mnt/c/Users/Matt/hg/mercurial/vfs.py", line 390, in abstractvfs: Function contextlib.contextmanager was called with the wrong arguments [wrong-arg-types] Expected: (func: Callable[[Any], Iterator]) Actually passed: (func: Callable[[Any, Any, Any], Iterable[Optional[Any]]]) Attributes of protocol Iterator[_T_co] are not implemented on Iterable[Optional[Any]]: __next__
mercurial/vfs.py
--- a/mercurial/vfs.py	Fri Sep 20 13:38:13 2024 -0400
+++ b/mercurial/vfs.py	Fri Sep 20 16:36:28 2024 -0400
@@ -126,7 +126,11 @@
             return fp.write(data)
 
     def writelines(
-        self, path: bytes, data: bytes, mode: bytes = b'wb', notindexed=False
+        self,
+        path: bytes,
+        data: Iterable[bytes],
+        mode: bytes = b'wb',
+        notindexed=False,
     ) -> None:
         with self(path, mode=mode, notindexed=notindexed) as fp:
             return fp.writelines(data)
@@ -362,7 +366,9 @@
     def utime(self, path: Optional[bytes] = None, t=None) -> None:
         return os.utime(self.join(path), t)
 
-    def walk(self, path: Optional[bytes] = None, onerror=None):
+    def walk(
+        self, path: Optional[bytes] = None, onerror=None
+    ) -> Iterator[Tuple[bytes, List[bytes], List[bytes]]]:
         """Yield (dirpath, dirs, files) tuple for each directory under path
 
         ``dirpath`` is relative one from the root of this vfs. This
@@ -379,7 +385,9 @@
             yield (dirpath[prefixlen:], dirs, files)
 
     @contextlib.contextmanager
-    def backgroundclosing(self, ui, expectedcount=-1):
+    def backgroundclosing(
+        self, ui, expectedcount=-1
+    ) -> Iterator[Optional[backgroundfilecloser]]:
         """Allow files to be closed asynchronously.
 
         When this context manager is active, ``backgroundclose`` can be passed
@@ -723,11 +731,11 @@
         return self
 
     @abc.abstractmethod
-    def __exit__(self, exc_type, exc_value, exc_tb):
+    def __exit__(self, exc_type, exc_value, exc_tb) -> None:
         ...
 
     @abc.abstractmethod
-    def close(self):
+    def close(self) -> None:
         ...
 
 
@@ -741,7 +749,7 @@
         super(delayclosedfile, self).__init__(fh)
         object.__setattr__(self, '_closer', closer)
 
-    def __exit__(self, exc_type, exc_value, exc_tb):
+    def __exit__(self, exc_type, exc_value, exc_tb) -> None:
         self._closer.close(self._origfh)
 
     def close(self) -> None:
@@ -793,7 +801,7 @@
         self._entered = True
         return self
 
-    def __exit__(self, exc_type, exc_value, exc_tb) -> None:  # TODO
+    def __exit__(self, exc_type, exc_value, exc_tb) -> None:
         self._running = False
 
         # Wait for threads to finish closing so open files don't linger for
@@ -860,7 +868,7 @@
         if oldstat.stat:
             _avoidambig(self._origfh.name, oldstat)
 
-    def __exit__(self, exc_type, exc_value, exc_tb) -> None:  # TODO
+    def __exit__(self, exc_type, exc_value, exc_tb) -> None:
         self._origfh.__exit__(exc_type, exc_value, exc_tb)
         self._checkambig()