77
88class LazyMixin (object ):
99 lazy_properties = []
10+ __slots__ = tuple ()
1011
11- __slots__ = "__baked__"
12-
13- def __init__ (self ):
14- self .__baked__ = False
15-
16- def __getattribute__ (self , attr ):
17- val = object .__getattribute__ (self , attr )
18- if val is not None :
19- return val
20- else :
21- self .__prebake__ ()
22- return object .__getattribute__ (self , attr )
23-
24- def __bake__ (self ):
25- """ This method should be overridden in the derived class. """
26- raise NotImplementedError (" '__bake__' method has not been implemented." )
27-
28- def __prebake__ (self ):
29- if self .__baked__ :
30- return
31- self .__bake__ ()
32- self .__baked__ = True
12+ def __getattr__ (self , attr ):
13+ """
14+ Whenever an attribute is requested that we do not know, we allow it
15+ to be created and set. Next time the same attribute is reqeusted, it is simply
16+ returned from our dict/slots.
17+ """
18+ self ._set_cache_ (attr )
19+ # will raise in case the cache was not created
20+ return object .__getattribute__ (self , attr )
3321
34- def __bake_it__ (self ):
35- self .__baked__ = True
22+ def _set_cache_ (self , attr ):
23+ """ This method should be overridden in the derived class.
24+ It should check whether the attribute named by attr can be created
25+ and cached. Do nothing if you do not know the attribute or call your subclass
3626
27+ The derived class may create as many additional attributes as it deems
28+ necessary in case a git command returns more information than represented
29+ in the single attribute."""
30+ pass
31+
3732
3833class Object (LazyMixin ):
3934 """
4035 Implements an Object which may be Blobs, Trees, Commits and Tags
4136 """
4237 TYPES = ("blob" , "tree" , "commit" , "tag" )
43- __slots__ = ("repo" , "id" , "size" , "_data_cached " )
38+ __slots__ = ("repo" , "id" , "size" , "data " )
4439 type = None # to be set by subclass
4540
46- def __init__ (self , repo , id , size = None ):
41+ def __init__ (self , repo , id ):
4742 """
4843 Initialize an object by identifying it by its id. All keyword arguments
4944 will be set on demand if None.
@@ -53,21 +48,32 @@ def __init__(self, repo, id, size=None):
5348
5449 ``id``
5550 SHA1 or ref suitable for git-rev-parse
56-
57- ``size``
58- Size of the object's data in bytes
5951 """
6052 super (Object ,self ).__init__ ()
6153 self .repo = repo
6254 self .id = id
63- self .size = size
64- self ._data_cached = type (None )
6555
66- def __bake__ (self ):
56+ def _set_self_from_args_ (self , args_dict ):
57+ """
58+ Initialize attributes on self from the given dict that was retrieved
59+ from locals() in the calling method.
60+
61+ Will only set an attribute on self if the corresponding value in args_dict
62+ is not None
63+ """
64+ for attr , val in args_dict .items ():
65+ if attr != "self" and val is not None :
66+ setattr ( self , attr , val )
67+ # END set all non-None attributes
68+
69+ def _set_cache_ (self , attr ):
6770 """
6871 Retrieve object information
6972 """
70- self .size = int (self .repo .git .cat_file (self .id , s = True ).rstrip ())
73+ if attr == "size" :
74+ self .size = int (self .repo .git .cat_file (self .id , s = True ).rstrip ())
75+ elif attr == "data" :
76+ self .data = self .repo .git .cat_file (self .id , p = True , with_raw_output = True )
7177
7278 def __eq__ (self , other ):
7379 """
@@ -105,18 +111,12 @@ def __repr__(self):
105111 return '<git.%s "%s">' % (self .__class__ .__name__ , self .id )
106112
107113 @property
108- def data (self ):
114+ def id_abbrev (self ):
109115 """
110- The binary contents of this object.
111-
112116 Returns
113- str
114-
115- NOTE
116- The data will be cached after the first access.
117+ First 7 bytes of the commit's sha id as an abbreviation of the full string.
117118 """
118- self ._data_cached = ( self ._data_cached is not type (None ) and self ._data_cached ) or self .repo .git .cat_file (self .id , p = True , with_raw_output = True )
119- return self ._data_cached
119+ return self .id [0 :7 ]
120120
121121 @classmethod
122122 def get_type_by_name (cls , object_type_name ):
@@ -154,7 +154,7 @@ class IndexObject(Object):
154154 """
155155 __slots__ = ("path" , "mode" )
156156
157- def __init__ (self , repo , id , mode = None , path = None , size = None ):
157+ def __init__ (self , repo , id , mode = None , path = None ):
158158 """
159159 Initialize a newly instanced IndexObject
160160 ``repo``
@@ -169,14 +169,11 @@ def __init__(self, repo, id, mode=None, path=None, size = None):
169169 ``path`` : str
170170 is the path to the file in the file system, relative to the git repository root, i.e.
171171 file.ext or folder/other.ext
172-
173- ``size`` : int
174- size of the object data in bytes
175172 """
176- super (IndexObject , self ).__init__ (repo , id , size )
173+ super (IndexObject , self ).__init__ (repo , id )
177174 self .mode = mode
178175 self .path = path
179-
176+
180177 @property
181178 def basename (self ):
182179 """
@@ -304,5 +301,6 @@ def from_string(cls, repo, line):
304301 git.Head
305302 """
306303 full_path , hexsha , type_name , object_size = line .split ("\x00 " )
307- obj = Object .get_type_by_name (type_name )(repo , hexsha , object_size )
304+ obj = Object .get_type_by_name (type_name )(repo , hexsha )
305+ obj .size = object_size
308306 return cls (full_path , obj )
0 commit comments