summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYobmod <yobmod@gmail.com>2021-06-30 22:47:45 +0100
committerYobmod <yobmod@gmail.com>2021-06-30 22:47:45 +0100
commita8ddf69c1268d2af6eff9179218ab61bcda1f6e5 (patch)
tree4305af24d08bf9b9ea74e436dc92a1599e4bb9dc
parent237966a20a61237a475135ed8a13b90f65dcb2ca (diff)
downloadgitpython-a8ddf69c1268d2af6eff9179218ab61bcda1f6e5.tar.gz
Type Traversable/list_traverse() better, make IterablleObj a protocol
-rw-r--r--git/objects/util.py24
-rw-r--r--git/remote.py2
-rw-r--r--git/types.py6
-rw-r--r--git/util.py9
4 files changed, 22 insertions, 19 deletions
diff --git a/git/objects/util.py b/git/objects/util.py
index fce62af2..bc6cdf8f 100644
--- a/git/objects/util.py
+++ b/git/objects/util.py
@@ -23,7 +23,7 @@ from datetime import datetime, timedelta, tzinfo
from typing import (Any, Callable, Deque, Iterator, NamedTuple, overload, Sequence,
TYPE_CHECKING, Tuple, Type, TypeVar, Union, cast)
-from git.types import Literal
+from git.types import Literal, TypeGuard
if TYPE_CHECKING:
from io import BytesIO, StringIO
@@ -306,24 +306,20 @@ class Traversable(object):
"""
raise NotImplementedError("To be implemented in subclass")
- def list_traverse(self, *args: Any, **kwargs: Any
- ) -> Union[IterableList['TraversableIterableObj'],
- IterableList[Tuple[Union[None, 'TraversableIterableObj'], 'TraversableIterableObj']]]:
+ def list_traverse(self, *args: Any, **kwargs: Any) -> IterableList['TraversableIterableObj']:
"""
:return: IterableList with the results of the traversal as produced by
traverse()
List objects must be IterableObj and Traversable e.g. Commit, Submodule"""
- out: Union[IterableList['TraversableIterableObj'],
- IterableList[Tuple[Union[None, 'TraversableIterableObj'], 'TraversableIterableObj']]]
-
- # def is_TraversableIterableObj(inp: Union['Traversable', IterableObj]) -> TypeGuard['TraversableIterableObj']:
- # return isinstance(self, TraversableIterableObj)
- # assert is_TraversableIterableObj(self), f"{type(self)}"
-
- self = cast('TraversableIterableObj', self)
- out = IterableList(self._id_attribute_)
- out.extend(self.traverse(*args, **kwargs)) # type: ignore
+ def is_TraversableIterableObj(inp: 'Traversable') -> TypeGuard['TraversableIterableObj']:
+ # return isinstance(self, TraversableIterableObj)
+ # Can it be anythin else?
+ return isinstance(self, Traversable)
+
+ assert is_TraversableIterableObj(self), f"{type(self)}"
+ out: IterableList['TraversableIterableObj'] = IterableList(self._id_attribute_)
+ out.extend(self.traverse(*args, **kwargs))
return out
def traverse(self,
diff --git a/git/remote.py b/git/remote.py
index a036446e..0ef54ea7 100644
--- a/git/remote.py
+++ b/git/remote.py
@@ -128,6 +128,7 @@ class PushInfo(IterableObj, object):
info.summary # summary line providing human readable english text about the push
"""
__slots__ = ('local_ref', 'remote_ref_string', 'flags', '_old_commit_sha', '_remote', 'summary')
+ _id_attribute_ = 'pushinfo'
NEW_TAG, NEW_HEAD, NO_MATCH, REJECTED, REMOTE_REJECTED, REMOTE_FAILURE, DELETED, \
FORCED_UPDATE, FAST_FORWARD, UP_TO_DATE, ERROR = [1 << x for x in range(11)]
@@ -242,6 +243,7 @@ class FetchInfo(IterableObj, object):
info.remote_ref_path # The path from which we fetched on the remote. It's the remote's version of our info.ref
"""
__slots__ = ('ref', 'old_commit', 'flags', 'note', 'remote_ref_path')
+ _id_attribute_ = 'fetchinfo'
NEW_TAG, NEW_HEAD, HEAD_UPTODATE, TAG_UPDATE, REJECTED, FORCED_UPDATE, \
FAST_FORWARD, ERROR = [1 << x for x in range(8)]
diff --git a/git/types.py b/git/types.py
index ea91d038..ad9bed16 100644
--- a/git/types.py
+++ b/git/types.py
@@ -6,6 +6,11 @@ import os
import sys
from typing import Dict, Union, Any, TYPE_CHECKING
+if sys.version_info[:2] >= (3, 7):
+ from typing import Protocol # noqa: F401
+else:
+ from typing_extensions import Protocol # noqa: F401
+
if sys.version_info[:2] >= (3, 8):
from typing import Final, Literal, SupportsIndex, TypedDict # noqa: F401
else:
@@ -18,7 +23,6 @@ else:
if sys.version_info[:2] < (3, 9):
- # Python >= 3.6, < 3.9
PathLike = Union[str, os.PathLike]
elif sys.version_info[:2] >= (3, 9):
# os.PathLike only becomes subscriptable from Python 3.9 onwards
diff --git a/git/util.py b/git/util.py
index 057d7478..ebb119b9 100644
--- a/git/util.py
+++ b/git/util.py
@@ -27,7 +27,7 @@ import warnings
# typing ---------------------------------------------------------
-from typing import (Any, AnyStr, BinaryIO, Callable, Dict, Generator, IO, Iterable as typIter, Iterator, List,
+from typing import (Any, AnyStr, BinaryIO, Callable, Dict, Generator, IO, Iterator, List,
Optional, Pattern, Sequence, Tuple, TypeVar, Union, cast, TYPE_CHECKING, overload)
import pathlib
@@ -37,9 +37,10 @@ if TYPE_CHECKING:
from git.repo.base import Repo
from git.config import GitConfigParser, SectionConstraint
-from .types import PathLike, Literal, SupportsIndex, HSH_TD, Total_TD, Files_TD
+from .types import (Literal, Protocol, SupportsIndex, # because behind py version guards
+ PathLike, HSH_TD, Total_TD, Files_TD) # aliases
-T_IterableObj = TypeVar('T_IterableObj', bound=Union['IterableObj', typIter], covariant=True)
+T_IterableObj = TypeVar('T_IterableObj', bound='IterableObj', covariant=True)
# So IterableList[Head] is subtype of IterableList[IterableObj]
# ---------------------------------------------------------------------
@@ -1065,7 +1066,7 @@ class Iterable(object):
raise NotImplementedError("To be implemented by Subclass")
-class IterableObj():
+class IterableObj(Protocol):
"""Defines an interface for iterable items which is to assure a uniform
way to retrieve and iterate items within the git repository