summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--git/objects/commit.py4
-rw-r--r--git/objects/submodule/base.py20
-rw-r--r--git/objects/util.py11
-rw-r--r--git/refs/reference.py4
-rw-r--r--git/remote.py31
-rw-r--r--git/repo/base.py12
-rw-r--r--git/util.py22
7 files changed, 62 insertions, 42 deletions
diff --git a/git/objects/commit.py b/git/objects/commit.py
index 26db6e36..0b707450 100644
--- a/git/objects/commit.py
+++ b/git/objects/commit.py
@@ -8,7 +8,7 @@ from gitdb import IStream
from git.util import (
hex_to_bin,
Actor,
- Iterable,
+ IterableObj,
Stats,
finalize_process
)
@@ -47,7 +47,7 @@ log.addHandler(logging.NullHandler())
__all__ = ('Commit', )
-class Commit(base.Object, Iterable, Diffable, Traversable, Serializable):
+class Commit(base.Object, IterableObj, Diffable, Traversable, Serializable):
"""Wraps a git Commit object.
diff --git a/git/objects/submodule/base.py b/git/objects/submodule/base.py
index 8cf4dd1e..57396a46 100644
--- a/git/objects/submodule/base.py
+++ b/git/objects/submodule/base.py
@@ -3,7 +3,6 @@ from io import BytesIO
import logging
import os
import stat
-from typing import List
from unittest import SkipTest
import uuid
@@ -27,7 +26,7 @@ from git.exc import (
from git.objects.base import IndexObject, Object
from git.objects.util import Traversable
from git.util import (
- Iterable,
+ IterableObj,
join_path_native,
to_native_path_linux,
RemoteProgress,
@@ -47,6 +46,15 @@ from .util import (
)
+# typing ----------------------------------------------------------------------
+
+from typing import TYPE_CHECKING
+
+if TYPE_CHECKING:
+ from git.util import IterableList
+
+# -----------------------------------------------------------------------------
+
__all__ = ["Submodule", "UpdateProgress"]
@@ -74,7 +82,7 @@ UPDWKTREE = UpdateProgress.UPDWKTREE
# IndexObject comes via util module, its a 'hacky' fix thanks to pythons import
# mechanism which cause plenty of trouble of the only reason for packages and
# modules is refactoring - subpackages shouldn't depend on parent packages
-class Submodule(IndexObject, Iterable, Traversable):
+class Submodule(IndexObject, IterableObj, Traversable):
"""Implements access to a git submodule. They are special in that their sha
represents a commit in the submodule's repository which is to be checked out
@@ -136,12 +144,12 @@ class Submodule(IndexObject, Iterable, Traversable):
# END handle attribute name
@classmethod
- def _get_intermediate_items(cls, item: 'Submodule') -> List['Submodule']: # type: ignore
+ def _get_intermediate_items(cls, item: 'Submodule') -> IterableList['Submodule']:
""":return: all the submodules of our module repository"""
try:
return cls.list_items(item.module())
except InvalidGitRepositoryError:
- return []
+ return IterableList('')
# END handle intermediate items
@classmethod
@@ -1163,7 +1171,7 @@ class Submodule(IndexObject, Iterable, Traversable):
:raise IOError: If the .gitmodules file/blob could not be read"""
return self._config_parser_constrained(read_only=True)
- def children(self):
+ def children(self) -> IterableList['Submodule']:
"""
:return: IterableList(Submodule, ...) an iterable list of submodules instances
which are children of this submodule or 0 if the submodule is not checked out"""
diff --git a/git/objects/util.py b/git/objects/util.py
index 087f0166..a565cf42 100644
--- a/git/objects/util.py
+++ b/git/objects/util.py
@@ -19,11 +19,11 @@ import calendar
from datetime import datetime, timedelta, tzinfo
# typing ------------------------------------------------------------
-from typing import (Any, Callable, Deque, Iterator, Sequence, TYPE_CHECKING, Tuple, Type, Union, cast, overload)
+from typing import (Any, Callable, Deque, Iterator, TYPE_CHECKING, Tuple, Type, Union, cast)
if TYPE_CHECKING:
from io import BytesIO, StringIO
- from .submodule.base import Submodule
+ from .submodule.base import Submodule # noqa: F401
from .commit import Commit
from .blob import Blob
from .tag import TagObject
@@ -284,6 +284,7 @@ class Traversable(object):
"""
__slots__ = ()
+ """
@overload
@classmethod
def _get_intermediate_items(cls, item: 'Commit') -> Tuple['Commit', ...]:
@@ -303,10 +304,10 @@ class Traversable(object):
@classmethod
def _get_intermediate_items(cls, item: 'Traversable') -> Tuple['Traversable', ...]:
...
+ """
@classmethod
- def _get_intermediate_items(cls, item: 'Traversable'
- ) -> Sequence['Traversable']:
+ def _get_intermediate_items(cls, item):
"""
Returns:
Tuple of items connected to the given item.
@@ -322,7 +323,7 @@ class Traversable(object):
"""
:return: IterableList with the results of the traversal as produced by
traverse()"""
- out = IterableList(self._id_attribute_) # type: ignore[attr-defined] # defined in sublcasses
+ out: IterableList = IterableList(self._id_attribute_) # type: ignore[attr-defined] # defined in sublcasses
out.extend(self.traverse(*args, **kwargs))
return out
diff --git a/git/refs/reference.py b/git/refs/reference.py
index 9014f555..8a9b0487 100644
--- a/git/refs/reference.py
+++ b/git/refs/reference.py
@@ -1,6 +1,6 @@
from git.util import (
LazyMixin,
- Iterable,
+ IterableObj,
)
from .symbolic import SymbolicReference
@@ -23,7 +23,7 @@ def require_remote_ref_path(func):
#}END utilities
-class Reference(SymbolicReference, LazyMixin, Iterable):
+class Reference(SymbolicReference, LazyMixin, IterableObj):
"""Represents a named reference to any object. Subclasses may apply restrictions though,
i.e. Heads can only point to commits."""
diff --git a/git/remote.py b/git/remote.py
index 6ea4b2a1..a85297c1 100644
--- a/git/remote.py
+++ b/git/remote.py
@@ -13,7 +13,7 @@ from git.compat import (defenc, force_text)
from git.exc import GitCommandError
from git.util import (
LazyMixin,
- Iterable,
+ IterableObj,
IterableList,
RemoteProgress,
CallableRemoteProgress,
@@ -107,7 +107,7 @@ def to_progress_instance(progress: Union[Callable[..., Any], RemoteProgress, Non
return progress
-class PushInfo(object):
+class PushInfo(IterableObj, object):
"""
Carries information about the result of a push operation of a single head::
@@ -220,7 +220,7 @@ class PushInfo(object):
return PushInfo(flags, from_ref, to_ref_string, remote, old_commit, summary)
-class FetchInfo(object):
+class FetchInfo(IterableObj, object):
"""
Carries information about the results of a fetch operation of a single head::
@@ -421,7 +421,7 @@ class FetchInfo(object):
return cls(remote_local_ref, flags, note, old_commit, local_remote_ref)
-class Remote(LazyMixin, Iterable):
+class Remote(LazyMixin, IterableObj):
"""Provides easy read and write access to a git remote.
@@ -580,18 +580,18 @@ class Remote(LazyMixin, Iterable):
raise ex
@property
- def refs(self) -> IterableList:
+ def refs(self) -> IterableList[RemoteReference]:
"""
:return:
IterableList of RemoteReference objects. It is prefixed, allowing
you to omit the remote path portion, i.e.::
remote.refs.master # yields RemoteReference('/refs/remotes/origin/master')"""
- out_refs = IterableList(RemoteReference._id_attribute_, "%s/" % self.name)
+ out_refs: IterableList[RemoteReference] = IterableList(RemoteReference._id_attribute_, "%s/" % self.name)
out_refs.extend(RemoteReference.list_items(self.repo, remote=self.name))
return out_refs
@property
- def stale_refs(self) -> IterableList:
+ def stale_refs(self) -> IterableList[Reference]:
"""
:return:
IterableList RemoteReference objects that do not have a corresponding
@@ -606,7 +606,7 @@ class Remote(LazyMixin, Iterable):
as well. This is a fix for the issue described here:
https://github.com/gitpython-developers/GitPython/issues/260
"""
- out_refs = IterableList(RemoteReference._id_attribute_, "%s/" % self.name)
+ out_refs: IterableList[RemoteReference] = IterableList(RemoteReference._id_attribute_, "%s/" % self.name)
for line in self.repo.git.remote("prune", "--dry-run", self).splitlines()[2:]:
# expecting
# * [would prune] origin/new_branch
@@ -681,11 +681,12 @@ class Remote(LazyMixin, Iterable):
return self
def _get_fetch_info_from_stderr(self, proc: TBD,
- progress: Union[Callable[..., Any], RemoteProgress, None]) -> IterableList:
+ progress: Union[Callable[..., Any], RemoteProgress, None]
+ ) -> IterableList['FetchInfo']:
progress = to_progress_instance(progress)
# skip first line as it is some remote info we are not interested in
- output = IterableList('name')
+ output: IterableList['FetchInfo'] = IterableList('name')
# lines which are no progress are fetch info lines
# this also waits for the command to finish
@@ -741,7 +742,7 @@ class Remote(LazyMixin, Iterable):
return output
def _get_push_info(self, proc: TBD,
- progress: Union[Callable[..., Any], RemoteProgress, None]) -> IterableList:
+ progress: Union[Callable[..., Any], RemoteProgress, None]) -> IterableList[PushInfo]:
progress = to_progress_instance(progress)
# read progress information from stderr
@@ -749,7 +750,7 @@ class Remote(LazyMixin, Iterable):
# read the lines manually as it will use carriage returns between the messages
# to override the previous one. This is why we read the bytes manually
progress_handler = progress.new_message_handler()
- output = IterableList('push_infos')
+ output: IterableList[PushInfo] = IterableList('push_infos')
def stdout_handler(line: str) -> None:
try:
@@ -785,7 +786,7 @@ class Remote(LazyMixin, Iterable):
def fetch(self, refspec: Union[str, List[str], None] = None,
progress: Union[Callable[..., Any], None] = None,
- verbose: bool = True, **kwargs: Any) -> IterableList:
+ verbose: bool = True, **kwargs: Any) -> IterableList[FetchInfo]:
"""Fetch the latest changes for this remote
:param refspec:
@@ -832,7 +833,7 @@ class Remote(LazyMixin, Iterable):
def pull(self, refspec: Union[str, List[str], None] = None,
progress: Union[Callable[..., Any], None] = None,
- **kwargs: Any) -> IterableList:
+ **kwargs: Any) -> IterableList[FetchInfo]:
"""Pull changes from the given branch, being the same as a fetch followed
by a merge of branch with your local branch.
@@ -853,7 +854,7 @@ class Remote(LazyMixin, Iterable):
def push(self, refspec: Union[str, List[str], None] = None,
progress: Union[Callable[..., Any], None] = None,
- **kwargs: Any) -> IterableList:
+ **kwargs: Any) -> IterableList[PushInfo]:
"""Push changes from source branch in refspec to target branch in refspec.
:param refspec: see 'fetch' method
diff --git a/git/repo/base.py b/git/repo/base.py
index 77947731..52727504 100644
--- a/git/repo/base.py
+++ b/git/repo/base.py
@@ -309,7 +309,7 @@ class Repo(object):
return self._bare
@property
- def heads(self) -> 'IterableList':
+ def heads(self) -> 'IterableList[Head]':
"""A list of ``Head`` objects representing the branch heads in
this repo
@@ -317,7 +317,7 @@ class Repo(object):
return Head.list_items(self)
@property
- def references(self) -> 'IterableList':
+ def references(self) -> 'IterableList[Reference]':
"""A list of Reference objects representing tags, heads and remote references.
:return: IterableList(Reference, ...)"""
@@ -342,7 +342,7 @@ class Repo(object):
return HEAD(self, 'HEAD')
@property
- def remotes(self) -> 'IterableList':
+ def remotes(self) -> 'IterableList[Remote]':
"""A list of Remote objects allowing to access and manipulate remotes
:return: ``git.IterableList(Remote, ...)``"""
return Remote.list_items(self)
@@ -358,13 +358,13 @@ class Repo(object):
#{ Submodules
@property
- def submodules(self) -> 'IterableList':
+ def submodules(self) -> 'IterableList[Submodule]':
"""
:return: git.IterableList(Submodule, ...) of direct submodules
available from the current head"""
return Submodule.list_items(self)
- def submodule(self, name: str) -> 'IterableList':
+ def submodule(self, name: str) -> 'Submodule':
""" :return: Submodule with the given name
:raise ValueError: If no such submodule exists"""
try:
@@ -396,7 +396,7 @@ class Repo(object):
#}END submodules
@property
- def tags(self) -> 'IterableList':
+ def tags(self) -> 'IterableList[TagReference]':
"""A list of ``Tag`` objects that are available in this repo
:return: ``git.IterableList(TagReference, ...)`` """
return TagReference.list_items(self)
diff --git a/git/util.py b/git/util.py
index 516c315c..5f184b7a 100644
--- a/git/util.py
+++ b/git/util.py
@@ -22,7 +22,7 @@ from urllib.parse import urlsplit, urlunsplit
# typing ---------------------------------------------------------
from typing import (Any, AnyStr, BinaryIO, Callable, Dict, Generator, IO, Iterator, List,
- Optional, Pattern, Sequence, Tuple, Union, cast, TYPE_CHECKING, overload)
+ Optional, Pattern, Sequence, Tuple, TypeVar, Union, cast, TYPE_CHECKING, overload)
import pathlib
@@ -920,7 +920,10 @@ class BlockingLockFile(LockFile):
# END endless loop
-class IterableList(list):
+T = TypeVar('T', bound='IterableObj')
+
+
+class IterableList(List[T]):
"""
List of iterable objects allowing to query an object by id or by named index::
@@ -930,6 +933,9 @@ class IterableList(list):
heads['master']
heads[0]
+ Iterable parent objects = [Commit, SubModule, Reference, FetchInfo, PushInfo]
+ Iterable via inheritance = [Head, TagReference, RemoteReference]
+ ]
It requires an id_attribute name to be set which will be queried from its
contained items to have a means for comparison.
@@ -938,7 +944,7 @@ class IterableList(list):
can be left out."""
__slots__ = ('_id_attr', '_prefix')
- def __new__(cls, id_attr: str, prefix: str = '') -> 'IterableList':
+ def __new__(cls, id_attr: str, prefix: str = '') -> 'IterableList[IterableObj]':
return super(IterableList, cls).__new__(cls)
def __init__(self, id_attr: str, prefix: str = '') -> None:
@@ -1015,7 +1021,7 @@ class Iterable(object):
_id_attribute_ = "attribute that most suitably identifies your instance"
@classmethod
- def list_items(cls, repo: 'Repo', *args: Any, **kwargs: Any) -> 'IterableList':
+ def list_items(cls, repo: 'Repo', *args: Any, **kwargs: Any) -> IterableList['IterableObj']:
"""
Find all items of this type - subclasses can specify args and kwargs differently.
If no args are given, subclasses are obliged to return all items if no additional
@@ -1024,12 +1030,12 @@ class Iterable(object):
:note: Favor the iter_items method as it will
:return:list(Item,...) list of item instances"""
- out_list = IterableList(cls._id_attribute_)
+ out_list: IterableList = IterableList(cls._id_attribute_)
out_list.extend(cls.iter_items(repo, *args, **kwargs))
return out_list
@classmethod
- def iter_items(cls, repo: 'Repo', *args: Any, **kwargs: Any) -> Iterator[TBD]:
+ def iter_items(cls, repo: 'Repo', *args: Any, **kwargs: Any) -> Iterator:
# return typed to be compatible with subtypes e.g. Remote
"""For more information about the arguments, see list_items
:return: iterator yielding Items"""
@@ -1038,6 +1044,10 @@ class Iterable(object):
#} END classes
+class IterableObj(Iterable):
+ pass
+
+
class NullHandler(logging.Handler):
def emit(self, record: object) -> None:
pass