7
7
8
8
class LazyMixin (object ):
9
9
lazy_properties = []
10
+ __slots__ = tuple ()
10
11
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 )
33
21
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
36
26
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
+
37
32
38
33
class Object (LazyMixin ):
39
34
"""
40
35
Implements an Object which may be Blobs, Trees, Commits and Tags
41
36
"""
42
37
TYPES = ("blob" , "tree" , "commit" , "tag" )
43
- __slots__ = ("repo" , "id" , "size" , "_data_cached " )
38
+ __slots__ = ("repo" , "id" , "size" , "data " )
44
39
type = None # to be set by subclass
45
40
46
- def __init__ (self , repo , id , size = None ):
41
+ def __init__ (self , repo , id ):
47
42
"""
48
43
Initialize an object by identifying it by its id. All keyword arguments
49
44
will be set on demand if None.
@@ -53,21 +48,32 @@ def __init__(self, repo, id, size=None):
53
48
54
49
``id``
55
50
SHA1 or ref suitable for git-rev-parse
56
-
57
- ``size``
58
- Size of the object's data in bytes
59
51
"""
60
52
super (Object ,self ).__init__ ()
61
53
self .repo = repo
62
54
self .id = id
63
- self .size = size
64
- self ._data_cached = type (None )
65
55
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 ):
67
70
"""
68
71
Retrieve object information
69
72
"""
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 )
71
77
72
78
def __eq__ (self , other ):
73
79
"""
@@ -105,18 +111,12 @@ def __repr__(self):
105
111
return '<git.%s "%s">' % (self .__class__ .__name__ , self .id )
106
112
107
113
@property
108
- def data (self ):
114
+ def id_abbrev (self ):
109
115
"""
110
- The binary contents of this object.
111
-
112
116
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.
117
118
"""
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 ]
120
120
121
121
@classmethod
122
122
def get_type_by_name (cls , object_type_name ):
@@ -154,7 +154,7 @@ class IndexObject(Object):
154
154
"""
155
155
__slots__ = ("path" , "mode" )
156
156
157
- def __init__ (self , repo , id , mode = None , path = None , size = None ):
157
+ def __init__ (self , repo , id , mode = None , path = None ):
158
158
"""
159
159
Initialize a newly instanced IndexObject
160
160
``repo``
@@ -169,14 +169,11 @@ def __init__(self, repo, id, mode=None, path=None, size = None):
169
169
``path`` : str
170
170
is the path to the file in the file system, relative to the git repository root, i.e.
171
171
file.ext or folder/other.ext
172
-
173
- ``size`` : int
174
- size of the object data in bytes
175
172
"""
176
- super (IndexObject , self ).__init__ (repo , id , size )
173
+ super (IndexObject , self ).__init__ (repo , id )
177
174
self .mode = mode
178
175
self .path = path
179
-
176
+
180
177
@property
181
178
def basename (self ):
182
179
"""
@@ -304,5 +301,6 @@ def from_string(cls, repo, line):
304
301
git.Head
305
302
"""
306
303
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
308
306
return cls (full_path , obj )
0 commit comments