Procházet zdrojové kódy

Fix typing issues broken on other versions/with deps

Jelmer Vernooij před 3 měsíci
rodič
revize
64ed1d285b

+ 3 - 3
dulwich/cli.py

@@ -302,7 +302,7 @@ class PagerBuffer(BinaryIO):
         """
         self.pager = pager
 
-    def write(self, data: Buffer) -> int:
+    def write(self, data: Union[bytes, bytearray, memoryview]) -> int:  # type: ignore[override]
         """Write bytes to pager."""
         # Convert to bytes and decode to string for the pager
         text = bytes(data).decode("utf-8", errors="replace")
@@ -312,7 +312,7 @@ class PagerBuffer(BinaryIO):
         """Flush the pager."""
         return self.pager.flush()
 
-    def writelines(self, lines: Iterable[Buffer]) -> None:
+    def writelines(self, lines: Iterable[Union[bytes, bytearray, memoryview]]) -> None:  # type: ignore[override]
         """Write multiple lines to pager."""
         for line in lines:
             self.write(line)
@@ -4517,7 +4517,7 @@ def main(argv: Optional[list[str]] = None) -> Optional[int]:
 
 def _main() -> None:
     if "DULWICH_PDB" in os.environ and getattr(signal, "SIGQUIT", None):
-        signal.signal(signal.SIGQUIT, signal_quit)
+        signal.signal(signal.SIGQUIT, signal_quit)  # type: ignore[attr-defined,unused-ignore]
     signal.signal(signal.SIGINT, signal_int)
 
     sys.exit(main())

+ 2 - 2
dulwich/client.py

@@ -244,7 +244,7 @@ def _fileno_can_read(fileno: int) -> bool:
 
 def _win32_peek_avail(handle: int) -> int:
     """Wrapper around PeekNamedPipe to check how many bytes are available."""
-    from ctypes import (  # type: ignore[attr-defined]
+    from ctypes import (  # type: ignore[attr-defined,unused-ignore]
         byref,
         windll,
         wintypes,
@@ -256,7 +256,7 @@ def _win32_peek_avail(handle: int) -> int:
         handle, None, 0, None, byref(c_avail), byref(c_message)
     )
     if not success:
-        from ctypes import GetLastError  # type: ignore[attr-defined]
+        from ctypes import GetLastError  # type: ignore[attr-defined,unused-ignore]
 
         raise OSError(GetLastError())
     return c_avail.value

+ 4 - 4
dulwich/config.py

@@ -1353,11 +1353,11 @@ def _find_git_in_win_reg() -> Iterator[str]:
     else:
         subkey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Git_is1"
 
-    for key in (winreg.HKEY_CURRENT_USER, winreg.HKEY_LOCAL_MACHINE):  # type: ignore
+    for key in (winreg.HKEY_CURRENT_USER, winreg.HKEY_LOCAL_MACHINE):  # type: ignore[attr-defined,unused-ignore]
         with suppress(OSError):
-            with winreg.OpenKey(key, subkey) as k:  # type: ignore
-                val, typ = winreg.QueryValueEx(k, "InstallLocation")  # type: ignore
-                if typ == winreg.REG_SZ:  # type: ignore
+            with winreg.OpenKey(key, subkey) as k:  # type: ignore[attr-defined,unused-ignore]
+                val, typ = winreg.QueryValueEx(k, "InstallLocation")  # type: ignore[attr-defined,unused-ignore]
+                if typ == winreg.REG_SZ:  # type: ignore[attr-defined,unused-ignore]
                     yield val
 
 

+ 9 - 3
dulwich/diff.py

@@ -48,9 +48,15 @@ import io
 import logging
 import os
 import stat
-from collections.abc import Buffer, Iterable
+import sys
+from collections.abc import Iterable
 from typing import BinaryIO, Optional, Union
 
+if sys.version_info >= (3, 12):
+    from collections.abc import Buffer
+else:
+    Buffer = Union[bytes, bytearray, memoryview]
+
 from .index import ConflictedIndexEntry, commit_index
 from .object_store import iter_tree_contents
 from .objects import S_ISGITLINK, Blob, Commit
@@ -566,7 +572,7 @@ class ColorizedDiffStream(BinaryIO):
         self.console = Console(file=self.text_wrapper, force_terminal=True)
         self.buffer = b""
 
-    def write(self, data: Union[bytes, Buffer]) -> int:
+    def write(self, data: Union[bytes, Buffer]) -> int:  # type: ignore[override,unused-ignore]
         """Write data to the stream, applying colorization.
 
         Args:
