|
4 | 4 | # This module is part of GitPython and is released under |
5 | 5 | # the BSD License: http://www.opensource.org/licenses/bsd-license.php |
6 | 6 | """Module for general utility functions""" |
| 7 | + |
| 8 | + |
7 | 9 | from git.util import ( |
8 | 10 | IterableList, |
9 | 11 | Actor |
|
18 | 20 | from datetime import datetime, timedelta, tzinfo |
19 | 21 |
|
20 | 22 | # typing ------------------------------------------------------------ |
21 | | -from typing import Any, IO, TYPE_CHECKING, Tuple, Type, Union, cast |
| 23 | +from typing import Any, Callable, IO, Iterator, Sequence, TYPE_CHECKING, Tuple, Type, Union, cast, overload |
22 | 24 |
|
23 | 25 | if TYPE_CHECKING: |
| 26 | + from .submodule.base import Submodule |
24 | 27 | from .commit import Commit |
25 | 28 | from .blob import Blob |
26 | 29 | from .tag import TagObject |
@@ -115,7 +118,7 @@ def verify_utctz(offset: str) -> str: |
115 | 118 |
|
116 | 119 |
|
117 | 120 | class tzoffset(tzinfo): |
118 | | - |
| 121 | + |
119 | 122 | def __init__(self, secs_west_of_utc: float, name: Union[None, str] = None) -> None: |
120 | 123 | self._offset = timedelta(seconds=-secs_west_of_utc) |
121 | 124 | self._name = name or 'fixed' |
@@ -275,29 +278,61 @@ class Traversable(object): |
275 | 278 | """Simple interface to perform depth-first or breadth-first traversals |
276 | 279 | into one direction. |
277 | 280 | Subclasses only need to implement one function. |
278 | | - Instances of the Subclass must be hashable""" |
| 281 | + Instances of the Subclass must be hashable |
| 282 | +
|
| 283 | + Defined subclasses = [Commit, Tree, SubModule] |
| 284 | + """ |
279 | 285 | __slots__ = () |
280 | 286 |
|
| 287 | + @overload |
| 288 | + @classmethod |
| 289 | + def _get_intermediate_items(cls, item: 'Commit') -> Tuple['Commit', ...]: |
| 290 | + ... |
| 291 | + |
| 292 | + @overload |
281 | 293 | @classmethod |
282 | | - def _get_intermediate_items(cls, item): |
| 294 | + def _get_intermediate_items(cls, item: 'Submodule') -> Tuple['Submodule', ...]: |
| 295 | + ... |
| 296 | + |
| 297 | + @overload |
| 298 | + @classmethod |
| 299 | + def _get_intermediate_items(cls, item: 'Tree') -> Tuple['Tree', ...]: |
| 300 | + ... |
| 301 | + |
| 302 | + @overload |
| 303 | + @classmethod |
| 304 | + def _get_intermediate_items(cls, item: 'Traversable') -> Tuple['Traversable', ...]: |
| 305 | + ... |
| 306 | + |
| 307 | + @classmethod |
| 308 | + def _get_intermediate_items(cls, item: 'Traversable' |
| 309 | + ) -> Sequence['Traversable']: |
283 | 310 | """ |
284 | 311 | Returns: |
285 | | - List of items connected to the given item. |
| 312 | + Tuple of items connected to the given item. |
286 | 313 | Must be implemented in subclass |
| 314 | +
|
| 315 | + class Commit:: (cls, Commit) -> Tuple[Commit, ...] |
| 316 | + class Submodule:: (cls, Submodule) -> Iterablelist[Submodule] |
| 317 | + class Tree:: (cls, Tree) -> Tuple[Tree, ...] |
287 | 318 | """ |
288 | 319 | raise NotImplementedError("To be implemented in subclass") |
289 | 320 |
|
290 | | - def list_traverse(self, *args, **kwargs): |
| 321 | + def list_traverse(self, *args: Any, **kwargs: Any) -> IterableList: |
291 | 322 | """ |
292 | 323 | :return: IterableList with the results of the traversal as produced by |
293 | 324 | traverse()""" |
294 | | - out = IterableList(self._id_attribute_) |
| 325 | + out = IterableList(self._id_attribute_) # type: ignore[attr-defined] # defined in sublcasses |
295 | 326 | out.extend(self.traverse(*args, **kwargs)) |
296 | 327 | return out |
297 | 328 |
|
298 | | - def traverse(self, predicate=lambda i, d: True, |
299 | | - prune=lambda i, d: False, depth=-1, branch_first=True, |
300 | | - visit_once=True, ignore_self=1, as_edge=False): |
| 329 | + def traverse(self, |
| 330 | + predicate: Callable[[object, int], bool] = lambda i, d: True, |
| 331 | + prune: Callable[[object, int], bool] = lambda i, d: False, |
| 332 | + depth: int = -1, |
| 333 | + branch_first: bool = True, |
| 334 | + visit_once: bool = True, ignore_self: int = 1, as_edge: bool = False |
| 335 | + ) -> Union[Iterator['Traversable'], Iterator[Tuple['Traversable', 'Traversable']]]: |
301 | 336 | """:return: iterator yielding of items found when traversing self |
302 | 337 |
|
303 | 338 | :param predicate: f(i,d) returns False if item i at depth d should not be included in the result |
@@ -329,13 +364,16 @@ def traverse(self, predicate=lambda i, d: True, |
329 | 364 | destination, i.e. tuple(src, dest) with the edge spanning from |
330 | 365 | source to destination""" |
331 | 366 | visited = set() |
332 | | - stack = Deque() |
| 367 | + stack = Deque() # type: Deque[Tuple[int, Traversable, Union[Traversable, None]]] |
333 | 368 | stack.append((0, self, None)) # self is always depth level 0 |
334 | 369 |
|
335 | | - def addToStack(stack, item, branch_first, depth): |
| 370 | + def addToStack(stack: Deque[Tuple[int, 'Traversable', Union['Traversable', None]]], |
| 371 | + item: 'Traversable', |
| 372 | + branch_first: bool, |
| 373 | + depth) -> None: |
336 | 374 | lst = self._get_intermediate_items(item) |
337 | 375 | if not lst: |
338 | | - return |
| 376 | + return None |
339 | 377 | if branch_first: |
340 | 378 | stack.extendleft((depth, i, item) for i in lst) |
341 | 379 | else: |
|
0 commit comments