From 82b131cf2afebbed3723df5b5dfd5cd820716f97 Mon Sep 17 00:00:00 2001 From: Yobmod Date: Wed, 30 Jun 2021 18:41:06 +0100 Subject: Type Traversable.traverse() better, start types of submodule --- git/objects/tree.py | 54 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 12 deletions(-) (limited to 'git/objects/tree.py') diff --git a/git/objects/tree.py b/git/objects/tree.py index 191fe27c..44d3b3da 100644 --- a/git/objects/tree.py +++ b/git/objects/tree.py @@ -3,6 +3,7 @@ # # This module is part of GitPython and is released under # the BSD License: http://www.opensource.org/licenses/bsd-license.php + from git.util import join_path import git.diff as diff from git.util import to_bin_sha @@ -20,14 +21,18 @@ from .fun import ( # typing ------------------------------------------------- -from typing import Callable, Dict, Generic, Iterable, Iterator, List, Tuple, Type, TypeVar, Union, cast, TYPE_CHECKING +from typing import (Callable, Dict, Generic, Iterable, Iterator, List, + Tuple, Type, TypeVar, Union, cast, TYPE_CHECKING) -from git.types import PathLike +from git.types import PathLike, TypeGuard if TYPE_CHECKING: from git.repo import Repo + from git.objects.util import TraversedTup from io import BytesIO +T_Tree_cache = TypeVar('T_Tree_cache', bound=Union[Tuple[bytes, int, str]]) + #-------------------------------------------------------- @@ -35,8 +40,6 @@ cmp: Callable[[str, str], int] = lambda a, b: (a > b) - (a < b) __all__ = ("TreeModifier", "Tree") -T_Tree_cache = TypeVar('T_Tree_cache', bound=Union[Tuple[bytes, int, str]]) - def git_cmp(t1: T_Tree_cache, t2: T_Tree_cache) -> int: a, b = t1[2], t2[2] @@ -137,8 +140,12 @@ class TreeModifier(Generic[T_Tree_cache], object): sha = to_bin_sha(sha) index = self._index_by_name(name) - assert isinstance(sha, bytes) and isinstance(mode, int) and isinstance(name, str) - item = cast(T_Tree_cache, (sha, mode, name)) # use Typeguard from typing-extensions 3.10.0 + def is_tree_cache(inp: Tuple[bytes, int, str]) -> TypeGuard[T_Tree_cache]: + return isinstance(inp[0], bytes) and isinstance(inp[1], int) and isinstance([inp], str) + + item = (sha, mode, name) + assert is_tree_cache(item) + if index == -1: self._cache.append(item) else: @@ -205,7 +212,7 @@ class Tree(IndexObject, diff.Diffable, util.Traversable, util.Serializable): super(Tree, self).__init__(repo, binsha, mode, path) @ classmethod - def _get_intermediate_items(cls, index_object: 'Tree', # type: ignore + def _get_intermediate_items(cls, index_object: 'Tree', ) -> Union[Tuple['Tree', ...], Tuple[()]]: if index_object.type == "tree": index_object = cast('Tree', index_object) @@ -289,14 +296,37 @@ class Tree(IndexObject, diff.Diffable, util.Traversable, util.Serializable): See the ``TreeModifier`` for more information on how to alter the cache""" return TreeModifier(self._cache) - def traverse(self, predicate=lambda i, d: True, - prune=lambda i, d: False, depth=-1, branch_first=True, - visit_once=False, ignore_self=1): - """For documentation, see util.Traversable.traverse + def traverse(self, + predicate: Callable[[Union['Tree', 'Submodule', 'Blob', + 'TraversedTup'], int], bool] = lambda i, d: True, + prune: Callable[[Union['Tree', 'Submodule', 'Blob', 'TraversedTup'], int], bool] = lambda i, d: False, + depth: int = -1, + branch_first: bool = True, + visit_once: bool = False, + ignore_self: int = 1, + as_edge: bool = False + ) -> Union[Iterator[Union['Tree', 'Blob', 'Submodule']], + Iterator[Tuple[Union['Tree', 'Submodule', None], Union['Tree', 'Blob', 'Submodule']]]]: + """For documentation, see util.Traversable._traverse() Trees are set to visit_once = False to gain more performance in the traversal""" - return super(Tree, self).traverse(predicate, prune, depth, branch_first, visit_once, ignore_self) + + # """ + # # To typecheck instead of using cast. + # import itertools + # def is_tree_traversed(inp: Tuple) -> TypeGuard[Tuple[Iterator[Union['Tree', 'Blob', 'Submodule']]]]: + # return all(isinstance(x, (Blob, Tree, Submodule)) for x in inp[1]) + + # ret = super(Tree, self).traverse(predicate, prune, depth, branch_first, visit_once, ignore_self) + # ret_tup = itertools.tee(ret, 2) + # assert is_tree_traversed(ret_tup), f"Type is {[type(x) for x in list(ret_tup[0])]}" + # return ret_tup[0]""" + return cast(Union[Iterator[Union['Tree', 'Blob', 'Submodule']], + Iterator[Tuple[Union['Tree', 'Submodule', None], Union['Tree', 'Blob', 'Submodule']]]], + super(Tree, self).traverse(predicate, prune, depth, # type: ignore + branch_first, visit_once, ignore_self)) # List protocol + def __getslice__(self, i: int, j: int) -> List[Union[Blob, 'Tree', Submodule]]: return list(self._iter_convert_to_object(self._cache[i:j])) -- cgit v1.2.1 From 237966a20a61237a475135ed8a13b90f65dcb2ca Mon Sep 17 00:00:00 2001 From: Yobmod Date: Wed, 30 Jun 2021 22:25:30 +0100 Subject: Type Tree.traverse() better --- git/objects/tree.py | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) (limited to 'git/objects/tree.py') diff --git a/git/objects/tree.py b/git/objects/tree.py index 44d3b3da..f61a4a87 100644 --- a/git/objects/tree.py +++ b/git/objects/tree.py @@ -9,7 +9,7 @@ import git.diff as diff from git.util import to_bin_sha from . import util -from .base import IndexObject +from .base import IndexObject, IndexObjUnion from .blob import Blob from .submodule.base import Submodule @@ -28,10 +28,11 @@ from git.types import PathLike, TypeGuard if TYPE_CHECKING: from git.repo import Repo - from git.objects.util import TraversedTup from io import BytesIO -T_Tree_cache = TypeVar('T_Tree_cache', bound=Union[Tuple[bytes, int, str]]) +T_Tree_cache = TypeVar('T_Tree_cache', bound=Tuple[bytes, int, str]) +TraversedTreeTup = Union[Tuple[Union['Tree', None], IndexObjUnion, + Tuple['Submodule', 'Submodule']]] #-------------------------------------------------------- @@ -201,7 +202,7 @@ class Tree(IndexObject, diff.Diffable, util.Traversable, util.Serializable): symlink_id = 0o12 tree_id = 0o04 - _map_id_to_type: Dict[int, Union[Type[Submodule], Type[Blob], Type['Tree']]] = { + _map_id_to_type: Dict[int, Type[IndexObjUnion]] = { commit_id: Submodule, blob_id: Blob, symlink_id: Blob @@ -229,7 +230,7 @@ class Tree(IndexObject, diff.Diffable, util.Traversable, util.Serializable): # END handle attribute def _iter_convert_to_object(self, iterable: Iterable[Tuple[bytes, int, str]] - ) -> Iterator[Union[Blob, 'Tree', Submodule]]: + ) -> Iterator[IndexObjUnion]: """Iterable yields tuples of (binsha, mode, name), which will be converted to the respective object representation""" for binsha, mode, name in iterable: @@ -240,7 +241,7 @@ class Tree(IndexObject, diff.Diffable, util.Traversable, util.Serializable): raise TypeError("Unknown mode %o found in tree data for path '%s'" % (mode, path)) from e # END for each item - def join(self, file: str) -> Union[Blob, 'Tree', Submodule]: + def join(self, file: str) -> IndexObjUnion: """Find the named object in this tree's contents :return: ``git.Blob`` or ``git.Tree`` or ``git.Submodule`` @@ -273,7 +274,7 @@ class Tree(IndexObject, diff.Diffable, util.Traversable, util.Serializable): raise KeyError(msg % file) # END handle long paths - def __truediv__(self, file: str) -> Union['Tree', Blob, Submodule]: + def __truediv__(self, file: str) -> IndexObjUnion: """For PY3 only""" return self.join(file) @@ -296,17 +297,16 @@ class Tree(IndexObject, diff.Diffable, util.Traversable, util.Serializable): See the ``TreeModifier`` for more information on how to alter the cache""" return TreeModifier(self._cache) - def traverse(self, - predicate: Callable[[Union['Tree', 'Submodule', 'Blob', - 'TraversedTup'], int], bool] = lambda i, d: True, - prune: Callable[[Union['Tree', 'Submodule', 'Blob', 'TraversedTup'], int], bool] = lambda i, d: False, + def traverse(self, # type: ignore # overrides super() + predicate: Callable[[Union[IndexObjUnion, TraversedTreeTup], int], bool] = lambda i, d: True, + prune: Callable[[Union[IndexObjUnion, TraversedTreeTup], int], bool] = lambda i, d: False, depth: int = -1, branch_first: bool = True, visit_once: bool = False, ignore_self: int = 1, as_edge: bool = False - ) -> Union[Iterator[Union['Tree', 'Blob', 'Submodule']], - Iterator[Tuple[Union['Tree', 'Submodule', None], Union['Tree', 'Blob', 'Submodule']]]]: + ) -> Union[Iterator[IndexObjUnion], + Iterator[TraversedTreeTup]]: """For documentation, see util.Traversable._traverse() Trees are set to visit_once = False to gain more performance in the traversal""" @@ -320,23 +320,22 @@ class Tree(IndexObject, diff.Diffable, util.Traversable, util.Serializable): # ret_tup = itertools.tee(ret, 2) # assert is_tree_traversed(ret_tup), f"Type is {[type(x) for x in list(ret_tup[0])]}" # return ret_tup[0]""" - return cast(Union[Iterator[Union['Tree', 'Blob', 'Submodule']], - Iterator[Tuple[Union['Tree', 'Submodule', None], Union['Tree', 'Blob', 'Submodule']]]], + return cast(Union[Iterator[IndexObjUnion], Iterator[TraversedTreeTup]], super(Tree, self).traverse(predicate, prune, depth, # type: ignore branch_first, visit_once, ignore_self)) # List protocol - def __getslice__(self, i: int, j: int) -> List[Union[Blob, 'Tree', Submodule]]: + def __getslice__(self, i: int, j: int) -> List[IndexObjUnion]: return list(self._iter_convert_to_object(self._cache[i:j])) - def __iter__(self) -> Iterator[Union[Blob, 'Tree', Submodule]]: + def __iter__(self) -> Iterator[IndexObjUnion]: return self._iter_convert_to_object(self._cache) def __len__(self) -> int: return len(self._cache) - def __getitem__(self, item: Union[str, int, slice]) -> Union[Blob, 'Tree', Submodule]: + def __getitem__(self, item: Union[str, int, slice]) -> IndexObjUnion: if isinstance(item, int): info = self._cache[item] return self._map_id_to_type[info[1] >> 12](self.repo, info[0], info[1], join_path(self.path, info[2])) @@ -348,7 +347,7 @@ class Tree(IndexObject, diff.Diffable, util.Traversable, util.Serializable): raise TypeError("Invalid index type: %r" % item) - def __contains__(self, item: Union[IndexObject, PathLike]) -> bool: + def __contains__(self, item: Union[IndexObjUnion, PathLike]) -> bool: if isinstance(item, IndexObject): for info in self._cache: if item.binsha == info[0]: -- cgit v1.2.1 From 02b8ef0f163ca353e27f6b4a8c2120444739fde5 Mon Sep 17 00:00:00 2001 From: Yobmod Date: Thu, 1 Jul 2021 10:35:11 +0100 Subject: Add missed types to Commit, uncomment to_native_path_linux() --- git/objects/tree.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'git/objects/tree.py') diff --git a/git/objects/tree.py b/git/objects/tree.py index f61a4a87..2e8d8a79 100644 --- a/git/objects/tree.py +++ b/git/objects/tree.py @@ -321,7 +321,7 @@ class Tree(IndexObject, diff.Diffable, util.Traversable, util.Serializable): # assert is_tree_traversed(ret_tup), f"Type is {[type(x) for x in list(ret_tup[0])]}" # return ret_tup[0]""" return cast(Union[Iterator[IndexObjUnion], Iterator[TraversedTreeTup]], - super(Tree, self).traverse(predicate, prune, depth, # type: ignore + super(Tree, self).traverse(predicate, prune, depth, # type: ignore branch_first, visit_once, ignore_self)) # List protocol -- cgit v1.2.1