@@ -587,7 +593,7 @@ class ColorizedDiffStream(BinaryIO):
 
         return len(data)
 
-    def writelines(self, lines: Iterable[Union[bytes, Buffer]]) -> None:
+    def writelines(self, lines: Iterable[Union[bytes, Buffer]]) -> None:  # type: ignore[override,unused-ignore]
         """Write a list of lines to the stream.
 
         Args:

+ 11 - 11
dulwich/fastexport.py

@@ -101,7 +101,7 @@ class GitFastExporter:
         """
         marker = self._allocate_marker()
         self.markers[marker] = blob.id
-        return (commands.BlobCommand(marker, blob.data), marker)
+        return (commands.BlobCommand(marker, blob.data), marker)  # type: ignore[no-untyped-call,unused-ignore]
 
     def emit_blob(self, blob: Blob) -> bytes:
         """Emit a blob to the output stream.
@@ -126,7 +126,7 @@ class GitFastExporter:
         ) in self.store.tree_changes(base_tree, new_tree):
             if new_path is None:
                 if old_path is not None:
-                    yield commands.FileDeleteCommand(old_path)
+                    yield commands.FileDeleteCommand(old_path)  # type: ignore[no-untyped-call,unused-ignore]
                 continue
             marker = b""
             if new_mode is not None and not stat.S_ISDIR(new_mode):
@@ -137,10 +137,10 @@ class GitFastExporter:
                     if isinstance(blob, Blob):
                         marker = self.emit_blob(blob)
             if old_path != new_path and old_path is not None:
-                yield commands.FileRenameCommand(old_path, new_path)
+                yield commands.FileRenameCommand(old_path, new_path)  # type: ignore[no-untyped-call,unused-ignore]
             if old_mode != new_mode or old_hexsha != new_hexsha:
                 prefixed_marker = b":" + marker
-                yield commands.FileModifyCommand(
+                yield commands.FileModifyCommand(  # type: ignore[no-untyped-call,unused-ignore]
                     new_path, new_mode, prefixed_marker, None
                 )
 
@@ -157,7 +157,7 @@ class GitFastExporter:
             merges = []
         author, author_email = split_email(commit.author)
         committer, committer_email = split_email(commit.committer)
-        cmd = commands.CommitCommand(
+        cmd = commands.CommitCommand(  # type: ignore[no-untyped-call,unused-ignore]
             ref,
             marker,
             (author, author_email, commit.author_time, commit.author_timezone),
@@ -192,7 +192,7 @@ class GitFastExporter:
         return marker
 
 
-class GitImportProcessor(processor.ImportProcessor):  # type: ignore[misc]
+class GitImportProcessor(processor.ImportProcessor):  # type: ignore[misc,unused-ignore]
     """An import processor that imports into a Git repository using Dulwich."""
 
     # FIXME: Batch creation of objects?
@@ -212,7 +212,7 @@ class GitImportProcessor(processor.ImportProcessor):  # type: ignore[misc]
           verbose: Whether to enable verbose output
           outf: Output file for verbose messages
         """
