2020
2121# typing -------------------------------------------------
2222
23- from typing import Iterable ,Iterator ,Tuple ,Union ,cast ,TYPE_CHECKING
23+ from typing import Callable ,Dict ,Iterable ,Iterator ,List ,Tuple ,Type ,Union ,cast ,TYPE_CHECKING
24+
25+ from git .types import PathLike
2426
2527if TYPE_CHECKING :
28+ from git .repo import Repo
2629from io import BytesIO
2730
2831#--------------------------------------------------------
2932
3033
31- cmp = lambda a ,b : (a > b )- (a < b )
34+ cmp : Callable [[ int , int ], int ] = lambda a ,b : (a > b )- (a < b )
3235
3336__all__ = ("TreeModifier" ,"Tree" )
3437
3538
36- def git_cmp (t1 ,t2 ) :
39+ def git_cmp (t1 : 'Tree' ,t2 : 'Tree' ) -> int :
3740a ,b = t1 [2 ],t2 [2 ]
3841len_a ,len_b = len (a ),len (b )
3942min_len = min (len_a ,len_b )
@@ -45,9 +48,9 @@ def git_cmp(t1, t2):
4548return len_a - len_b
4649
4750
48- def merge_sort (a ,cmp ) :
51+ def merge_sort (a : List [ int ] ,cmp : Callable [[ int , int ], int ]) -> None :
4952if len (a )< 2 :
50- return
53+ return None
5154
5255mid = len (a )// 2
5356lefthalf = a [:mid ]
@@ -182,29 +185,29 @@ class Tree(IndexObject, diff.Diffable, util.Traversable, util.Serializable):
182185symlink_id = 0o12
183186tree_id = 0o04
184187
185- _map_id_to_type = {
188+ _map_id_to_type : Dict [ int , Union [ Type [ Submodule ], Type [ Blob ], Type [ 'Tree' ]]] = {
186189commit_id :Submodule ,
187190blob_id :Blob ,
188191symlink_id :Blob
189192# tree id added once Tree is defined
190193 }
191194
192- def __init__ (self ,repo ,binsha ,mode = tree_id << 12 ,path = None ):
195+ def __init__ (self ,repo : 'Repo' ,binsha : bytes ,mode : int = tree_id << 12 ,path : Union [ PathLike , None ] = None ):
193196super (Tree ,self ).__init__ (repo ,binsha ,mode ,path )
194197
195198@classmethod
196199def _get_intermediate_items (cls ,index_object :'Tree' ,# type: ignore
197- )-> Tuple ['Tree' , ...]:
200+ )-> Union [ Tuple ['Tree' , ...], Tuple [()] ]:
198201if index_object .type == "tree" :
199202index_object = cast ('Tree' ,index_object )
200203return tuple (index_object ._iter_convert_to_object (index_object ._cache ))
201204return ()
202205
203- def _set_cache_ (self ,attr ) :
206+ def _set_cache_ (self ,attr : str ) -> None :
204207if attr == "_cache" :
205208# Set the data when we need it
206209ostream = self .repo .odb .stream (self .binsha )
207- self ._cache = tree_entries_from_data (ostream .read ())
210+ self ._cache : List [ Tuple [ bytes , int , str ]] = tree_entries_from_data (ostream .read ())
208211else :
209212super (Tree ,self )._set_cache_ (attr )
210213# END handle attribute
@@ -221,7 +224,7 @@ def _iter_convert_to_object(self, iterable: Iterable[Tuple[bytes, int, str]]
221224raise TypeError ("Unknown mode %o found in tree data for path '%s'" % (mode ,path ))from e
222225# END for each item
223226
224- def join (self ,file ) :
227+ def join (self ,file : str ) -> Union [ Blob , 'Tree' , Submodule ] :
225228"""Find the named object in this tree's contents
226229 :return: ``git.Blob`` or ``git.Tree`` or ``git.Submodule``
227230
@@ -254,26 +257,22 @@ def join(self, file):
254257raise KeyError (msg % file )
255258# END handle long paths
256259
257- def __div__ (self ,file ):
258- """For PY2 only"""
259- return self .join (file )
260-
261- def __truediv__ (self ,file ):
260+ def __truediv__ (self ,file :str )-> Union ['Tree' ,Blob ,Submodule ]:
262261"""For PY3 only"""
263262return self .join (file )
264263
265264@property
266- def trees (self ):
265+ def trees (self )-> List [ 'Tree' ] :
267266""":return: list(Tree, ...) list of trees directly below this tree"""
268267return [i for i in self if i .type == "tree" ]
269268
270269@property
271- def blobs (self ):
270+ def blobs (self )-> List [ 'Blob' ] :
272271""":return: list(Blob, ...) list of blobs directly below this tree"""
273272return [i for i in self if i .type == "blob" ]
274273
275274@property
276- def cache (self ):
275+ def cache (self )-> TreeModifier :
277276"""
278277 :return: An object allowing to modify the internal cache. This can be used
279278 to change the tree's contents. When done, make sure you call ``set_done``
@@ -289,16 +288,16 @@ def traverse(self, predicate=lambda i, d: True,
289288return super (Tree ,self ).traverse (predicate ,prune ,depth ,branch_first ,visit_once ,ignore_self )
290289
291290# List protocol
292- def __getslice__ (self ,i ,j ) :
291+ def __getslice__ (self ,i : int ,j : int ) -> List [ Union [ Blob , 'Tree' , Submodule ]] :
293292return list (self ._iter_convert_to_object (self ._cache [i :j ]))
294293
295- def __iter__ (self ):
294+ def __iter__ (self )-> Iterator [ Union [ Blob , 'Tree' , Submodule ]] :
296295return self ._iter_convert_to_object (self ._cache )
297296
298- def __len__ (self ):
297+ def __len__ (self )-> int :
299298return len (self ._cache )
300299
301- def __getitem__ (self ,item ) :
300+ def __getitem__ (self ,item : Union [ str , int , slice ]) -> Union [ Blob , 'Tree' , Submodule ] :
302301if isinstance (item ,int ):
303302info = self ._cache [item ]
304303return self ._map_id_to_type [info [1 ]>> 12 ](self .repo ,info [0 ],info [1 ],join_path (self .path ,info [2 ]))
@@ -310,7 +309,7 @@ def __getitem__(self, item):
310309
311310raise TypeError ("Invalid index type: %r" % item )
312311
313- def __contains__ (self ,item ) :
312+ def __contains__ (self ,item : Union [ IndexObject , PathLike ]) -> bool :
314313if isinstance (item ,IndexObject ):
315314for info in self ._cache :
316315if item .binsha == info [0 ]:
@@ -321,10 +320,11 @@ def __contains__(self, item):
321320# compatibility
322321
323322# treat item as repo-relative path
324- path = self .path
325- for info in self ._cache :
326- if item == join_path (path ,info [2 ]):
327- return True
323+ else :
324+ path = self .path
325+ for info in self ._cache :
326+ if item == join_path (path ,info [2 ]):
327+ return True
328328# END for each item
329329return False
330330