Просмотр исходного кода

Add PackCapableObjectStore base class to remove type: ignore

Create PackCapableObjectStore as a base class for both PackBasedObjectStore
and MemoryObjectStore. This class inherits from both BaseObjectStore and
PackedObjectContainer, providing:

1. add_pack() and add_pack_data() methods for pack operations
2. Default implementations of get_unpacked_object() and iterobjects_subset()
   from PackedObjectContainer protocol

This allows MemoryObjectStore to properly support pack operations without
needing type: ignore comments, while maintaining the existing class hierarchy
where PackBasedObjectStore adds disk-specific pack functionality.
Jelmer Vernooij 3 месяцев назад
Родитель
Сommit
4704c14538
5 измененных файлов с 82 добавлено и 33 удалено
  1. 5 5
      dulwich/__init__.py
  2. 0 20
      dulwich/__init__.pyi
  3. 4 4
      dulwich/diff_tree.py
  4. 68 2
      dulwich/object_store.py
  5. 5 2
      dulwich/repo.py

+ 5 - 5
dulwich/__init__.py

@@ -40,14 +40,14 @@ R = TypeVar("R")
 F = TypeVar("F", bound=Callable[..., Any])
 
 try:
-    from dissolve import replace_me
+    from dissolve import replace_me as replace_me
 except ImportError:
     # if dissolve is not installed, then just provide a basic implementation
     # of its replace_me decorator
     def replace_me(
-        since: Optional[Union[str, tuple[int, ...]]] = None,
-        remove_in: Optional[Union[str, tuple[int, ...]]] = None,
-    ) -> Callable[[Callable[P, R]], Callable[P, R]]:
+        since: Optional[Union[tuple[int, ...], str]] = None,
+        remove_in: Optional[Union[tuple[int, ...], str]] = None,
+    ) -> Callable[[F], F]:
         """Decorator to mark functions as deprecated.
 
         Args:
@@ -86,4 +86,4 @@ except ImportError:
 
             return _wrapped_func
 
-        return decorator
+        return decorator  # type: ignore[return-value]

+ 0 - 20
dulwich/__init__.pyi

@@ -1,20 +0,0 @@
-# Type stubs for dulwich/__init__.py
-
-from typing import Callable, Optional, TypeVar, Union
-
-if True:  # sys.version_info >= (3, 10)
-    from typing import ParamSpec
-else:
-    from typing_extensions import ParamSpec
-
-__version__: tuple[int, int, int]
-
-__all__: list[str]
-
-P = ParamSpec("P")
-R = TypeVar("R")
-
-def replace_me(
-    since: Optional[Union[str, tuple[int, ...]]] = None,
-    remove_in: Optional[Union[str, tuple[int, ...]]] = None,
-) -> Callable[[Callable[P, R]], Callable[P, R]]: ...

+ 4 - 4
dulwich/diff_tree.py

@@ -116,10 +116,10 @@ def _merge_entries(
     while i1 < len1 and i2 < len2:
         entry1 = entries1[i1]
         entry2 = entries2[i2]
-        if entry1.path < entry2.path:  # type: ignore[operator]
+        if entry1.path < entry2.path:
             result.append((entry1, None))
             i1 += 1
-        elif entry1.path > entry2.path:  # type: ignore[operator]
+        elif entry1.path > entry2.path:
             result.append((None, entry2))
             i2 += 1
         else:
@@ -175,8 +175,8 @@ def walk_trees(
         if prune_identical and is_tree1 and is_tree2 and entry1 == entry2:
             continue
 
-        tree1 = (is_tree1 and entry1 and store[entry1.sha]) or None  # type: ignore[index]
-        tree2 = (is_tree2 and entry2 and store[entry2.sha]) or None  # type: ignore[index]
+        tree1 = (is_tree1 and entry1 and store[entry1.sha]) or None
+        tree2 = (is_tree2 and entry2 and store[entry2.sha]) or None
         path = (
             (entry1.path if entry1 else None)
             or (entry2.path if entry2 else None)

+ 68 - 2
dulwich/object_store.py

@@ -622,7 +622,73 @@ class BaseObjectStore:
         raise KeyError(sha)
 
 
-class PackBasedObjectStore(BaseObjectStore, PackedObjectContainer):
+class PackCapableObjectStore(BaseObjectStore, PackedObjectContainer):
+    """Object store that supports pack operations.
+
+    This is a base class for object stores that can handle pack files,
+    including both disk-based and memory-based stores.
+    """
+
+    def add_pack(self) -> tuple[BinaryIO, Callable[[], None], Callable[[], None]]:
+        """Add a new pack to this object store.
+
+        Returns: Tuple of (file, commit_func, abort_func)
+        """
+        raise NotImplementedError(self.add_pack)
+
+    def add_pack_data(
+        self,
+        count: int,
+        unpacked_objects: Iterator["UnpackedObject"],
+        progress: Optional[Callable[..., None]] = None,
+    ) -> Optional["Pack"]:
+        """Add pack data to this object store.
+
+        Args:
+          count: Number of objects
+          unpacked_objects: Iterator over unpacked objects
+          progress: Optional progress callback
+        """
+        raise NotImplementedError(self.add_pack_data)
+
+    def get_unpacked_object(
+        self, sha1: bytes, *, include_comp: bool = False
+    ) -> "UnpackedObject":
+        """Get a raw unresolved object.
+
+        Args:
+            sha1: SHA-1 hash of the object
+            include_comp: Whether to include compressed data
+
+        Returns:
+            UnpackedObject instance
+        """
+        from .pack import UnpackedObject
+
+        obj = self[sha1]
+        return UnpackedObject(obj.type_num, sha=sha1, decomp_chunks=obj.as_raw_chunks())
+
+    def iterobjects_subset(
+        self, shas: Iterable[bytes], *, allow_missing: bool = False
+    ) -> Iterator[ShaFile]:
+        """Iterate over a subset of objects.
+
+        Args:
+            shas: Iterable of object SHAs to retrieve
+            allow_missing: If True, skip missing objects
+
+        Returns:
+            Iterator of ShaFile objects
+        """
+        for sha in shas:
+            try:
+                yield self[sha]
+            except KeyError:
+                if not allow_missing:
+                    raise
+
+
+class PackBasedObjectStore(PackCapableObjectStore, PackedObjectContainer):
     """Object store that uses pack files for storage.
 
     This class provides a base implementation for object stores that use
