From 2b768c700103a80789dff93dcb36b9530d303fd3 Mon Sep 17 00:00:00 2001 From: Eliah Kagan Date: Sat, 23 Dec 2023 07:06:29 -0500 Subject: [PATCH] Shorten Iterable docstrings and put IterableObj first This shortens the git.util.Iterable docstrings, removing most of the text duplicated from git.util.IterableObj docstrings and instead referring the reader to the specific corresponding methods in IterableObj. A comment about return types that appeared in both places but really only documented IterableObj is likewise removed from Iterable. This also reorders the classes, placing IterableObj before Iterable and its associated metaclass. This makes it easier to find, and may help remind users that IterableObj is the class they should use. These changes build on those in dfee31f (#1780). --- git/util.py | 99 +++++++++++++++++++++++++---------------------------- 1 file changed, 46 insertions(+), 53 deletions(-) diff --git a/git/util.py b/git/util.py index 5acc001f7..110961b93 100644 --- a/git/util.py +++ b/git/util.py @@ -1182,54 +1182,37 @@ def __delitem__(self, index: Union[SupportsIndex, int, slice, str]) -> None: list.__delitem__(self, delindex) -class IterableClassWatcher(type): - """Metaclass that issues :class:`DeprecationWarning` when :class:`git.util.Iterable` - is subclassed.""" - - def __init__(cls, name: str, bases: Tuple, clsdict: Dict) -> None: - for base in bases: - if type(base) is IterableClassWatcher: - warnings.warn( - f"GitPython Iterable subclassed by {name}. " - "Iterable is deprecated due to naming clash since v3.1.18" - " and will be removed in 3.1.20, " - "Use IterableObj instead \n", - DeprecationWarning, - stacklevel=2, - ) - - -class Iterable(metaclass=IterableClassWatcher): - """Deprecated, use :class:`IterableObj` instead. - - Defines an interface for iterable items, so there is a uniform way to retrieve +@runtime_checkable +class IterableObj(Protocol): + """Defines an interface for iterable items, so there is a uniform way to retrieve and iterate items within the git repository. + + Subclasses = [Submodule, Commit, Reference, PushInfo, FetchInfo, Remote] """ __slots__ = () - _id_attribute_ = "attribute that most suitably identifies your instance" + _id_attribute_: str @classmethod - def iter_items(cls, repo: "Repo", *args: Any, **kwargs: Any) -> Any: - # return typed to be compatible with subtypes e.g. Remote - """Deprecated, use :class:`IterableObj` instead. - - Find (all) items of this type. + @abstractmethod + def iter_items(cls, repo: "Repo", *args: Any, **kwargs: Any) -> Iterator[T_IterableObj]: + # Return-typed to be compatible with subtypes e.g. Remote. + """Find (all) items of this type. Subclasses can specify ``args`` and ``kwargs`` differently, and may use them for filtering. However, when the method is called with no additional positional or keyword arguments, subclasses are obliged to to yield all items. + For more information about the arguments, see list_items. + :return: Iterator yielding Items """ raise NotImplementedError("To be implemented by Subclass") @classmethod - def list_items(cls, repo: "Repo", *args: Any, **kwargs: Any) -> Any: - """Deprecated, use :class:`IterableObj` instead. - - Find (all) items of this type and collect them into a list. + def list_items(cls, repo: "Repo", *args: Any, **kwargs: Any) -> IterableList[T_IterableObj]: + """Find (all) items of this type and collect them into a list. For more information about the arguments, see :meth:`list_items`. @@ -1239,52 +1222,62 @@ def list_items(cls, repo: "Repo", *args: Any, **kwargs: Any) -> Any: :return: list(Item,...) list of item instances """ - out_list: Any = IterableList(cls._id_attribute_) + out_list: IterableList = IterableList(cls._id_attribute_) out_list.extend(cls.iter_items(repo, *args, **kwargs)) return out_list -@runtime_checkable -class IterableObj(Protocol): - """Defines an interface for iterable items, so there is a uniform way to retrieve - and iterate items within the git repository. +class IterableClassWatcher(type): + """Metaclass that issues :class:`DeprecationWarning` when :class:`git.util.Iterable` + is subclassed.""" - Subclasses = [Submodule, Commit, Reference, PushInfo, FetchInfo, Remote] + def __init__(cls, name: str, bases: Tuple, clsdict: Dict) -> None: + for base in bases: + if type(base) is IterableClassWatcher: + warnings.warn( + f"GitPython Iterable subclassed by {name}. " + "Iterable is deprecated due to naming clash since v3.1.18" + " and will be removed in 3.1.20, " + "Use IterableObj instead \n", + DeprecationWarning, + stacklevel=2, + ) + + +class Iterable(metaclass=IterableClassWatcher): + """Deprecated, use :class:`IterableObj` instead. + + Defines an interface for iterable items, so there is a uniform way to retrieve + and iterate items within the git repository. """ __slots__ = () - _id_attribute_: str + _id_attribute_ = "attribute that most suitably identifies your instance" @classmethod - @abstractmethod - def iter_items(cls, repo: "Repo", *args: Any, **kwargs: Any) -> Iterator[T_IterableObj]: - # Return-typed to be compatible with subtypes e.g. Remote. - """Find (all) items of this type. + def iter_items(cls, repo: "Repo", *args: Any, **kwargs: Any) -> Any: + """Deprecated, use :class:`IterableObj` instead. - Subclasses can specify ``args`` and ``kwargs`` differently, and may use them for - filtering. However, when the method is called with no additional positional or - keyword arguments, subclasses are obliged to to yield all items. + Find (all) items of this type. - For more information about the arguments, see list_items. + See :meth:`IterableObj.list_items` for details on usage. :return: Iterator yielding Items """ raise NotImplementedError("To be implemented by Subclass") @classmethod - def list_items(cls, repo: "Repo", *args: Any, **kwargs: Any) -> IterableList[T_IterableObj]: - """Find (all) items of this type and collect them into a list. + def list_items(cls, repo: "Repo", *args: Any, **kwargs: Any) -> Any: + """Deprecated, use :class:`IterableObj` instead. - For more information about the arguments, see :meth:`list_items`. + Find (all) items of this type and collect them into a list. - :note: Favor the :meth:`iter_items` method as it will avoid eagerly collecting - all items. When there are many items, that can slow performance and increase - memory usage. + See :meth:`IterableObj.list_items` for details on usage. :return: list(Item,...) list of item instances """ - out_list: IterableList = IterableList(cls._id_attribute_) + out_list: Any = IterableList(cls._id_attribute_) out_list.extend(cls.iter_items(repo, *args, **kwargs)) return out_list