Skip to content

Commit a6c2cdb

Browse files
Add script to report rules
Signed-off-by: Ayan Sinha Mahapatra <ayansmahapatra@gmail.com>
1 parent 3be07db commit a6c2cdb

1 file changed

Lines changed: 198 additions & 0 deletions

File tree

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
# -*- coding: utf-8 -*-
2+
#
3+
# Copyright (c) nexB Inc. and others. All rights reserved.
4+
# ScanCode is a trademark of nexB Inc.
5+
# SPDX-License-Identifier: Apache-2.0
6+
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
7+
# See https://github.com/nexB/scancode-toolkit for support or download.
8+
# See https://aboutcode.org for more information about nexB OSS projects.
9+
#
10+
11+
import io
12+
13+
import click
14+
import csv
15+
16+
from commoncode.cliutils import PluggableCommandLineOption
17+
from licensedcode.models import load_licenses
18+
from licensedcode.models import load_rules
19+
20+
21+
LICENSES_FIELDNAMES = [
22+
'key', 'short_name', 'name', 'category', 'owner', 'text', 'words_count', 'notes',
23+
'minimum_coverage', 'homepage_url', 'is_exception', 'language', 'is_unknown',
24+
'spdx_license_key', 'text_urls', 'other_urls', 'standard_notice',
25+
'license_filename', 'faq_url', 'ignorable_authors',
26+
'ignorable_copyrights', 'ignorable_holders', 'ignorable_urls', 'ignorable_emails',
27+
'osi_license_key', 'osi_url', 'other_spdx_license_keys',
28+
]
29+
30+
31+
RULES_FIELDNAMES = [
32+
'identifier', 'license_expression', 'relevance', 'text', 'words_count', 'category',
33+
'is_false_positive', 'is_license_text', 'is_license_notice', 'is_license_tag',
34+
'is_license_reference', 'is_license_intro', 'has_unknown', 'only_known_words',
35+
'notes', 'referenced_filenames', 'minimum_coverage', 'ignorable_copyrights',
36+
'ignorable_holders', 'ignorable_authors', 'ignorable_urls', 'ignorable_emails',
37+
]
38+
39+
40+
def write_data_to_csv(data, output_csv, fieldnames):
41+
42+
with open(output_csv,'w',encoding='utf-8-sig',newline='') as f:
43+
w = csv.DictWriter(f,fieldnames=fieldnames)
44+
w.writeheader()
45+
46+
for entry in data:
47+
w.writerow(entry)
48+
49+
50+
def filter_by_attribute(data, attribute, expected):
51+
52+
filtered_output = []
53+
for entry in data:
54+
if entry.get(attribute, 'None') == expected:
55+
filtered_output.append(entry)
56+
57+
return filtered_output
58+
59+
def flatten_output(data):
60+
61+
if not isinstance(data, list):
62+
return
63+
64+
output = []
65+
for entry in data:
66+
if not isinstance(entry, dict):
67+
continue
68+
69+
output_entry = {}
70+
for key, value in entry.items():
71+
entry_value = None
72+
if value is None:
73+
continue
74+
elif isinstance(value, list):
75+
entry_value = ' '.join(value)
76+
elif not isinstance(value, str):
77+
entry_value = repr(value)
78+
elif not entry_value:
79+
entry_value = value
80+
81+
output_entry[key] = entry_value
82+
83+
output.append(output_entry)
84+
85+
return output
86+
87+
@click.command()
88+
@click.option('-l', '--licenses',
89+
type=click.Path(dir_okay=False, writable=True, readable=False),
90+
default=None,
91+
metavar='FILE',
92+
help='Write all Licenses data to the csv FILE.',
93+
cls=PluggableCommandLineOption
94+
)
95+
@click.option('-r', '--rules',
96+
type=click.Path(dir_okay=False, writable=True, readable=False),
97+
default=None,
98+
metavar='FILE',
99+
help='Write all Rules data to the csv FILE.',
100+
cls=PluggableCommandLineOption,
101+
)
102+
@click.option('-c', '--category',
103+
type=str,
104+
default=None,
105+
metavar='STRING',
106+
help='An optional filter to only output licenses/rules of this category'
107+
'. Example STRING: `permissive`.',
108+
cls=PluggableCommandLineOption,
109+
)
110+
@click.option('-k', '--license-key',
111+
type=str,
112+
default=None,
113+
metavar='STRING',
114+
help='An optional filter to only output licenses/rules which has this license key.'
115+
'Example STRING: `mit`.',
116+
cls=PluggableCommandLineOption,
117+
)
118+
@click.option('-t', '--with-text',
119+
is_flag=True,
120+
default=False,
121+
help='Also include the license/rules texts.'
122+
'Note that this increases the file size significantly.',
123+
cls=PluggableCommandLineOption,
124+
)
125+
@click.help_option('-h', '--help')
126+
def cli(licenses, rules, category, license_key, with_text):
127+
"""
128+
Write Licenses/Rules from scancode into a CSV file with all details.
129+
Output can be optionally filtered by category/license-key.
130+
"""
131+
licenses_output = []
132+
rules_output = []
133+
134+
licenses_data = load_licenses()
135+
136+
if licenses:
137+
for license in licenses_data.values():
138+
license_data = license.to_dict()
139+
if with_text:
140+
license_data['text'] = license.text
141+
license_data['is_unknown'] = license.is_unknown
142+
license_data['words_count'] = len(license.text)
143+
licenses_output.append(license_data)
144+
145+
if category:
146+
licenses_output = filter_by_attribute(
147+
data=licenses_output,
148+
attribute='category',
149+
expected=category
150+
)
151+
152+
if license_key:
153+
licenses_output = filter_by_attribute(
154+
data=licenses_output,
155+
attribute='key',
156+
expected=license_key,
157+
)
158+
159+
licenses_output = flatten_output(data=licenses_output)
160+
write_data_to_csv(data=licenses_output, output_csv=licenses, fieldnames=LICENSES_FIELDNAMES)
161+
162+
163+
if rules:
164+
rules_data = list(load_rules())
165+
for rule in rules_data:
166+
rule_data = rule.to_dict()
167+
rule_data['identifier'] = rule.identifier
168+
rule_data['referenced_filenames'] = rule.referenced_filenames
169+
if with_text:
170+
rule_data['text'] = rule.text()
171+
rule_data['has_unknown'] = rule.has_unknown
172+
rule_data['words_count'] = len(rule.text())
173+
try:
174+
rule_data['category'] = licenses_data[rule_data['license_expression']].category
175+
except KeyError:
176+
pass
177+
rules_output.append(rule_data)
178+
179+
if category:
180+
rules_output = filter_by_attribute(
181+
data=rules_output,
182+
attribute='category',
183+
expected=category
184+
)
185+
186+
if license_key:
187+
rules_output = filter_by_attribute(
188+
data=rules_output,
189+
attribute='license_expression',
190+
expected=license_key,
191+
)
192+
193+
rules_output = flatten_output(rules_output)
194+
write_data_to_csv(data=rules_output, output_csv=rules, fieldnames=RULES_FIELDNAMES)
195+
196+
197+
if __name__ == '__main__':
198+
cli()

0 commit comments

Comments
 (0)