@@ -1836,7 +1902,7 @@ class DiskObjectStore(PackBasedObjectStore):
                     os.remove(pack_path)
 
 
-class MemoryObjectStore(BaseObjectStore):
+class MemoryObjectStore(PackCapableObjectStore):
     """Object store that keeps all objects in memory."""
 
     def __init__(self) -> None:

+ 5 - 2
dulwich/repo.py

@@ -87,6 +87,7 @@ from .object_store import (
     MissingObjectFinder,
     ObjectStoreGraphWalker,
     PackBasedObjectStore,
+    PackCapableObjectStore,
     find_shallow,
     peel_sha,
 )
@@ -407,7 +408,9 @@ class BaseRepo:
         repository
     """
 
-    def __init__(self, object_store: PackBasedObjectStore, refs: RefsContainer) -> None:
+    def __init__(
+        self, object_store: "PackCapableObjectStore", refs: RefsContainer
+    ) -> None:
         """Open a repository.
 
         This shouldn't be called directly, but rather through one of the
@@ -2217,7 +2220,7 @@ class MemoryRepo(BaseRepo):
 
         self._reflog: list[Any] = []
         refs_container = DictRefsContainer({}, logger=self._append_reflog)
-        BaseRepo.__init__(self, MemoryObjectStore(), refs_container)  # type: ignore[arg-type]
+        BaseRepo.__init__(self, MemoryObjectStore(), refs_container)
         self._named_files: dict[str, bytes] = {}
         self.bare = True
         self._config = ConfigFile()