@@ -56,7 +56,7 @@ def __init__(self, new_path, old_path, options):
5656 if self .new .path != '' and self .old .path != '' :
5757 self .determine_delta ()
5858 self .determine_moved ()
59- # TODO: how can we test the sort order?
59+ self . license_diff ()
6060 # Sort deltas by score, descending, i.e., high > low.
6161 self .deltas .sort (key = lambda Delta : Delta .score , reverse = True )
6262
@@ -77,8 +77,8 @@ def align_scans(self):
7777
7878 def determine_delta (self ):
7979 """
80- Add to a list of Delta objects that can be sorted by their attributes,
81- e.g., by Delta.score. Return None if no File objects can be loaded
80+ Add to a list of Delta objects that can be sorted by their attributes,
81+ e.g., by Delta.score. Return None if no File objects can be loaded
8282 from either scan.
8383 """
8484 # align scan and create our index
@@ -95,13 +95,15 @@ def determine_delta(self):
9595
9696 if new_file .type != 'file' :
9797 continue
98-
98+
9999 new_visited += 1
100100
101101 try :
102102 delta_old_files = old_index [path ]
103103 except KeyError :
104- self .deltas .append (Delta (new_file , None , 'added' ))
104+ delta = Delta (100 , new_file , None )
105+ delta .factors .append ('added' )
106+ self .deltas .append (delta )
105107 continue
106108
107109 # at this point, we have a delta_old_file.
@@ -110,25 +112,30 @@ def determine_delta(self):
110112 for f in delta_old_files :
111113 # TODO: make sure sha1 is NOT empty
112114 if new_file .sha1 == f .sha1 :
113- self .deltas .append (Delta (new_file , f , 'unmodified' ))
115+ delta = Delta (0 , new_file , f )
116+ delta .factors .append ('unmodified' )
117+ self .deltas .append (delta )
114118 continue
115119 else :
116- delta = Delta (new_file , f , 'modified' )
120+ delta = Delta (20 , new_file , f )
121+ delta .factors .append ('modified' )
117122 self .deltas .append (delta )
118123
119124 # now time to find the added.
120125 for path , old_files in old_index .items ():
121126 for old_file in old_files :
122127 if old_file .type != 'file' :
123128 continue
124-
129+
125130 old_visited += 1
126131
127132 try :
128133 # This file already classified so do nothing
129134 new_index [path ]
130135 except KeyError :
131- self .deltas .append (Delta (None , old_file , 'removed' ))
136+ delta = Delta (10 , None , old_file )
137+ delta .factors .append ('removed' )
138+ self .deltas .append (delta )
132139 continue
133140
134141 # make sure everything is accounted for
@@ -149,10 +156,11 @@ def determine_moved(self):
149156 by their 'sha1' attribute, identifying any unique pairs of Deltas in
150157 both indices with the same 'sha1' and File 'name' attributes, and
151158 converting each such pair of 'added' and 'removed' Delta objects to a
152- 'moved' Delta object.
159+ 'moved' Delta object. The 'added' and 'removed' indices are defined by
160+ the 'score' attribute of the Delta objects.
153161 """
154- added = self .index_deltas ('sha1' , [i for i in self .deltas if i .category == 'added' ])
155- removed = self .index_deltas ('sha1' , [i for i in self .deltas if i .category == 'removed' ])
162+ added = self .index_deltas ('sha1' , [i for i in self .deltas if i .score == 100 ])
163+ removed = self .index_deltas ('sha1' , [i for i in self .deltas if i .score == 10 ])
156164
157165 # TODO: should it be iteritems() or items()
158166 for added_sha1 , added_deltas in added .iteritems ():
@@ -165,28 +173,61 @@ def determine_moved(self):
165173 def update_deltas (self , added , removed ):
166174 """
167175 Convert the matched 'added' and 'removed' Delta objects to a combined
168- 'moved' Delta object and delete the 'added' and 'removed' objects.
176+ 'moved' Delta object -- passing the appropriate 'score' during object
177+ creation -- and delete the 'added' and 'removed' objects.
169178 """
170- self .deltas .append (Delta (added .new_file , removed .old_file , 'moved' ))
179+ delta = Delta (5 , added .new_file , removed .old_file )
180+ delta .factors .append ('moved' )
181+ self .deltas .append (delta )
171182 self .deltas .remove (added )
172183 self .deltas .remove (removed )
173184
185+ def license_diff (self ):
186+ """
187+ Compare the license details for a pair of 'new' and 'old' File objects
188+ in a Delta object and change the Delta object's 'score' attribute --
189+ and add an appropriate category (e.g., 'license info removed', 'license
190+ info added' or 'license change') to the Delta object's 'factors'
191+ attribute -- if there has been a license change and depending on the
192+ nature of that change.
193+ """
194+ for i in self .deltas :
195+ if 20 <= i .score < 100 :
196+
197+ new_licenses = i .new_file .licenses or []
198+ old_licenses = i .old_file .licenses or []
199+
200+ if len (i .new_file .licenses ) > 0 and i .old_file .licenses == []:
201+ i .factors .append ('license info added' )
202+ i .score += 20
203+ return
204+
205+ if i .new_file .licenses == [] and len (i .old_file .licenses ) > 0 :
206+ i .factors .append ('license info removed' )
207+ i .score += 15
208+ return
209+
210+ new_keys = set (l .key for l in new_licenses )
211+ old_keys = set (l .key for l in old_licenses )
212+
213+ if new_keys != old_keys :
214+ i .factors .append ('license change' )
215+ i .score += 10
216+
174217 def index_deltas (self , index_key = 'path' , delta_list = []):
175218 """
176219 Return a dictionary of a list of Delta objects indexed by the key
177220 passed via the 'index_key' variable. If no 'index_key' variable is
178221 passed, the dict is keyed by the Delta object's 'path' variable. For a
179- 'removed' Delta object, use the variable from the 'old_file'; for all
180- other Delta objects (e.g., 'added'), use the 'new_file'. This function
181- does not currently catch the AttributeError exception.
222+ 'removed' Delta object -- identified by its 'score' attribute -- use
223+ the variable from the 'old_file'; for all other Delta objects (e.g.,
224+ 'added'), use the 'new_file'. This function does not currently catch
225+ the AttributeError exception.
182226 """
183227 index = {}
184228
185229 for delta in delta_list :
186- if delta .category == 'removed' :
187- key = getattr (delta .old_file , index_key )
188- else :
189- key = getattr (delta .new_file , index_key )
230+ key = getattr (delta .new_file if delta .new_file else delta .old_file , index_key )
190231
191232 if index .get (key ) is None :
192233 index [key ] = []
@@ -196,111 +237,37 @@ def index_deltas(self, index_key='path', delta_list=[]):
196237
197238 return index
198239
199- def get_stats (self ):
200- """
201- Given a list of Delta objects, return a 'counts' dictionary keyed by
202- the Delta object's 'category' attribute that contains the count as a
203- value for each category.
204- """
205- added , modified , moved , removed , unmodified = 0 , 0 , 0 , 0 , 0
206-
207- added = len ([i for i in self .deltas if i .category == 'added' ])
208- modified = len ([i for i in self .deltas if i .category == 'modified' ])
209- moved = len ([i for i in self .deltas if i .category == 'moved' ])
210- removed = len ([i for i in self .deltas if i .category == 'removed' ])
211- unmodified = len ([i for i in self .deltas if i .category == 'unmodified' ])
212-
213- return OrderedDict ([('added' , added ), ('modified' , modified ), ('moved' , moved ), ('removed' , removed ), ('unmodified' , unmodified )])
214-
215240
216241class Delta (object ):
217242 """
218243 A tuple reflecting a comparison of two files -- each of which is a File
219- object -- and the category that characterizes the comparison:
220- 'added', 'modified', 'moved', 'removed' or 'unmodified' .
244+ object -- and the 'factors' (e.g., 'added', 'modified' etc.) and related
245+ 'score' that characterize that comparison .
221246 """
222- def __init__ (self , new_file = None , old_file = None , delta_type = None , score = 0 ):
223- self .new_file = new_file if new_file else File ()
224- self .old_file = old_file if old_file else File ()
225- self .category = delta_type if delta_type else ''
247+ def __init__ (self , score = 0 , new_file = None , old_file = None ):
248+ self .new_file = new_file if new_file else None
249+ self .old_file = old_file if old_file else None
250+ self .factors = []
226251 self .score = score
227252
228- # If a license change is detected, and depending on the nature of that change,
229- # change the Delta object's 'category' attribute from 'modified' to
230- # 'license change', 'license info removed' or 'license info added'.
231- if self .category == 'modified' :
232- self ._license_diff ()
233-
234- self .determine_score ()
235-
236- def _license_diff (self , cutoff_score = 50 ):
237- """
238- Compare the license details for a pair of 'new' and 'old' File objects
239- in a Delta object and change the Delta object's 'category' attribute to
240- 'license info removed', 'license info added' or 'license change' if
241- there has been a license change and depending on the nature of that change.
242- """
243- new_licenses = self .new_file .licenses or []
244- old_licenses = self .old_file .licenses or []
245-
246- if len (self .new_file .licenses ) > 0 and self .old_file .licenses == []:
247- self .category = 'license info added'
248- return
249-
250- if self .new_file .licenses == [] and len (self .old_file .licenses ) > 0 :
251- self .category = 'license info removed'
252- return
253-
254- new_keys = set (l .key for l in new_licenses if l .score >= cutoff_score )
255- old_keys = set (l .key for l in old_licenses if l .score >= cutoff_score )
256-
257- if new_keys != old_keys :
258- self .category = 'license change'
259-
260- def determine_score (self ):
261- """
262- Assign a score to each 'Delta' object by modifying the object's 'score'
263- attribute based on the object's 'category' attribute.
264- """
265- scores = {
266- 'added' : 75 ,
267- 'license info added' : 70 ,
268- 'license info removed' : 65 ,
269- 'license change' : 60 ,
270- 'modified' : 50 ,
271- 'removed' : 25 ,
272- 'moved' : 0 ,
273- 'unmodified' : 0
274- }
275-
276- self .score = scores .get (self .category , 0 )
277-
278253 def to_dict (self ):
279254 """
280- Check the 'category' attribute of the Delta object and return an
281- OrderedDict comprising the 'category', 'score' and ' path' of the object.
255+ Return an OrderedDict comprising the 'factors', 'score' and new and old
256+ ' path' attributes of the object.
282257 """
283- delta = OrderedDict ([
284- ('category' , self .category ),
285- ('score' , self .score )
286- ])
287-
288- if self .category == 'added' :
289- delta .update (OrderedDict ([
290- ('new' , self .new_file .to_dict ()),
291- ('old' , None ),
292- ]))
293-
294- elif self .category == 'removed' :
295- delta .update (OrderedDict ([
296- ('new' , None ),
297- ('old' , self .old_file .to_dict ()),
298- ]))
258+ if self .new_file :
259+ new_file = self .new_file .to_dict ()
260+ else :
261+ new_file = None
299262
263+ if self .old_file :
264+ old_file = self .old_file .to_dict ()
300265 else :
301- delta .update (OrderedDict ([
302- ('new' , self .new_file .to_dict ()),
303- ('old' , self .old_file .to_dict ()),
304- ]))
266+ old_file = None
305267
306- return delta
268+ return OrderedDict ([
269+ ('factors' , self .factors ),
270+ ('score' , self .score ),
271+ ('new' , new_file ),
272+ ('old' , old_file ),
273+ ])
0 commit comments