-        processor.ImportProcessor.__init__(self, params, verbose)
+        processor.ImportProcessor.__init__(self, params, verbose)  # type: ignore[no-untyped-call,unused-ignore]
         self.repo = repo
         self.last_commit = ZERO_SHA
         self.markers: dict[bytes, bytes] = {}
@@ -240,8 +240,8 @@ class GitImportProcessor(processor.ImportProcessor):  # type: ignore[misc]
         Returns:
           Dictionary of markers to object IDs
         """
-        p = parser.ImportParser(stream)
-        self.process(p.iter_commands)
+        p = parser.ImportParser(stream)  # type: ignore[no-untyped-call,unused-ignore]
+        self.process(p.iter_commands)  # type: ignore[no-untyped-call,unused-ignore]
         return self.markers
 
     def blob_handler(self, cmd: commands.BlobCommand) -> None:
@@ -279,7 +279,7 @@ class GitImportProcessor(processor.ImportProcessor):  # type: ignore[misc]
         if cmd.from_:
             cmd.from_ = self.lookup_object(cmd.from_)
             self._reset_base(cmd.from_)
-        for filecmd in cmd.iter_files():
+        for filecmd in cmd.iter_files():  # type: ignore[no-untyped-call,unused-ignore]
             if filecmd.name == b"filemodify":
                 if filecmd.data is not None:
                     blob = Blob.from_string(filecmd.data)
@@ -356,4 +356,4 @@ class GitImportProcessor(processor.ImportProcessor):  # type: ignore[misc]
 
     def feature_handler(self, cmd: commands.FeatureCommand) -> None:
         """Process a FeatureCommand."""
-        raise fastimport_errors.UnknownFeature(cmd.feature_name)
+        raise fastimport_errors.UnknownFeature(cmd.feature_name)  # type: ignore[no-untyped-call,unused-ignore]

+ 1 - 1
dulwich/filters.py

@@ -398,7 +398,7 @@ class ProcessFilterDriver:
                             try:
                                 import signal
 
-                                os.kill(self._process.pid, signal.SIGKILL)
+                                os.kill(self._process.pid, signal.SIGKILL)  # type: ignore[attr-defined,unused-ignore]
                                 self._process.wait(timeout=1)
                             except (ProcessLookupError, subprocess.TimeoutExpired):
                                 pass

+ 9 - 6
dulwich/merge.py

@@ -1,12 +1,15 @@
 """Git merge implementation."""
 
 from difflib import SequenceMatcher
-from typing import Optional
+from typing import TYPE_CHECKING, Optional
 
-try:
+if TYPE_CHECKING:
     import merge3
-except ImportError:
-    merge3 = None
+else:
+    try:
+        import merge3
+    except ImportError:
+        merge3 = None  # type: ignore[assignment]
 
 from dulwich.attrs import GitAttributes
 from dulwich.config import Config
@@ -62,7 +65,7 @@ def _can_merge_lines(
 
 if merge3 is not None:
 
-    def _merge3_to_bytes(m: merge3.Merge3) -> bytes:
+    def _merge3_to_bytes(m: "merge3.Merge3") -> bytes:
         """Convert merge3 result to bytes with conflict markers.
 
         Args:
@@ -72,7 +75,7 @@ if merge3 is not None:
             Merged content as bytes
         """
         result = []
-        for group in m.merge_groups():
+        for group in m.merge_groups():  # type: ignore[no-untyped-call,unused-ignore]
             if group[0] == "unchanged":
                 result.extend(group[1])
             elif group[0] == "a":

+ 1 - 1
dulwich/object_store.py

@@ -1459,7 +1459,7 @@ class DiskObjectStore(PackBasedObjectStore):
             os.remove(pack.index.path)
 
     def _get_pack_basepath(
-        self, entries: Iterable[tuple[bytes, int, int | None]]
+        self, entries: Iterable[tuple[bytes, int, Union[int, None]]]
     ) -> str:
         suffix_bytes = iter_sha1(entry[0] for entry in entries)
         # TODO: Handle self.pack_dir being bytes

+ 19 - 7
dulwich/pack.py

@@ -2294,7 +2294,7 @@ class SHA1Writer(BinaryIO):
         self.sha1 = sha1(b"")
         self.digest: Optional[bytes] = None
 
-    def write(self, data: Buffer, /) -> int:
+    def write(self, data: Union[bytes, bytearray, memoryview], /) -> int:  # type: ignore[override]
         """Write data and update SHA1.
 
         Args:
