Skip to content

Commit 6560b2f

Browse files
committed
Add is_builtin field to Licenses and Rules and modify url output
Signed-off-by: Kevin Ji <kyji1011@gmail.com>
1 parent 4825121 commit 6560b2f

7 files changed

Lines changed: 74 additions & 35 deletions

File tree

src/licensedcode/cache.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,12 @@ def load_or_build(
129129
pickle.dump(additional_directories, file, protocol=PICKLE_PROTOCOL)
130130

131131
additional_license_dirs = get_license_dirs(additional_dirs=additional_directories)
132-
validate_additional_license_data(additional_license_dirs)
132+
validate_additional_license_data(additional_directories=additional_license_dirs, scancode_license_dir=licenses_data_dir)
133133
combined_directories = [licenses_data_dir] + additional_license_dirs
134-
licenses_db = load_licenses_from_multiple_dirs(license_directories=combined_directories)
134+
licenses_db = load_licenses_from_multiple_dirs(
135+
license_directories=combined_directories,
136+
scancode_license_dir=licenses_data_dir
137+
)
135138

136139
# create a single merged index containing license data from licenses_data_dir
137140
# and data from additional directories
@@ -207,10 +210,14 @@ def build_index(
207210

208211
# if we have additional directories, extract the rules from them
209212
additional_rule_dirs = get_rule_dirs(additional_dirs=additional_directories)
210-
validate_ignorable_clues(additional_rule_dirs)
213+
validate_ignorable_clues(rule_directories=additional_rule_dirs, is_builtin=False)
211214
# then combine the rules in these additional directories with the rules in the original rules directory
212215
combined_rule_directories = [rules_data_dir] + additional_rule_dirs
213-
rules = get_rules_from_multiple_dirs(licenses_db=licenses_db, rule_directories=combined_rule_directories)
216+
rules = get_rules_from_multiple_dirs(
217+
licenses_db=licenses_db,
218+
rule_directories=combined_rule_directories,
219+
scancode_rules_dir=rules_data_dir
220+
)
214221

215222
legalese = common_license_words
216223
spdx_tokens = set(get_all_spdx_key_tokens(licenses_db))

src/licensedcode/models.py

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,13 @@ class License:
189189
help='Free text notes.')
190190
)
191191

192+
is_builtin = attr.ib(
193+
default=True,
194+
repr=False,
195+
metadata=dict(
196+
help='Flag set to True if this license is a built in license in the ScanCode LicenseDB.')
197+
)
198+
192199
# TODO: add the license key(s) this exception applies to
193200
is_exception = attr.ib(
194201
default=False,
@@ -349,12 +356,12 @@ class License:
349356
)
350357

