55
55
from attributecode .util import csv
56
56
from attributecode .util import file_fields
57
57
from attributecode .util import filter_errors
58
+ from attributecode .util import get_spdx_key_and_lic_key_from_licdb
58
59
from attributecode .util import is_valid_name
59
60
from attributecode .util import on_windows
60
61
from attributecode .util import norm
@@ -802,6 +803,7 @@ def set_standard_fields(self):
802
803
('license_name' , ListField ()),
803
804
('license_file' , FileTextField ()),
804
805
('license_url' , UrlListField ()),
806
+ ('spdx_license_expression' , StringField ()),
805
807
('spdx_license_key' , ListField ()),
806
808
('copyright' , StringField ()),
807
809
('notice_file' , FileTextField ()),
@@ -1222,6 +1224,13 @@ def dumps(self, licenses_dict=None):
1222
1224
else :
1223
1225
if field .value :
1224
1226
data [field .name ] = field .value
1227
+ # If there is no license_key value, parse the license_expression
1228
+ # and get the parsed license key
1229
+ if 'license_expression' in data :
1230
+ if not license_key and data ['license_expression' ]:
1231
+ _spec_char , lic_list = parse_license_expression (
1232
+ data ['license_expression' ])
1233
+ license_key = lic_list
1225
1234
1226
1235
# Group the same license information in a list
1227
1236
# This `licenses_dict` is a dictionary with license key as the key and the
@@ -1244,20 +1253,35 @@ def dumps(self, licenses_dict=None):
1244
1253
lic_dict ['spdx_license_key' ] = spdx_lic_key
1245
1254
1246
1255
# Remove the license information if it has been handled
1247
- lic_key_copy .remove (lic_key )
1248
- if lic_name in license_name :
1249
- license_name .remove (lic_name )
1250
- if lic_url in license_url :
1251
- license_url .remove (lic_url )
1252
- if lic_filename in license_file :
1253
- license_file .remove (lic_filename )
1254
- if spdx_lic_key in spdx_license_key :
1255
- spdx_license_key .remove (spdx_lic_key )
1256
- lic_dict_list .append (lic_dict )
1256
+ # The following condition is to check if license information
1257
+ # has been fetched, the license key is invalid or custom if
1258
+ # no value for lic_name
1259
+ if lic_name :
1260
+ lic_key_copy .remove (lic_key )
1261
+ if lic_name in license_name :
1262
+ license_name .remove (lic_name )
1263
+ if lic_url in license_url :
1264
+ license_url .remove (lic_url )
1265
+ if lic_filename in license_file :
1266
+ license_file .remove (lic_filename )
1267
+ if spdx_lic_key in spdx_license_key :
1268
+ spdx_license_key .remove (spdx_lic_key )
1269
+ lic_dict_list .append (lic_dict )
1257
1270
1258
1271
# Handle license information that have not been handled.
1259
- license_group = list (zip_longest (
1260
- lic_key_copy , license_name , license_file , license_url , spdx_license_key ))
1272
+ # If the len of the lic_key is the same as the lic_file, the tool should
1273
+ # assume the lic_file (custom license) is referring this specific lic_key
1274
+ # otherwise, the tool shouldn't group them
1275
+ if len (lic_key_copy ) == len (license_file ):
1276
+ license_group = list (zip_longest (
1277
+ lic_key_copy , license_name , license_file , license_url , spdx_license_key ))
1278
+ else :
1279
+ license_group = list (zip_longest (
1280
+ lic_key_copy , license_name , [], license_url , spdx_license_key ))
1281
+ # Add the unhandled_lic_file if any
1282
+ if license_file :
1283
+ for lic_file in license_file :
1284
+ license_group .append ((None , None , lic_file , None , None ))
1261
1285
1262
1286
for lic_group in license_group :
1263
1287
lic_dict = {}
@@ -1278,15 +1302,15 @@ def dumps(self, licenses_dict=None):
1278
1302
lic_dict_list .append (lic_dict )
1279
1303
1280
1304
# Format the license information in the same order of the license expression
1281
- if license_key :
1282
- for key in license_key :
1283
- for lic_dict in lic_dict_list :
1284
- if key == lic_dict ['key' ]:
1285
- data .setdefault ('licenses' , []).append (lic_dict )
1286
- break
1287
- else :
1305
+ for key in license_key :
1288
1306
for lic_dict in lic_dict_list :
1289
- data .setdefault ('licenses' , []).append (lic_dict )
1307
+ if key == lic_dict ['key' ]:
1308
+ data .setdefault ('licenses' , []).append (lic_dict )
1309
+ lic_dict_list .remove (lic_dict )
1310
+ break
1311
+
1312
+ for lic_dict in lic_dict_list :
1313
+ data .setdefault ('licenses' , []).append (lic_dict )
1290
1314
1291
1315
return saneyaml .dump (data )
1292
1316
@@ -1764,6 +1788,7 @@ def pre_process_and_fetch_license_dict(abouts, from_check=False, api_url=None, a
1764
1788
if errors :
1765
1789
return key_text_dict , errors
1766
1790
1791
+ spdx_sclickey_dict = get_spdx_key_and_lic_key_from_licdb ()
1767
1792
for about in abouts :
1768
1793
# No need to go through all the about objects if '--api_key' is invalid
1769
1794
auth_error = Error (
@@ -1779,6 +1804,27 @@ def pre_process_and_fetch_license_dict(abouts, from_check=False, api_url=None, a
1779
1804
about .license_expression .value = lic_exp
1780
1805
about .license_expression .present = True
1781
1806
1807
+ if not about .license_expression .value and about .spdx_license_expression .value :
1808
+ lic_exp_value = ""
1809
+ special_char_in_expression , lic_list = parse_license_expression (
1810
+ about .spdx_license_expression .value )
1811
+ if special_char_in_expression :
1812
+ msg = (about .about_file_path + u": The following character(s) cannot be in the spdx_license_expression: " +
1813
+ str (special_char_in_expression ))
1814
+ errors .append (Error (ERROR , msg ))
1815
+ else :
1816
+ spdx_lic_exp_segment = about .spdx_license_expression .value .split ()
1817
+ for spdx_lic_key in spdx_lic_exp_segment :
1818
+ if lic_exp_value :
1819
+ lic_exp_value = lic_exp_value + " " + convert_spdx_expression_to_lic_expression (
1820
+ spdx_lic_key , spdx_sclickey_dict )
1821
+ else :
1822
+ lic_exp_value = convert_spdx_expression_to_lic_expression (
1823
+ spdx_lic_key , spdx_sclickey_dict )
1824
+ if lic_exp_value :
1825
+ about .license_expression .value = lic_exp_value
1826
+ about .license_expression .present = True
1827
+
1782
1828
if about .license_expression .value :
1783
1829
special_char_in_expression , lic_list = parse_license_expression (
1784
1830
about .license_expression .value )
@@ -1855,6 +1901,30 @@ def pre_process_and_fetch_license_dict(abouts, from_check=False, api_url=None, a
1855
1901
return key_text_dict , errors
1856
1902
1857
1903
1904
+ def convert_spdx_expression_to_lic_expression (spdx_key , spdx_lic_dict ):
1905
+ """
1906
+ Translate the spdx_license_expression to license_expression and return
1907
+ errors if spdx_license_key is not matched
1908
+ """
1909
+ value = ""
1910
+ if spdx_key in spdx_lic_dict :
1911
+ value = spdx_lic_dict [spdx_key ]
1912
+ else :
1913
+ if spdx_key .startswith ('(' ):
1914
+ mod_key = spdx_key .partition ('(' )[2 ]
1915
+ value = '(' + \
1916
+ convert_spdx_expression_to_lic_expression (
1917
+ mod_key , spdx_lic_dict )
1918
+ elif spdx_key .endswith (')' ):
1919
+ mod_key = spdx_key .rpartition (')' )[0 ]
1920
+ value = convert_spdx_expression_to_lic_expression (
1921
+ mod_key , spdx_lic_dict ) + ')'
1922
+ else :
1923
+ # This can be operator or key that don't have match
1924
+ value = spdx_key
1925
+ return value
1926
+
1927
+
1858
1928
def parse_license_expression (lic_expression ):
1859
1929
licensing = Licensing ()
1860
1930
lic_list = []
0 commit comments