Skip to content

Commit 5459956

Browse files
authored
Merge pull request #85 from nexB/83-add-copyright-diff
Add Copyright class and copyright_diff() #82 #83
2 parents 5338a3c + 4199bcd commit 5459956

58 files changed

Lines changed: 4133 additions & 65 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/deltacode/__init__.py

Lines changed: 53 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ def __init__(self, new_path, old_path, options):
5757
self.determine_delta()
5858
self.determine_moved()
5959
self.license_diff()
60+
self.copyright_diff()
6061
# Sort deltas by score, descending, i.e., high > low.
6162
self.deltas.sort(key=lambda Delta: Delta.score, reverse=True)
6263

@@ -191,28 +192,57 @@ def license_diff(self):
191192
attribute -- if there has been a license change and depending on the
192193
nature of that change.
193194
"""
194-
for i in self.deltas:
195-
if 20 <= i.score < 100:
195+
for delta in self.deltas:
196+
if 20 <= delta.score < 100:
196197

197-
new_licenses = i.new_file.licenses or []
198-
old_licenses = i.old_file.licenses or []
198+
new_licenses = delta.new_file.licenses or []
199+
old_licenses = delta.old_file.licenses or []
199200

200-
if len(i.new_file.licenses) > 0 and i.old_file.licenses == []:
201-
i.factors.append('license info added')
202-
i.score += 20
201+
if len(delta.new_file.licenses) > 0 and delta.old_file.licenses == []:
202+
delta.update(20, 'license info added')
203203
return
204204

205-
if i.new_file.licenses == [] and len(i.old_file.licenses) > 0:
206-
i.factors.append('license info removed')
207-
i.score += 15
205+
if delta.new_file.licenses == [] and len(delta.old_file.licenses) > 0:
206+
delta.update(15, 'license info removed')
208207
return
209208

210-
new_keys = set(l.key for l in new_licenses)
211-
old_keys = set(l.key for l in old_licenses)
209+
new_keys = set(license.key for license in new_licenses)
210+
old_keys = set(license.key for license in old_licenses)
212211

213212
if new_keys != old_keys:
214-
i.factors.append('license change')
215-
i.score += 10
213+
delta.update(10, 'license change')
214+
215+
def copyright_diff(self):
216+
"""
217+
Compare the copyright details for a pair of 'new' and 'old' File objects
218+
in a Delta object and change the Delta object's 'score' attribute --
219+
and add an appropriate category (e.g., 'copyright info removed', 'copyright
220+
info added' or 'copyright change') to the Delta object's 'factors'
221+
attribute -- if there has been a copyright change and depending on the
222+
nature of that change.
223+
"""
224+
for delta in self.deltas:
225+
if 20 <= delta.score < 100:
226+
227+
new_copyrights = delta.new_file.copyrights or []
228+
old_copyrights = delta.old_file.copyrights or []
229+
230+
if len(delta.new_file.copyrights) > 0 and delta.old_file.copyrights == []:
231+
delta.update(10, 'copyright info added')
232+
return
233+
elif delta.new_file.copyrights == [] and len(delta.old_file.copyrights) > 0:
234+
delta.update(10, 'copyright info removed')
235+
return
236+
237+
new_statements = set(statement for copyright in new_copyrights for statement in copyright.statements)
238+
old_statements = set(statement for copyright in old_copyrights for statement in copyright.statements)
239+
240+
new_holders = set(holder for copyright in new_copyrights for holder in copyright.holders)
241+
old_holders = set(holder for copyright in old_copyrights for holder in copyright.holders)
242+
243+
if ((new_statements != old_statements) or
244+
(new_holders != old_holders)):
245+
delta.update(5, 'copyright change')
216246

217247
def index_deltas(self, index_key='path', delta_list=[]):
218248
"""
@@ -250,6 +280,15 @@ def __init__(self, score=0, new_file=None, old_file=None):
250280
self.factors = []
251281
self.score = score
252282

283+
def update(self, score=0, factor=''):
284+
"""
285+
Add the score to the Delta object's 'score' attribute and add a string,
286+
summarizing the factor associated with the score, to the object's
287+
'factors' attribute (a list).
288+
"""
289+
self.factors.append(factor)
290+
self.score += score
291+
253292
def to_dict(self):
254293
"""
255294
Return an OrderedDict comprising the 'factors', 'score' and new and old

src/deltacode/models.py

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,13 +161,20 @@ def __init__(self, dictionary={}):
161161
self.sha1 = dictionary.get('sha1', '')
162162
self.original_path = ''
163163
self.licenses = self.get_licenses(dictionary) if dictionary.get('licenses') else []
164+
self.copyrights = self.get_copyrights(dictionary) if dictionary.get('copyrights') else []
164165

165166
def get_licenses(self, dictionary):
166167
if dictionary.get('licenses') == []:
167168
return []
168169
else:
169170
return [License(l) for l in dictionary.get('licenses')]
170171

172+
def get_copyrights(self, dictionary):
173+
if dictionary.get('copyrights') == []:
174+
return []
175+
else:
176+
return [Copyright(l) for l in dictionary.get('copyrights')]
177+
171178
def to_dict(self):
172179
d = OrderedDict([
173180
('path', self.path),
@@ -180,6 +187,13 @@ def to_dict(self):
180187

181188
if self.licenses:
182189
d['licenses'] = [l.to_dict() for l in self.licenses]
190+
else:
191+
d['licenses'] = []
192+
193+
if self.copyrights:
194+
d['copyrights'] = [l.to_dict() for l in self.copyrights]
195+
else:
196+
d['copyrights'] = []
183197

184198
return d
185199

@@ -199,7 +213,8 @@ def __repr__(self):
199213

200214
class License(object):
201215
"""
202-
License object created from the 'license' field in an ABCD formatted 'file' dictionary.
216+
License object created from the 'license' field in an ABCD formatted 'file'
217+
dictionary.
203218
"""
204219
def __init__(self, dictionary={}):
205220
self.key = dictionary.get('key')
@@ -225,7 +240,37 @@ def to_dict(self):
225240

226241
def __repr__(self):
227242
"""
228-
Return string containing a printable representation of the License object.
243+
Return string containing a printable representation of the License
244+
object.
245+
"""
246+
return "%s" % self.__dict__
247+
248+
249+
class Copyright(object):
250+
"""
251+
Copyright object created from the 'copyrights' field in an ABCD formatted
252+
'file' dictionary.
253+
"""
254+
def __init__(self, dictionary={}):
255+
self.statements = dictionary.get('statements')
256+
self.holders = dictionary.get('holders')
257+
258+
def to_dict(self):
259+
"""
260+
Given a Copyright object, return an OrderedDict with the full
261+
set of fields from the ScanCode 'copyrights' value.
262+
"""
263+
d = OrderedDict([
264+
('statements', self.statements),
265+
('holders', self.holders)
266+
])
267+
268+
return d
269+
270+
def __repr__(self):
271+
"""
272+
Return string containing a printable representation of the Copyright
273+
object.
229274
"""
230275
return "%s" % self.__dict__
231276

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Factors,Score,Path,Name,Type,Size,Old Path
2+
modified license info added copyright info added,50,path.txt,path.txt,file,300,
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
{
2+
"scancode_notice": "Generated with ScanCode and provided on an \"AS IS\" BASIS, WITHOUT WARRANTIES\nOR CONDITIONS OF ANY KIND, either express or implied. No content created from\nScanCode should be considered or used as legal advice. Consult an Attorney\nfor any legal advice.\nScanCode is a free software code scanning tool from nexB Inc. and others.\nVisit https://github.com/nexB/scancode-toolkit/ for support and download.",
3+
"scancode_version": "2.1.0",
4+
"scancode_options": {
5+
"--license": true,
6+
"--info": true
7+
},
8+
"files_count": 2,
9+
"files": [
10+
{
11+
"path": "new/default.txt",
12+
"type": "file",
13+
"name": "default.txt",
14+
"size": 100,
15+
"sha1": "a",
16+
"licenses": [],
17+
"copyrights": []
18+
},
19+
{
20+
"path": "new/path.txt",
21+
"type": "file",
22+
"name": "path.txt",
23+
"size": 300,
24+
"sha1": "b_modified",
25+
"licenses": [
26+
{
27+
"key": "gpl-1.0-plus",
28+
"score": 20.0,
29+
"short_name": "GPL 1.0 or later",
30+
"category": "Copyleft",
31+
"owner": "Free Software Foundation (FSF)",
32+
"homepage_url": "http://www.gnu.org/licenses/old-licenses/gpl-1.0-standalone.html",
33+
"text_url": "http://www.gnu.org/licenses/old-licenses/gpl-1.0-standalone.html",
34+
"reference_url": "https://enterprise.dejacode.com/urn/urn:dje:license:gpl-1.0-plus",
35+
"spdx_license_key": "GPL-1.0+",
36+
"spdx_url": "https://spdx.org/licenses/GPL-1.0",
37+
"start_line": 353,
38+
"end_line": 353,
39+
"matched_rule": {
40+
"identifier": "gpl_63.RULE",
41+
"license_choice": false,
42+
"licenses": [
43+
"gpl-1.0-plus"
44+
]
45+
}
46+
}
47+
],
48+
"copyrights": [
49+
{
50+
"statements": [
51+
"Copyright (c) 2016 Mark Adler"
52+
],
53+
"holders": [
54+
"Mark Adler"
55+
],
56+
"authors": [],
57+
"start_line": 1,
58+
"end_line": 3
59+
}
60+
]
61+
}
62+
]
63+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"scancode_notice": "Generated with ScanCode and provided on an \"AS IS\" BASIS, WITHOUT WARRANTIES\nOR CONDITIONS OF ANY KIND, either express or implied. No content created from\nScanCode should be considered or used as legal advice. Consult an Attorney\nfor any legal advice.\nScanCode is a free software code scanning tool from nexB Inc. and others.\nVisit https://github.com/nexB/scancode-toolkit/ for support and download.",
3+
"scancode_version": "2.1.0",
4+
"scancode_options": {
5+
"--license": true,
6+
"--info": true
7+
},
8+
"files_count": 2,
9+
"files": [
10+
{
11+
"path": "old/default.txt",
12+
"type": "file",
13+
"name": "default.txt",
14+
"size": 100,
15+
"sha1": "a",
16+
"licenses": [],
17+
"copyrights": []
18+
},
19+
{
20+
"path": "old/path.txt",
21+
"type": "file",
22+
"name": "path.txt",
23+
"size": 300,
24+
"sha1": "b",
25+
"licenses": [],
26+
"copyrights": []
27+
}
28+
]
29+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Factors,Score,Path,Name,Type,Size,Old Path
2+
modified license info removed copyright info removed,45,path.txt,path.txt,file,300,
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"scancode_notice": "Generated with ScanCode and provided on an \"AS IS\" BASIS, WITHOUT WARRANTIES\nOR CONDITIONS OF ANY KIND, either express or implied. No content created from\nScanCode should be considered or used as legal advice. Consult an Attorney\nfor any legal advice.\nScanCode is a free software code scanning tool from nexB Inc. and others.\nVisit https://github.com/nexB/scancode-toolkit/ for support and download.",
3+
"scancode_version": "2.1.0",
4+
"scancode_options": {
5+
"--license": true,
6+
"--info": true
7+
},
8+
"files_count": 2,
9+
"files": [
10+
{
11+
"path": "new/default.txt",
12+
"type": "file",
13+
"name": "default.txt",
14+
"size": 100,
15+
"sha1": "a",
16+
"licenses": [],
17+
"copyrights": []
18+
},
19+
{
20+
"path": "new/path.txt",
21+
"type": "file",
22+
"name": "path.txt",
23+
"size": 300,
24+
"sha1": "b_modified",
25+
"licenses": [],
26+
"copyrights": []
27+
}
28+
]
29+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
{
2+
"scancode_notice": "Generated with ScanCode and provided on an \"AS IS\" BASIS, WITHOUT WARRANTIES\nOR CONDITIONS OF ANY KIND, either express or implied. No content created from\nScanCode should be considered or used as legal advice. Consult an Attorney\nfor any legal advice.\nScanCode is a free software code scanning tool from nexB Inc. and others.\nVisit https://github.com/nexB/scancode-toolkit/ for support and download.",
3+
"scancode_version": "2.1.0",
4+
"scancode_options": {
5+
"--license": true,
6+
"--info": true
7+
},
8+
"files_count": 2,
9+
"files": [
10+
{
11+
"path": "old/default.txt",
12+
"type": "file",
13+
"name": "default.txt",
14+
"size": 100,
15+
"sha1": "a",
16+
"licenses": [],
17+
"copyrights": []
18+
},
19+
{
20+
"path": "old/path.txt",
21+
"type": "file",
22+
"name": "path.txt",
23+
"size": 300,
24+
"sha1": "b",
25+
"licenses": [
26+
{
27+
"key": "gpl-1.0-plus",
28+
"score": 20.0,
29+
"short_name": "GPL 1.0 or later",
30+
"category": "Copyleft",
31+
"owner": "Free Software Foundation (FSF)",
32+
"homepage_url": "http://www.gnu.org/licenses/old-licenses/gpl-1.0-standalone.html",
33+
"text_url": "http://www.gnu.org/licenses/old-licenses/gpl-1.0-standalone.html",
34+
"reference_url": "https://enterprise.dejacode.com/urn/urn:dje:license:gpl-1.0-plus",
35+
"spdx_license_key": "GPL-1.0+",
36+
"spdx_url": "https://spdx.org/licenses/GPL-1.0",
37+
"start_line": 353,
38+
"end_line": 353,
39+
"matched_rule": {
40+
"identifier": "gpl_63.RULE",
41+
"license_choice": false,
42+
"licenses": [
43+
"gpl-1.0-plus"
44+
]
45+
}
46+
}
47+
],
48+
"copyrights": [
49+
{
50+
"statements": [
51+
"Copyright (c) 2016 Mark Adler"
52+
],
53+
"holders": [
54+
"Mark Adler"
55+
],
56+
"authors": [],
57+
"start_line": 1,
58+
"end_line": 3
59+
}
60+
]
61+
}
62+
]
63+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Factors,Score,Path,Name,Type,Size,Old Path
2+
modified copyright change,25,path.txt,path.txt,file,300,

0 commit comments

Comments
 (0)