5
5
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
6
6
"""Module for general utility functions"""
7
7
8
+ from abc import abstractmethod
9
+ import warnings
8
10
from git .util import (
9
11
IterableList ,
10
12
IterableObj ,
23
25
from typing import (Any , Callable , Deque , Iterator , NamedTuple , overload , Sequence ,
24
26
TYPE_CHECKING , Tuple , Type , TypeVar , Union , cast )
25
27
26
- from git .types import Has_id_attribute , Literal
28
+ from git .types import Has_id_attribute , Literal , Protocol , runtime_checkable
27
29
28
30
if TYPE_CHECKING :
29
31
from io import BytesIO , StringIO
@@ -289,7 +291,8 @@ def __getattr__(self, attr: str) -> Any:
289
291
return getattr (self ._stream , attr )
290
292
291
293
292
- class Traversable (object ):
294
+ @runtime_checkable
295
+ class Traversable (Protocol ):
293
296
294
297
"""Simple interface to perform depth-first or breadth-first traversals
295
298
into one direction.
@@ -301,6 +304,7 @@ class Traversable(object):
301
304
__slots__ = ()
302
305
303
306
@classmethod
307
+ @abstractmethod
304
308
def _get_intermediate_items (cls , item ) -> Sequence ['Traversable' ]:
305
309
"""
306
310
Returns:
@@ -313,7 +317,18 @@ class Tree:: (cls, Tree) -> Tuple[Tree, ...]
313
317
"""
314
318
raise NotImplementedError ("To be implemented in subclass" )
315
319
316
- def list_traverse (self , * args : Any , ** kwargs : Any ) -> IterableList [Union ['Commit' , 'Submodule' , 'Tree' , 'Blob' ]]:
320
+ @abstractmethod
321
+ def list_traverse (self , * args : Any , ** kwargs : Any ) -> Any :
322
+ """ """
323
+ warnings .warn ("list_traverse() method should only be called from subclasses."
324
+ "Calling from Traversable abstract class will raise NotImplementedError in 3.1.20"
325
+ "Builtin sublclasses are 'Submodule', 'Tree' and 'Commit" ,
326
+ DeprecationWarning ,
327
+ stacklevel = 2 )
328
+ return self ._list_traverse (* args , ** kwargs )
329
+
330
+ def _list_traverse (self , as_edge = False , * args : Any , ** kwargs : Any
331
+ ) -> IterableList [Union ['Commit' , 'Submodule' , 'Tree' , 'Blob' ]]:
317
332
"""
318
333
:return: IterableList with the results of the traversal as produced by
319
334
traverse()
@@ -329,22 +344,34 @@ def list_traverse(self, *args: Any, **kwargs: Any) -> IterableList[Union['Commit
329
344
id = "" # shouldn't reach here, unless Traversable subclass created with no _id_attribute_
330
345
# could add _id_attribute_ to Traversable, or make all Traversable also Iterable?
331
346
332
- out : IterableList [Union ['Commit' , 'Submodule' , 'Tree' , 'Blob' ]] = IterableList (id )
333
- # overloads in subclasses (mypy does't allow typing self: subclass)
334
- # Union[IterableList['Commit'], IterableList['Submodule'], IterableList[Union['Submodule', 'Tree', 'Blob']]]
335
-
336
- # NOTE: if is_edge=True, self.traverse returns a Tuple, so should be prevented or flattened?
337
- kwargs ['as_edge' ] = False
338
- out .extend (self .traverse (* args , ** kwargs )) # type: ignore
339
- return out
340
-
341
- def traverse (self ,
342
- predicate : Callable [[Union ['Traversable' , 'Blob' , TraversedTup ], int ], bool ] = lambda i , d : True ,
343
- prune : Callable [[Union ['Traversable' , 'Blob' , TraversedTup ], int ], bool ] = lambda i , d : False ,
344
- depth : int = - 1 , branch_first : bool = True , visit_once : bool = True ,
345
- ignore_self : int = 1 , as_edge : bool = False
346
- ) -> Union [Iterator [Union ['Traversable' , 'Blob' ]],
347
- Iterator [TraversedTup ]]:
347
+ if not as_edge :
348
+ out : IterableList [Union ['Commit' , 'Submodule' , 'Tree' , 'Blob' ]] = IterableList (id )
349
+ out .extend (self .traverse (as_edge = as_edge , * args , ** kwargs )) # type: ignore
350
+ return out
351
+ # overloads in subclasses (mypy does't allow typing self: subclass)
352
+ # Union[IterableList['Commit'], IterableList['Submodule'], IterableList[Union['Submodule', 'Tree', 'Blob']]]
353
+ else :
354
+ # Raise deprecationwarning, doesn't make sense to use this
355
+ out_list : IterableList = IterableList (self .traverse (* args , ** kwargs ))
356
+ return out_list
357
+
358
+ @ abstractmethod
359
+ def traverse (self , * args : Any , ** kwargs ) -> Any :
360
+ """ """
361
+ warnings .warn ("traverse() method should only be called from subclasses."
362
+ "Calling from Traversable abstract class will raise NotImplementedError in 3.1.20"
363
+ "Builtin sublclasses are 'Submodule', 'Tree' and 'Commit" ,
364
+ DeprecationWarning ,
365
+ stacklevel = 2 )
366
+ return self ._traverse (* args , ** kwargs )
367
+
368
+ def _traverse (self ,
369
+ predicate : Callable [[Union ['Traversable' , 'Blob' , TraversedTup ], int ], bool ] = lambda i , d : True ,
370
+ prune : Callable [[Union ['Traversable' , 'Blob' , TraversedTup ], int ], bool ] = lambda i , d : False ,
371
+ depth : int = - 1 , branch_first : bool = True , visit_once : bool = True ,
372
+ ignore_self : int = 1 , as_edge : bool = False
373
+ ) -> Union [Iterator [Union ['Traversable' , 'Blob' ]],
374
+ Iterator [TraversedTup ]]:
348
375
""":return: iterator yielding of items found when traversing self
349
376
:param predicate: f(i,d) returns False if item i at depth d should not be included in the result
350
377
@@ -435,32 +462,35 @@ def addToStack(stack: Deque[TraverseNT],
435
462
# END for each item on work stack
436
463
437
464
438
- class Serializable (object ):
465
+ @ runtime_checkable
466
+ class Serializable (Protocol ):
439
467
440
468
"""Defines methods to serialize and deserialize objects from and into a data stream"""
441
469
__slots__ = ()
442
470
471
+ # @abstractmethod
443
472
def _serialize (self , stream : 'BytesIO' ) -> 'Serializable' :
444
473
"""Serialize the data of this object into the given data stream
445
474
:note: a serialized object would ``_deserialize`` into the same object
446
475
:param stream: a file-like object
447
476
:return: self"""
448
477
raise NotImplementedError ("To be implemented in subclass" )
449
478
479
+ # @abstractmethod
450
480
def _deserialize (self , stream : 'BytesIO' ) -> 'Serializable' :
451
481
"""Deserialize all information regarding this object from the stream
452
482
:param stream: a file-like object
453
483
:return: self"""
454
484
raise NotImplementedError ("To be implemented in subclass" )
455
485
456
486
457
- class TraversableIterableObj (Traversable , IterableObj ):
487
+ class TraversableIterableObj (IterableObj , Traversable ):
458
488
__slots__ = ()
459
489
460
490
TIobj_tuple = Tuple [Union [T_TIobj , None ], T_TIobj ]
461
491
462
- def list_traverse (self : T_TIobj , * args : Any , ** kwargs : Any ) -> IterableList [T_TIobj ]: # type: ignore[override]
463
- return super (TraversableIterableObj , self ).list_traverse (* args , ** kwargs )
492
+ def list_traverse (self : T_TIobj , * args : Any , ** kwargs : Any ) -> IterableList [T_TIobj ]:
493
+ return super (TraversableIterableObj , self )._list_traverse (* args , ** kwargs )
464
494
465
495
@ overload # type: ignore
466
496
def traverse (self : T_TIobj ,
@@ -522,6 +552,6 @@ def is_commit_traversed(inp: Tuple) -> TypeGuard[Tuple[Iterator[Tuple['Commit',
522
552
"""
523
553
return cast (Union [Iterator [T_TIobj ],
524
554
Iterator [Tuple [Union [None , T_TIobj ], T_TIobj ]]],
525
- super (TraversableIterableObj , self ).traverse (
555
+ super (TraversableIterableObj , self )._traverse (
526
556
predicate , prune , depth , branch_first , visit_once , ignore_self , as_edge # type: ignore
527
557
))
0 commit comments