Skip to content

Commit 57ed51a

Browse files
committed
Fixed #487 - Add spdx_license_key support
* Update changelog/tests Signed-off-by: Chin Yeung Li <[email protected]>
1 parent 0c47a6b commit 57ed51a

File tree

9 files changed

+62
-34
lines changed

9 files changed

+62
-34
lines changed

CHANGELOG.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
* Add new option to choose extract license from ScanCode LicenseDB or DJC License Library
1515
* Add ability to transform Excel formatted file
1616
* Support Excel file format for `inventory`, `gen` and `attrib`
17+
* Add 'spdx_license_key' support
1718

1819
2021-04-02
1920
Release 6.0.0

src/attributecode/api.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,4 @@ def get_license_details_from_api(api_url, api_key, license_key):
9999
Missing values are provided as empty strings.
100100
"""
101101
license_data, errors = request_license_data(api_url, api_key, license_key)
102-
license_name = license_data.get('short_name', '')
103-
license_text = license_data.get('full_text', '')
104-
license_key = license_data.get('key', '')
105-
return license_name, license_key, license_text, errors
102+
return license_data, errors

src/attributecode/gen.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -333,22 +333,27 @@ def generate(location, base_dir, android=None, reference_dir=None, fetch_license
333333
licenses_dict = {}
334334
if gen_license:
335335
# Write generated LICENSE file
336-
license_key_name_context_url_list = about.dump_lic(dump_loc, license_dict)
336+
license_key_name_context_url_list, err = about.dump_lic(dump_loc, license_dict)
337+
if err:
338+
errors.append(err)
337339
if license_key_name_context_url_list:
338-
for lic_key, lic_name, lic_filename, lic_context, lic_url in license_key_name_context_url_list:
339-
licenses_dict[lic_key] = [lic_name, lic_filename, lic_context, lic_url]
340+
for lic_key, lic_name, lic_filename, lic_context, lic_url, spdx_lic_key in license_key_name_context_url_list:
341+
licenses_dict[lic_key] = [lic_name, lic_filename, lic_context, lic_url, spdx_lic_key]
340342
if not lic_name in about.license_name.value:
341343
about.license_name.value.append(lic_name)
342344
about.license_file.value[lic_filename] = lic_filename
343345
if not lic_url in about.license_url.value:
344346
about.license_url.value.append(lic_url)
345-
347+
if not spdx_lic_key in about.spdx_license_key.value:
348+
about.spdx_license_key.value.append(spdx_lic_key)
346349
if about.license_name.value:
347350
about.license_name.present = True
348351
if about.license_file.value:
349352
about.license_file.present = True
350353
if about.license_url.value:
351354
about.license_url.present = True
355+
if about.spdx_license_key.value:
356+
about.spdx_license_key.present = True
352357

353358
about.dump(dump_loc, licenses_dict)
354359

src/attributecode/model.py

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,7 @@ def set_standard_fields(self):
777777
('license_name', ListField()),
778778
('license_file', FileTextField()),
779779
('license_url', UrlListField()),
780+
('spdx_license_key', ListField()),
780781
('copyright', StringField()),
781782
('notice_file', FileTextField()),
782783
('notice_url', UrlField()),
@@ -1035,7 +1036,7 @@ def load_dict(self, fields_dict, base_dir, scancode=False, from_attrib=False, ru
10351036
continue
10361037
if key == u'licenses':
10371038
# FIXME: use a license object instead
1038-
lic_key, lic_name, lic_file, lic_url, lic_score = ungroup_licenses(value)
1039+
lic_key, lic_name, lic_file, lic_url, spdx_lic_key, lic_score = ungroup_licenses(value)
10391040
if lic_key:
10401041
fields.append(('license_key', lic_key))
10411042
if lic_name:
@@ -1044,6 +1045,10 @@ def load_dict(self, fields_dict, base_dir, scancode=False, from_attrib=False, ru
10441045
fields.append(('license_file', lic_file))
10451046
if lic_url:
10461047
fields.append(('license_url', lic_url))
1048+
if lic_url:
1049+
fields.append(('license_url', lic_url))
1050+
if spdx_lic_key:
1051+
fields.append(('spdx_license_key', spdx_lic_key))
10471052
# The license score is a key from scancode license scan
10481053
if lic_score:
10491054
fields.append(('license_score', lic_score))
@@ -1085,6 +1090,7 @@ def dumps(self, licenses_dict=None):
10851090
license_name = []
10861091
license_file = []
10871092
license_url = []
1093+
spdx_license_key = []
10881094
bool_fields = ['redistribute', 'attribute', 'track_changes', 'modified', 'internal_use_only']
10891095
for field in self.all_fields():
10901096
if not field.value and not field.name in bool_fields:
@@ -1119,6 +1125,8 @@ def dumps(self, licenses_dict=None):
11191125
license_file = list(field.value.keys())
11201126
elif field.name == 'license_url' and field.value:
11211127
license_url = field.value
1128+
elif field.name == 'spdx_license_key' and field.value:
1129+
spdx_license_key = field.value
11221130
elif field.name in file_fields and field.value:
11231131
data[field.name] = field.original_value
11241132
elif field.name in bool_fields and not field.value == None:
@@ -1136,14 +1144,12 @@ def dumps(self, licenses_dict=None):
11361144
lic_dict = {}
11371145
if licenses_dict and lic_key in licenses_dict:
11381146
lic_dict['key'] = lic_key
1139-
lic_name, lic_filename, lic_context, lic_url = licenses_dict[lic_key]
1140-
#lic_name = licenses_dict[lic_key][0]
1141-
#lic_url = licenses_dict[lic_key][2]
1142-
#lic_file = lic_key + '.LICENSE'
1147+
lic_name, lic_filename, lic_context, lic_url, spdx_lic_key = licenses_dict[lic_key]
11431148

11441149
lic_dict['name'] = lic_name
11451150
lic_dict['file'] = lic_filename
11461151
lic_dict['url'] = lic_url
1152+
lic_dict['spdx_license_key'] = spdx_lic_key
11471153

11481154
# Remove the license information if it has been handled
11491155
lic_key_copy.remove(lic_key)
@@ -1156,7 +1162,7 @@ def dumps(self, licenses_dict=None):
11561162
lic_dict_list.append(lic_dict)
11571163

11581164
# Handle license information that have not been handled.
1159-
license_group = list(zip_longest(lic_key_copy, license_name, license_file, license_url))
1165+
license_group = list(zip_longest(lic_key_copy, license_name, license_file, license_url, spdx_license_key))
11601166
for lic_group in license_group:
11611167
lic_dict = {}
11621168
if lic_group[0]:
@@ -1171,6 +1177,8 @@ def dumps(self, licenses_dict=None):
11711177
lic_dict['file'] = lic_group[2]
11721178
if lic_group[3]:
11731179
lic_dict['url'] = lic_group[3]
1180+
if lic_group[4]:
1181+
lic_dict['spdx_license_key'] = lic_group[4]
11741182
lic_dict_list.append(lic_dict)
11751183

11761184
# Format the license information in the same order of the license expression
@@ -1267,6 +1275,7 @@ def dump_lic(self, location, license_dict):
12671275
loc = util.to_posix(location)
12681276
parent = posixpath.dirname(loc)
12691277
license_key_name_context_url = []
1278+
err = ''
12701279

12711280
if not posixpath.exists(parent):
12721281
os.makedirs(add_unc(parent))
@@ -1282,16 +1291,15 @@ def dump_lic(self, location, license_dict):
12821291
license_path = posixpath.join(parent, lic_key)
12831292
license_path += u'.LICENSE'
12841293
license_path = add_unc(license_path)
1285-
license_name, license_filename, license_context, license_url = license_dict[lic_key]
1286-
license_info = (lic_key, license_name, license_filename, license_context, license_url)
1294+
license_name, license_filename, license_context, license_url, spdx_license_key = license_dict[lic_key]
1295+
license_info = (lic_key, license_name, license_filename, license_context, license_url, spdx_license_key)
12871296
license_key_name_context_url.append(license_info)
12881297
with io.open(license_path, mode='w', encoding='utf-8', newline='\n', errors='replace') as lic:
12891298
lic.write(license_context)
12901299
except Exception as e:
1291-
# TODO: it should return error if exception caught
1292-
pass
1300+
err = str(e)
12931301

1294-
return license_key_name_context_url
1302+
return license_key_name_context_url, err
12951303

12961304

12971305
def collect_inventory(location):
@@ -1593,9 +1601,14 @@ def pre_process_and_fetch_license_dict(abouts, api_url=None, api_key=None, scanc
15931601
license_name = ''
15941602
license_filename = ''
15951603
license_text = ''
1604+
spdx_license_key = ''
15961605
detail_list = []
15971606
if api_key:
1598-
license_name, _license_key, license_text, errs = api.get_license_details_from_api(url, api_key, lic_key)
1607+
license_data, errs = api.get_license_details_from_api(url, api_key, lic_key)
1608+
license_name = license_data.get('short_name', '')
1609+
license_text = license_data.get('full_text', '')
1610+
license_key = license_data.get('key', '')
1611+
spdx_license_key = license_data.get('spdx_license_key', '')
15991612
for severity, message in errs:
16001613
msg = (about.about_file_path + ": " + message)
16011614
errors.append(Error(severity, msg))
@@ -1611,6 +1624,7 @@ def pre_process_and_fetch_license_dict(abouts, api_url=None, api_key=None, scanc
16111624
license_text = urllib.request.urlopen(license_text_url).read().decode('utf-8')
16121625
license_filename = data['key'] + '.LICENSE'
16131626
lic_url = url + license_filename
1627+
spdx_license_key = data['spdx_license_key']
16141628
except:
16151629
msg = about.about_file_path + u" : Invalid 'license': " + lic_key
16161630
errors.append(Error(ERROR, msg))
@@ -1619,6 +1633,7 @@ def pre_process_and_fetch_license_dict(abouts, api_url=None, api_key=None, scanc
16191633
detail_list.append(license_filename)
16201634
detail_list.append(license_text)
16211635
detail_list.append(lic_url)
1636+
detail_list.append(spdx_license_key)
16221637
key_text_dict[lic_key] = detail_list
16231638
if not about.license_key.value:
16241639
about.license_key.value = lic_list

src/attributecode/util.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,7 @@ def ungroup_licenses(licenses):
470470
lic_name = []
471471
lic_file = []
472472
lic_url = []
473+
spdx_lic_key = []
473474
lic_score = []
474475
for lic in licenses:
475476
if 'key' in lic:
@@ -480,9 +481,11 @@ def ungroup_licenses(licenses):
480481
lic_file.append(lic['file'])
481482
if 'url' in lic:
482483
lic_url.append(lic['url'])
484+
if 'spdx_license_key' in lic:
485+
spdx_lic_key.append(lic['spdx_license_key'])
483486
if 'score' in lic:
484487
lic_score.append(lic['score'])
485-
return lic_key, lic_name, lic_file, lic_url, lic_score
488+
return lic_key, lic_name, lic_file, lic_url, spdx_lic_key, lic_score
486489

487490

488491
# FIXME: add docstring

tests/test_api.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,7 @@ def test_api_get_license_details_from_api(self, request_license_data):
4444
errors = []
4545
request_license_data.return_value = license_data, errors
4646

47-
expected = (
48-
'Apache 2.0',
49-
'apache-2.0',
50-
'Apache License Version 2.0 ...',
51-
[])
47+
expected = ({'short_name': 'Apache 2.0', 'full_text': 'Apache License Version 2.0 ...', 'key': 'apache-2.0'}, [])
5248
result = api.get_license_details_from_api(
5349
api_url='api_url', api_key='api_key', license_key='license_key')
5450
assert expected == result

tests/test_gen.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,8 @@ def test_generate_license_key_with_custom_file_450_with_fetch(self):
301301
lic_dict = {u'public-domain': [u'Public Domain',
302302
u'public-domain.LICENSE',
303303
u'This component is released to the public domain by the author.',
304-
u'https://enterprise.dejacode.com/urn/?urn=urn:dje:license:public-domain'
304+
u'https://enterprise.dejacode.com/urn/?urn=urn:dje:license:public-domain',
305+
u''
305306
]}
306307
a = abouts[0]
307308
a.license_key.value.append('public-domain')
@@ -316,6 +317,7 @@ def test_generate_license_key_with_custom_file_450_with_fetch(self):
316317
name: Public Domain
317318
file: public-domain.LICENSE
318319
url: https://enterprise.dejacode.com/urn/?urn=urn:dje:license:public-domain
320+
spdx_license_key:
319321
- key: custom
320322
name: custom
321323
file: custom.txt
@@ -332,7 +334,8 @@ def test_generate_license_key_with_custom_file_450_with_fetch_with_order(self):
332334
lic_dict = {u'public-domain': [u'Public Domain',
333335
u'public-domain.LICENSE',
334336
u'This component is released to the public domain by the author.',
335-
u'https://enterprise.dejacode.com/urn/?urn=urn:dje:license:public-domain'
337+
u'https://enterprise.dejacode.com/urn/?urn=urn:dje:license:public-domain',
338+
u''
336339
]}
337340
# The first row from the test file
338341
a = abouts[0]
@@ -354,6 +357,7 @@ def test_generate_license_key_with_custom_file_450_with_fetch_with_order(self):
354357
name: Public Domain
355358
file: public-domain.LICENSE
356359
url: https://enterprise.dejacode.com/urn/?urn=urn:dje:license:public-domain
360+
spdx_license_key:
357361
- key: custom
358362
name: custom
359363
file: custom.txt
@@ -372,6 +376,7 @@ def test_generate_license_key_with_custom_file_450_with_fetch_with_order(self):
372376
name: Public Domain
373377
file: public-domain.LICENSE
374378
url: https://enterprise.dejacode.com/urn/?urn=urn:dje:license:public-domain
379+
spdx_license_key:
375380
'''
376381
)
377382
assert expected1 == result1

tests/test_model.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -690,8 +690,8 @@ def test_load_dict_issue_433(self):
690690
'license_expression': 'license1 AND license2',
691691
'notice_file': 'package1.zip.NOTICE',
692692
'licenses': [
693-
{'key': 'license1', 'name': 'License1', 'file': 'license1.LICENSE', 'url': 'some_url'},
694-
{'key': 'license2', 'name': 'License2', 'file': 'license2.LICENSE', 'url': 'some_url'},
693+
{'key': 'license1', 'name': 'License1', 'file': 'license1.LICENSE', 'url': 'some_url', 'spdx_license_key': 'key'},
694+
{'key': 'license2', 'name': 'License2', 'file': 'license2.LICENSE', 'url': 'some_url', 'spdx_license_key': 'key'},
695695
],
696696
}
697697
about = model.About()
@@ -708,12 +708,14 @@ def test_load_dict_issue_433(self):
708708
name: License1
709709
file: license1.LICENSE
710710
url: some_url
711+
spdx_license_key: key
711712
- key: license2
712713
name: License2
713714
file: license2.LICENSE
714715
url: some_url
716+
spdx_license_key: key
715717
'''
716-
lic_dict = {u'license1': [u'License1', u'license1.LICENSE',u'', u'some_url'], u'license2' : [u'License2', u'license2.LICENSE', u'', u'some_url']}
718+
lic_dict = {u'license1': [u'License1', u'license1.LICENSE',u'', u'some_url', 'key'], u'license2' : [u'License2', u'license2.LICENSE', u'', u'some_url', 'key']}
717719
assert about.dumps(lic_dict) == expected
718720

719721

tests/test_util.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -556,24 +556,28 @@ def test_ungroup_licenses(self):
556556
(u'key', u'mit'),
557557
(u'name', u'MIT License'),
558558
(u'file', u'mit.LICENSE'),
559-
(u'url', u'https://enterprise.dejacode.com/urn/?urn=urn:dje:license:mit')]),
559+
(u'url', u'https://enterprise.dejacode.com/urn/?urn=urn:dje:license:mit'),
560+
(u'spdx_license_key', u'MIT')]),
560561
dict([
561562
(u'key', u'bsd-new'),
562563
(u'name', u'BSD-3-Clause'),
563564
(u'file', u'bsd-new.LICENSE'),
564-
(u'url', u'https://enterprise.dejacode.com/urn/?urn=urn:dje:license:bsd-new')])
565+
(u'url', u'https://enterprise.dejacode.com/urn/?urn=urn:dje:license:bsd-new'),
566+
(u'spdx_license_key', u'BSD-3-Clause')])
565567
]
566568
expected_lic_key = [u'mit', u'bsd-new']
567569
expected_lic_name = [u'MIT License', u'BSD-3-Clause']
568570
expected_lic_file = [u'mit.LICENSE', u'bsd-new.LICENSE']
569571
expected_lic_url = [
570572
u'https://enterprise.dejacode.com/urn/?urn=urn:dje:license:mit',
571573
u'https://enterprise.dejacode.com/urn/?urn=urn:dje:license:bsd-new']
572-
lic_key, lic_name, lic_file, lic_url, lic_score = util.ungroup_licenses(about)
574+
expected_spdx = [u'MIT', u'BSD-3-Clause']
575+
lic_key, lic_name, lic_file, lic_url, spdx_lic_key, lic_score = util.ungroup_licenses(about)
573576
assert expected_lic_key == lic_key
574577
assert expected_lic_name == lic_name
575578
assert expected_lic_file == lic_file
576579
assert expected_lic_url == lic_url
580+
assert expected_spdx == spdx_lic_key
577581

578582
def test_unique_does_deduplicate_and_keep_ordering(self):
579583
items = ['a', 'b', 'd', 'b', 'c', 'a']

0 commit comments

Comments
 (0)