@@ -2859,7 +2859,11 @@ def full_unpacked_object(o: ShaFile) -> UnpackedObject:
 
 
 def write_pack_from_container(
-    write: Union[Callable[[bytes], None], Callable[[Buffer], int], IO[bytes]],
+    write: Union[
+        Callable[[bytes], None],
+        Callable[[Union[bytes, bytearray, memoryview]], int],
+        IO[bytes],
+    ],
     container: PackedObjectContainer,
     object_ids: Sequence[tuple[ObjectID, Optional[PackHint]]],
     delta_window_size: Optional[int] = None,
@@ -3043,7 +3047,11 @@ class PackChunkGenerator:
 
 
 def write_pack_data(
-    write: Union[Callable[[bytes], None], Callable[[Buffer], int], IO[bytes]],
+    write: Union[
+        Callable[[bytes], None],
+        Callable[[Union[bytes, bytearray, memoryview]], int],
+        IO[bytes],
+    ],
     records: Iterator[UnpackedObject],
     *,
     num_records: Optional[int] = None,
@@ -3075,7 +3083,9 @@ def write_pack_data(
 
 
 def write_pack_index_v1(
-    f: IO[bytes], entries: Iterable[tuple[bytes, int, int | None]], pack_checksum: bytes
+    f: IO[bytes],
+    entries: Iterable[tuple[bytes, int, Union[int, None]]],
+    pack_checksum: bytes,
 ) -> bytes:
     """Write a new pack index file.
 
@@ -3257,7 +3267,9 @@ def apply_delta(
 
 
 def write_pack_index_v2(
-    f: IO[bytes], entries: Iterable[tuple[bytes, int, int | None]], pack_checksum: bytes
+    f: IO[bytes],
+    entries: Iterable[tuple[bytes, int, Union[int, None]]],
+    pack_checksum: bytes,
 ) -> bytes:
     """Write a new pack index file.
 
@@ -3298,7 +3310,7 @@ def write_pack_index_v2(
 
 def write_pack_index_v3(
     f: IO[bytes],
-    entries: Iterable[tuple[bytes, int, int | None]],
+    entries: Iterable[tuple[bytes, int, Union[int, None]]],
     pack_checksum: bytes,
     hash_algorithm: int = 1,
 ) -> bytes:
@@ -3378,7 +3390,7 @@ def write_pack_index_v3(
 
 def write_pack_index(
     f: IO[bytes],
-    entries: Iterable[tuple[bytes, int, int | None]],
+    entries: Iterable[tuple[bytes, int, Union[int, None]]],
     pack_checksum: bytes,
     progress: Optional[Callable[..., None]] = None,
     version: Optional[int] = None,

+ 1 - 1
dulwich/patch.py

@@ -235,7 +235,7 @@ def _get_sequence_matcher(
         try:
             from patiencediff import PatienceSequenceMatcher
 
-            return PatienceSequenceMatcher(None, a, b)
+            return PatienceSequenceMatcher(None, a, b)  # type: ignore[no-any-return,unused-ignore]
         except ImportError:
             raise DiffAlgorithmNotAvailable(
                 "patience", "Install with: pip install 'dulwich[patiencediff]'"

+ 2 - 2
dulwich/porcelain.py

@@ -2297,7 +2297,7 @@ def reset(
                     source: Union[str, bytes, os.PathLike[str]],
                     target: Union[str, bytes, os.PathLike[str]],
                 ) -> None:
-                    symlink(source, target)
+                    symlink(source, target)  # type: ignore[arg-type,unused-ignore]
 
                 symlink_fn = symlink_wrapper
             else:
@@ -4186,7 +4186,7 @@ def checkout(
                 source: Union[str, bytes, os.PathLike[str]],
                 target: Union[str, bytes, os.PathLike[str]],
             ) -> None:
-                symlink(source, target)
+                symlink(source, target)  # type: ignore[arg-type,unused-ignore]
 
             symlink_fn = symlink_wrapper
         else:

+ 1 - 1
dulwich/repo.py

@@ -176,7 +176,7 @@ def _get_default_identity() -> tuple[str, str]:
         fullname = None
     else:
         try:
-            entry = pwd.getpwuid(os.getuid())
+            entry = pwd.getpwuid(os.getuid())  # type: ignore[attr-defined,unused-ignore]
         except KeyError:
             fullname = None
         else:

+ 2 - 2
dulwich/stash.py

@@ -162,7 +162,7 @@ class Stash:
             symlink_fn = symlink
         else:
 
-            def symlink_fn(  # type: ignore[misc]
+            def symlink_fn(  # type: ignore[misc,unused-ignore]
                 src: Union[str, bytes],
                 dst: Union[str, bytes],
                 target_is_directory: bool = False,
@@ -248,7 +248,7 @@ class Stash:
                     tree_entry2.mode,
                     full_path,
                     honor_filemode=honor_filemode,
-                    symlink_fn=symlink_fn,
+                    symlink_fn=symlink_fn,  # type: ignore[arg-type,unused-ignore]
                 )
 
             # Update index if the file wasn't already staged

+ 2 - 2
dulwich/web.py

@@ -83,9 +83,9 @@ else:
             from _typeshed.wsgi import StartResponse, WSGIApplication, WSGIEnvironment
         except ImportError:
             # Define our own protocol types for type checking
-            from typing import Protocol
+            from typing import Protocol as TypingProtocol
 
-            class StartResponse(Protocol):  # type: ignore[no-redef]
+            class StartResponse(TypingProtocol):  # type: ignore[no-redef]
                 """WSGI start_response callable protocol."""
 
                 def __call__(

+ 2 - 2
dulwich/worktree.py

@@ -644,7 +644,7 @@ class WorkTree:
             symlink_fn = symlink
         else:
 
-            def symlink_fn(  # type: ignore[misc]
+            def symlink_fn(  # type: ignore[misc,unused-ignore]
                 src: Union[str, bytes],
                 dst: Union[str, bytes],
                 target_is_directory: bool = False,
@@ -662,7 +662,7 @@ class WorkTree:
             tree,
             honor_filemode=honor_filemode,
             validate_path_element=validate_path_element,
-            symlink_fn=symlink_fn,
+            symlink_fn=symlink_fn,  # type: ignore[arg-type,unused-ignore]
             blob_normalizer=blob_normalizer,
         )
 

+ 23 - 0
pyproject.toml

@@ -76,6 +76,29 @@ ignore_missing_imports = true
 [[tool.mypy.overrides]]
 module = "fastimport"
 ignore_missing_imports = true
+no_implicit_reexport = false
+disallow_untyped_calls = false
+warn_return_any = false
+
+[[tool.mypy.overrides]]
+module = "fastimport.*"
+ignore_missing_imports = true
+no_implicit_reexport = false
+disallow_untyped_calls = false
+warn_return_any = false
+
+[[tool.mypy.overrides]]
+module = "patiencediff"
+ignore_missing_imports = true
+no_implicit_reexport = false
+disallow_untyped_calls = false
+warn_return_any = false
+
+[[tool.mypy.overrides]]
+module = "merge3"
+ignore_missing_imports = true
+disallow_untyped_calls = false
+warn_return_any = false
 
 [tool.setuptools]
 packages = [