351358
@classmethod
352-
def from_dir(cls, key, licenses_data_dir=licenses_data_dir):
359+
def from_dir(cls, key, licenses_data_dir=licenses_data_dir, is_builtin=True):
353360
"""
354361
Return a new License object for a license ``key`` and load its attribute
355362
from a data file stored in ``licenses_data_dir``.
356363
"""
357-
lic = cls(key=key)
364+
lic = cls(key=key, is_builtin=is_builtin)
358365
data_file = lic.data_file(licenses_data_dir=licenses_data_dir)
359366
if exists(data_file):
360367
text_file = lic.text_file(licenses_data_dir=licenses_data_dir)
@@ -685,6 +692,7 @@ def load_licenses(
685692
licenses_data_dir=licenses_data_dir,
686693
with_deprecated=False,
687694
check_dangling=True,
695+
is_builtin = True,
688696
):
689697
"""
690698
Return a mapping of {key: License} loaded from license data and text files
@@ -712,7 +720,7 @@ def load_licenses(
712720
key = file_base_name(data_file)
713721

714722
try:
715-
lic = License.from_dir(key=key, licenses_data_dir=licenses_data_dir)
723+
lic = License.from_dir(key=key, licenses_data_dir=licenses_data_dir, is_builtin=is_builtin)
716724
except Exception as e:
717725
raise Exception(f'Failed to load license: {key} from: file://{licenses_data_dir}/{key}.yml with error: {e}') from e
718726

@@ -752,6 +760,7 @@ def get_rules(
752760
licenses_data_dir=licenses_data_dir,
753761
rules_data_dir=rules_data_dir,
754762
validate=False,
763+
is_builtin=True,
755764
):
756765
"""
757766
Yield Rule objects loaded from a ``licenses_db`` and license files found in
@@ -764,6 +773,7 @@ def get_rules(
764773

765774
rules = list(load_rules(
766775
rules_data_dir=rules_data_dir,
776+
is_builtin=is_builtin,
767777
))
768778

769779
if validate:
@@ -815,6 +825,7 @@ def get_paths_to_installed_licenses_and_rules():
815825

816826
def load_licenses_from_multiple_dirs(
817827
license_directories,
828+
scancode_license_dir,
818829
with_deprecated=False,
819830
):
820831
"""
@@ -824,7 +835,8 @@ def load_licenses_from_multiple_dirs(
824835
combined_licenses = {}
825836
combined_licenses_keys = set()
826837
for license_dir in license_directories:
827-
licenses = load_licenses(licenses_data_dir=license_dir, with_deprecated=False)
838+
is_builtin = scancode_license_dir == license_dir
839+
licenses = load_licenses(licenses_data_dir=license_dir, with_deprecated=False, is_builtin=is_builtin)
828840
# check if two dictionaries have duplicate keys
829841
licenses_keys = set(licenses.keys())
830842
duplicate_keys = combined_licenses_keys.intersection(licenses_keys)
@@ -842,6 +854,7 @@ def load_licenses_from_multiple_dirs(
842854
def get_rules_from_multiple_dirs(
843855
licenses_db,
844856
rule_directories,
857+
scancode_rules_dir,
845858
):
846859
"""
847860
Return a mapping of {key: License} built from a list of ``license_directories``.
@@ -851,8 +864,10 @@ def get_rules_from_multiple_dirs(
851864
if rule_directories:
852865
combined_rules = []
853866
for rules_dir in rule_directories:
867+
is_builtin = rules_dir == scancode_rules_dir
854868
r = list(load_rules(
855869
rules_data_dir=rules_dir,
870+
is_builtin=is_builtin,
856871
))
857872
combined_rules.append(r)
858873
# flatten lists of rules into a single iterable
@@ -868,12 +883,12 @@ class InvalidLicense(Exception):
868883
pass
869884

870885

871-
def validate_additional_license_data(additional_directories):
886+
def validate_additional_license_data(additional_directories, scancode_license_dir):
872887
"""
873888
Raises an exception if there are any invalid licenses in the directories of
874889
additional licenses.
875890
"""
876-
licenses = load_licenses_from_multiple_dirs(additional_directories)
891+
licenses = load_licenses_from_multiple_dirs(additional_directories, scancode_license_dir)
877892
errors, _, _ = License.validate(
878893
licenses,
879894
verbose=False,
@@ -907,7 +922,7 @@ def _ignorable_clue_error(rule):
907922
return result, expected
908923

909924

910-
def validate_ignorable_clues(rule_directories):
925+
def validate_ignorable_clues(rule_directories, is_builtin):
911926
"""
912927
Raises an exception if any ignorable clues declared in a Rule are improperly detected
913928
in the rule text file.
@@ -916,6 +931,7 @@ def validate_ignorable_clues(rule_directories):
916931
for rules_dir in rule_directories:
917932
r = list(load_rules(
918933
rules_data_dir=rules_dir,
934+
is_builtin=is_builtin,
919935
))
920936
combined_rules.append(r)
921937
# flatten lists of rules into a single iterable
@@ -1012,6 +1028,7 @@ def build_rule_from_license(license_obj):
10121028
has_stored_minimum_coverage=bool(minimum_coverage),
10131029
minimum_coverage=minimum_coverage,
10141030

1031+
is_builtin=license_obj.is_builtin,
10151032
is_from_license=True,
10161033
is_license_text=True,
10171034

@@ -1064,7 +1081,7 @@ def get_license_tokens():
10641081
yield 'licensed'
10651082

10661083

1067-
def load_rules(rules_data_dir=rules_data_dir, with_checks=True):
1084+
def load_rules(rules_data_dir=rules_data_dir, with_checks=True, is_builtin=True):
10681085
"""
10691086
Return an iterable of rules loaded from rule files in ``rules_data_dir``.
10701087
Optionally check for consistency if ``with_checks`` is True.
@@ -1088,7 +1105,7 @@ def load_rules(rules_data_dir=rules_data_dir, with_checks=True):
10881105
text_file = join(rules_data_dir, f'{base_name}.RULE')
10891106

10901107
try:
1091-
yield Rule.from_files(data_file=data_file, text_file=text_file)
1108+
yield Rule.from_files(data_file=data_file, text_file=text_file, is_builtin=is_builtin)
10921109
except Exception as re:
10931110
if with_checks:
10941111
model_errors.append(str(re))
@@ -1193,6 +1210,13 @@ class BasicRule:
11931210
'string.')
11941211
)
11951212

1213+
is_builtin = attr.ib(
1214+
default=True,
1215+
repr=False,
1216+
metadata=dict(
1217+
help='Flag set to True if this license is a built in license in the ScanCode LicenseDB.')
1218+
)
1219+
11961220
# The is_license_xxx flags below are nn indication of what this rule
11971221
# importance is (e.g. how important is its text when detected as a licensing
11981222
# clue) as one of several "is_license_xxx" flags. These flags are mutually
@@ -1877,12 +1901,12 @@ def __attrs_post_init__(self, *args, **kwargs):
18771901
self.setup()
18781902

18791903
@classmethod
1880-
def from_files(cls, data_file, text_file):
1904+
def from_files(cls, data_file, text_file, is_builtin):
18811905
"""
18821906
Return a new Rule object loaded from a data file stored at
18831907
``data_file`` and a companion ``text_file``.
18841908
"""
1885-
rule = Rule()
1909+
rule = Rule(is_builtin=is_builtin)
18861910
rule.load_data(data_file=data_file, text_file=text_file)
18871911
return rule
18881912

src/scancode/api.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -249,13 +249,19 @@ def _licenses_data_from_match(
249249
result['is_exception'] = lic.is_exception
250250
result['is_unknown'] = lic.is_unknown
251251
result['owner'] = lic.owner
252-
result['homepage_url'] = lic.homepage_url
253-
result['text_url'] = lic.text_urls[0] if lic.text_urls else ''
254-
result['reference_url'] = license_url_template.format(lic.key)
255-
# TODO: change this in the case of a private license?
256-
result['scancode_text_url'] = SCANCODE_LICENSE_TEXT_URL.format(lic.key)
257-
result['scancode_data_url'] = SCANCODE_LICENSE_DATA_URL.format(lic.key)
258-
252+
# if the license is not builtin these should all be empty
253+
if lic.is_builtin:
254+
result['homepage_url'] = lic.homepage_url
255+
result['text_url'] = lic.text_urls[0] if lic.text_urls else ''
256+
result['reference_url'] = license_url_template.format(lic.key)
257+
result['scancode_text_url'] = SCANCODE_LICENSE_TEXT_URL.format(lic.key)
258+
result['scancode_data_url'] = SCANCODE_LICENSE_DATA_URL.format(lic.key)
259+
else:
260+
result['homepage_url'] = ''
261+
result['text_url'] = ''
262+
result['reference_url'] = ''
263+
result['scancode_text_url'] = ''
264+
result['scancode_data_url'] = ''
259265
spdx_key = lic.spdx_license_key
260266
result['spdx_license_key'] = spdx_key
261267

tests/licensedcode/data/plugin_license/external_licenses/scan.expected.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,9 @@
5151
"owner": "NexB",
5252
"homepage_url": null,
5353
"text_url": "",
54-
"reference_url": "https://scancode-licensedb.aboutcode.org/example1",
55-
"scancode_text_url": "https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/licenses/example1.LICENSE",
56-
"scancode_data_url": "https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/licenses/example1.yml",
54+
"reference_url": "",
55+
"scancode_text_url": "",
56+
"scancode_data_url": "",
5757
"spdx_license_key": "scancode-example1",
5858
"spdx_url": "https://spdx.org/licenses/scancode-example1",
5959
"start_line": 1,

tests/licensedcode/data/plugin_license/external_licenses/scan_multiple.expected.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,9 @@
5252
"owner": "NexB",
5353
"homepage_url": null,
5454
"text_url": "",
55-
"reference_url": "https://scancode-licensedb.aboutcode.org/example1",
56-
"scancode_text_url": "https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/licenses/example1.LICENSE",
57-
"scancode_data_url": "https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/licenses/example1.yml",
55+
"reference_url": "",
56+
"scancode_text_url": "",
57+
"scancode_data_url": "",
5858
"spdx_license_key": "scancode-example1",
5959
"spdx_url": "https://spdx.org/licenses/scancode-example1",
6060
"start_line": 1,

tests/licensedcode/data/plugin_license/installed_licenses/scan.expected.json

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
"python_version": "3.8.10 (default, Jun 22 2022, 20:18:18) \n[GCC 9.4.0]"
2828
},
2929
"additional_directories": [
30-
"/home/kevin/code/scancode-toolkit/tests/licensedcode/data/example_external_licenses/example1",
3130
"/home/kevin/code/scancode-toolkit/venv/lib/python3.8/site-packages/licenses_to_install1"
3231
],
3332
"spdx_license_list_version": "3.17",
@@ -51,9 +50,9 @@
5150
"owner": "NexB",
5251
"homepage_url": null,
5352
"text_url": "",
54-
"reference_url": "https://scancode-licensedb.aboutcode.org/example-installed-1",
55-
"scancode_text_url": "https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/licenses/example-installed-1.LICENSE",
56-
"scancode_data_url": "https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/licenses/example-installed-1.yml",
53+
"reference_url": "",
54+
"scancode_text_url": "",
55+
"scancode_data_url": "",
5756
"spdx_license_key": "scancode-example-installed1",
5857
"spdx_url": "https://spdx.org/licenses/scancode-example-installed1",
5958
"start_line": 1,

tests/licensedcode/data/plugin_license/installed_rules/scan.expected.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
"platform_version": "#123~18.04.1-Ubuntu SMP Fri Apr 8 09:48:52 UTC 2022",
2222
"python_version": "3.6.9 (default, Mar 15 2022, 13:55:28) \n[GCC 8.4.0]"
2323
},
24+
"additional_directories": [
25+
"/home/kevin/code/scancode-toolkit/venv/lib/python3.8/site-packages/licenses_to_install1"
26+
],
2427
"spdx_license_list_version": "3.17",
2528
"files_count": 1
2629
}
@@ -42,9 +45,9 @@
4245
"owner": "NexB",
4346
"homepage_url": "",
4447
"text_url": "",
45-
"reference_url": "https://scancode-licensedb.aboutcode.org/example-installed-1",
46-
"scancode_text_url": "https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/licenses/example-installed-1.LICENSE",
47-
"scancode_data_url": "https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/licenses/example-installed-1.yml",
48+
"reference_url": "",
49+
"scancode_text_url": "",
50+
"scancode_data_url": "",
4851
"spdx_license_key": "scancode-example-installed1",
4952
"spdx_url": "https://spdx.org/licenses/scancode-example-installed1",
5053
"start_line": 1,

0 commit comments

Comments
 (0)