fosslight-util 1.4.34__py3-none-any.whl → 2.1.28__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fosslight_util/_get_downloadable_url.py +466 -36
- fosslight_util/compare_yaml.py +20 -11
- fosslight_util/constant.py +35 -0
- fosslight_util/correct.py +46 -78
- fosslight_util/cover.py +60 -0
- fosslight_util/download.py +302 -95
- fosslight_util/exclude.py +65 -0
- fosslight_util/help.py +20 -8
- fosslight_util/oss_item.py +171 -110
- fosslight_util/output_format.py +147 -19
- fosslight_util/parsing_yaml.py +45 -23
- fosslight_util/read_excel.py +40 -39
- fosslight_util/set_log.py +30 -5
- fosslight_util/spdx_licenses.py +2 -1
- fosslight_util/write_cyclonedx.py +210 -0
- fosslight_util/write_excel.py +141 -133
- fosslight_util/write_opossum.py +14 -20
- fosslight_util/write_scancodejson.py +51 -32
- fosslight_util/write_spdx.py +162 -115
- fosslight_util/write_txt.py +2 -1
- fosslight_util/write_yaml.py +43 -49
- {fosslight_util-1.4.34.dist-info → fosslight_util-2.1.28.dist-info}/METADATA +32 -24
- fosslight_util-2.1.28.dist-info/RECORD +32 -0
- {fosslight_util-1.4.34.dist-info → fosslight_util-2.1.28.dist-info}/WHEEL +1 -1
- {fosslight_util-1.4.34.dist-info → fosslight_util-2.1.28.dist-info}/entry_points.txt +0 -1
- fosslight_util/convert_excel_to_yaml.py +0 -69
- fosslight_util-1.4.34.dist-info/RECORD +0 -30
- {fosslight_util-1.4.34.dist-info → fosslight_util-2.1.28.dist-info/licenses}/LICENSE +0 -0
- {fosslight_util-1.4.34.dist-info → fosslight_util-2.1.28.dist-info}/top_level.txt +0 -0
fosslight_util/oss_item.py
CHANGED
|
@@ -5,41 +5,43 @@
|
|
|
5
5
|
|
|
6
6
|
import logging
|
|
7
7
|
import os
|
|
8
|
-
|
|
8
|
+
import hashlib
|
|
9
|
+
from fosslight_util.constant import LOGGER_NAME, FOSSLIGHT_SCANNER
|
|
10
|
+
from fosslight_util.cover import CoverItem
|
|
11
|
+
from typing import List, Dict
|
|
9
12
|
|
|
10
13
|
_logger = logging.getLogger(LOGGER_NAME)
|
|
14
|
+
CHECKSUM_NULL = "0"
|
|
11
15
|
|
|
12
16
|
|
|
13
17
|
class OssItem:
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
self.
|
|
18
|
+
|
|
19
|
+
def __init__(self, name="", version="", license="", dl_url=""):
|
|
20
|
+
self.name = name
|
|
21
|
+
self.version = version
|
|
17
22
|
self._license = []
|
|
18
|
-
self.
|
|
23
|
+
self.license = license
|
|
24
|
+
self.download_location = dl_url
|
|
25
|
+
self.exclude = False
|
|
19
26
|
self.comment = ""
|
|
20
|
-
self._exclude = False
|
|
21
27
|
self.homepage = ""
|
|
22
|
-
self.
|
|
23
|
-
self._source_name_or_path = []
|
|
24
|
-
self.download_location = ""
|
|
25
|
-
self._yocto_recipe = []
|
|
26
|
-
self._yocto_package = []
|
|
27
|
-
self.is_binary = False
|
|
28
|
+
self._copyright = ""
|
|
28
29
|
|
|
29
30
|
def __del__(self):
|
|
30
31
|
pass
|
|
31
32
|
|
|
32
33
|
@property
|
|
33
|
-
def
|
|
34
|
-
return self.
|
|
34
|
+
def license(self):
|
|
35
|
+
return self._license
|
|
35
36
|
|
|
36
|
-
@
|
|
37
|
-
def
|
|
37
|
+
@license.setter
|
|
38
|
+
def license(self, value):
|
|
38
39
|
if value != "":
|
|
39
|
-
if isinstance(value, list):
|
|
40
|
-
value = "
|
|
41
|
-
|
|
42
|
-
self.
|
|
40
|
+
if not isinstance(value, list):
|
|
41
|
+
value = value.split(",")
|
|
42
|
+
self._license.extend(value)
|
|
43
|
+
self._license = [item.strip() for item in self._license]
|
|
44
|
+
self._license = list(set(self._license))
|
|
43
45
|
|
|
44
46
|
@property
|
|
45
47
|
def exclude(self):
|
|
@@ -53,13 +55,18 @@ class OssItem:
|
|
|
53
55
|
self._exclude = False
|
|
54
56
|
|
|
55
57
|
@property
|
|
56
|
-
def
|
|
57
|
-
return self.
|
|
58
|
+
def copyright(self):
|
|
59
|
+
return self._copyright
|
|
58
60
|
|
|
59
|
-
@
|
|
60
|
-
def
|
|
61
|
-
if value
|
|
62
|
-
|
|
61
|
+
@copyright.setter
|
|
62
|
+
def copyright(self, value):
|
|
63
|
+
if value:
|
|
64
|
+
if isinstance(value, list):
|
|
65
|
+
value = list(set(value))
|
|
66
|
+
else:
|
|
67
|
+
value = set(value.split("\n"))
|
|
68
|
+
value = "\n".join(value).strip()
|
|
69
|
+
self._copyright = value
|
|
63
70
|
|
|
64
71
|
@property
|
|
65
72
|
def version(self):
|
|
@@ -73,107 +80,161 @@ class OssItem:
|
|
|
73
80
|
self._version = ""
|
|
74
81
|
|
|
75
82
|
@property
|
|
76
|
-
def
|
|
77
|
-
return self.
|
|
78
|
-
|
|
79
|
-
@license.setter
|
|
80
|
-
def license(self, value):
|
|
81
|
-
if not isinstance(value, list):
|
|
82
|
-
value = value.split(",")
|
|
83
|
-
self._license.extend(value)
|
|
84
|
-
self._license = [item.strip() for item in self._license]
|
|
85
|
-
self._license = list(set(self._license))
|
|
86
|
-
|
|
87
|
-
@property
|
|
88
|
-
def source_name_or_path(self):
|
|
89
|
-
return self._source_name_or_path
|
|
83
|
+
def comment(self):
|
|
84
|
+
return self._comment
|
|
90
85
|
|
|
91
|
-
@
|
|
92
|
-
def
|
|
86
|
+
@comment.setter
|
|
87
|
+
def comment(self, value):
|
|
93
88
|
if not value:
|
|
94
|
-
self.
|
|
89
|
+
self._comment = ""
|
|
95
90
|
else:
|
|
96
|
-
if
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
91
|
+
if self._comment:
|
|
92
|
+
self._comment = f"{self._comment} / {value}"
|
|
93
|
+
else:
|
|
94
|
+
self._comment = value
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
class FileItem:
|
|
98
|
+
def __init__(self, value):
|
|
99
|
+
self.relative_path = value
|
|
100
|
+
self.source_name_or_path = ""
|
|
101
|
+
self._exclude = False
|
|
102
|
+
self._comment = ""
|
|
103
|
+
self.is_binary = False
|
|
104
|
+
self.oss_items: List[OssItem] = []
|
|
105
|
+
self.checksum = CHECKSUM_NULL
|
|
106
|
+
|
|
107
|
+
def __del__(self):
|
|
108
|
+
pass
|
|
101
109
|
|
|
102
110
|
@property
|
|
103
|
-
def
|
|
104
|
-
return self.
|
|
111
|
+
def exclude(self):
|
|
112
|
+
return self._exclude
|
|
105
113
|
|
|
106
|
-
@
|
|
107
|
-
def
|
|
108
|
-
if
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
114
|
+
@exclude.setter
|
|
115
|
+
def exclude(self, value):
|
|
116
|
+
if value:
|
|
117
|
+
self._exclude = True
|
|
118
|
+
else:
|
|
119
|
+
self._exclude = False
|
|
120
|
+
for oss in self.oss_items:
|
|
121
|
+
oss.exclude = value
|
|
113
122
|
|
|
114
123
|
@property
|
|
115
|
-
def
|
|
116
|
-
return self.
|
|
117
|
-
|
|
118
|
-
@
|
|
119
|
-
def
|
|
120
|
-
if not
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
return
|
|
130
|
-
self.source_name_or_path = item[0]
|
|
131
|
-
self.name = item[1]
|
|
132
|
-
self.version = item[2]
|
|
133
|
-
self.license = item[3]
|
|
134
|
-
self.download_location = item[4]
|
|
135
|
-
self.homepage = item[5]
|
|
136
|
-
self.copyright = item[6]
|
|
137
|
-
self.exclude = item[7]
|
|
138
|
-
self.comment = item[8]
|
|
124
|
+
def comment(self):
|
|
125
|
+
return self._comment
|
|
126
|
+
|
|
127
|
+
@comment.setter
|
|
128
|
+
def comment(self, value):
|
|
129
|
+
if not value:
|
|
130
|
+
self._comment = ""
|
|
131
|
+
else:
|
|
132
|
+
if self._comment:
|
|
133
|
+
self._comment = f"{self._comment} / {value}"
|
|
134
|
+
else:
|
|
135
|
+
self._comment = value
|
|
136
|
+
for oss in self.oss_items:
|
|
137
|
+
oss.comment = value
|
|
139
138
|
|
|
140
139
|
def get_print_array(self):
|
|
141
140
|
items = []
|
|
142
|
-
if len(self.source_name_or_path) == 0:
|
|
143
|
-
self.source_name_or_path.append("")
|
|
144
|
-
if len(self.license) == 0:
|
|
145
|
-
self.license.append("")
|
|
146
141
|
|
|
147
|
-
|
|
142
|
+
for oss in self.oss_items:
|
|
143
|
+
exclude = "Exclude" if self.exclude or oss.exclude else ""
|
|
144
|
+
lic = ",".join(oss.license)
|
|
148
145
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
items.append(
|
|
152
|
-
self.download_location, self.homepage, self.copyright, exclude, self.comment])
|
|
146
|
+
oss_item = [os.path.join(self.relative_path, self.source_name_or_path), oss.name, oss.version, lic,
|
|
147
|
+
oss.download_location, oss.homepage, oss.copyright, exclude, oss.comment]
|
|
148
|
+
items.append(oss_item)
|
|
153
149
|
return items
|
|
154
150
|
|
|
155
151
|
def get_print_json(self):
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
json_item["
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
152
|
+
items = []
|
|
153
|
+
|
|
154
|
+
for oss in self.oss_items:
|
|
155
|
+
json_item = {}
|
|
156
|
+
json_item["name"] = oss.name
|
|
157
|
+
json_item["version"] = oss.version
|
|
158
|
+
|
|
159
|
+
if self.source_name_or_path != "":
|
|
160
|
+
json_item["source path"] = self.source_name_or_path
|
|
161
|
+
if len(oss.license) > 0:
|
|
162
|
+
json_item["license"] = oss.license
|
|
163
|
+
if oss.download_location != "":
|
|
164
|
+
json_item["download location"] = oss.download_location
|
|
165
|
+
if oss.homepage != "":
|
|
166
|
+
json_item["homepage"] = oss.homepage
|
|
167
|
+
if oss.copyright != "":
|
|
168
|
+
json_item["copyright text"] = oss.copyright
|
|
169
|
+
if self.exclude or oss.exclude:
|
|
170
|
+
json_item["exclude"] = True
|
|
171
|
+
if oss.comment != "":
|
|
172
|
+
json_item["comment"] = oss.comment
|
|
173
|
+
items.append(json_item)
|
|
174
|
+
return items
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def get_checksum_sha1(source_name_or_path) -> str:
|
|
178
|
+
checksum = CHECKSUM_NULL
|
|
179
|
+
try:
|
|
180
|
+
checksum = str(hashlib.sha1(source_name_or_path.encode()).hexdigest())
|
|
181
|
+
except Exception:
|
|
182
|
+
try:
|
|
183
|
+
f = open(source_name_or_path, "rb")
|
|
184
|
+
byte = f.read()
|
|
185
|
+
checksum = str(hashlib.sha1(byte).hexdigest())
|
|
186
|
+
f.close()
|
|
187
|
+
except Exception as ex:
|
|
188
|
+
_logger.info(f"(Error) Get_checksum: {ex}")
|
|
189
|
+
|
|
190
|
+
return checksum
|
|
176
191
|
|
|
177
192
|
|
|
178
193
|
def invalid(cmd):
|
|
179
194
|
_logger.info('[{}] is invalid'.format(cmd))
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
class ScannerItem:
|
|
198
|
+
def __init__(self, pkg_name, start_time=""):
|
|
199
|
+
self.cover = CoverItem(tool_name=pkg_name, start_time=start_time)
|
|
200
|
+
self.file_items: Dict[str, List[FileItem]] = {pkg_name: []} if pkg_name != FOSSLIGHT_SCANNER else {}
|
|
201
|
+
self.external_sheets: Dict[str, List[List[str]]] = {}
|
|
202
|
+
|
|
203
|
+
def set_cover_pathinfo(self, input_dir, path_to_exclude):
|
|
204
|
+
self.cover.input_path = input_dir
|
|
205
|
+
self.cover.exclude_path = ", ".join(path_to_exclude)
|
|
206
|
+
|
|
207
|
+
def set_cover_comment(self, value):
|
|
208
|
+
if value:
|
|
209
|
+
if self.cover.comment:
|
|
210
|
+
self.cover.comment = f"{self.cover.comment} / {value}"
|
|
211
|
+
else:
|
|
212
|
+
self.cover.comment = value
|
|
213
|
+
|
|
214
|
+
def get_cover_comment(self):
|
|
215
|
+
return [item.strip() for item in self.cover.comment.split(" / ")]
|
|
216
|
+
|
|
217
|
+
def append_file_items(self, file_item: List[FileItem], pkg_name=""):
|
|
218
|
+
if pkg_name == "":
|
|
219
|
+
if len(self.file_items.keys()) != 1:
|
|
220
|
+
_logger.error("Package name is not set. Cannot append file_item into ScannerItem.")
|
|
221
|
+
else:
|
|
222
|
+
pkg_name = list(self.file_items.keys())[0]
|
|
223
|
+
if pkg_name not in self.file_items:
|
|
224
|
+
self.file_items[pkg_name] = []
|
|
225
|
+
self.file_items[pkg_name].extend(file_item)
|
|
226
|
+
|
|
227
|
+
def get_print_array(self, scanner_name):
|
|
228
|
+
items = []
|
|
229
|
+
for file_item in self.file_items[scanner_name]:
|
|
230
|
+
items.extend(file_item.get_print_array())
|
|
231
|
+
return items
|
|
232
|
+
|
|
233
|
+
def get_print_json(self, scanner_name):
|
|
234
|
+
items = []
|
|
235
|
+
for file_item in self.file_items[scanner_name]:
|
|
236
|
+
items.extend(file_item.get_print_json())
|
|
237
|
+
return items
|
|
238
|
+
|
|
239
|
+
def __del__(self):
|
|
240
|
+
pass
|
fosslight_util/output_format.py
CHANGED
|
@@ -3,11 +3,17 @@
|
|
|
3
3
|
# Copyright (c) 2021 LG Electronics Inc.
|
|
4
4
|
# SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
import os
|
|
6
|
-
|
|
6
|
+
import platform
|
|
7
|
+
from fosslight_util.write_excel import write_result_to_excel, write_result_to_csv
|
|
7
8
|
from fosslight_util.write_opossum import write_opossum
|
|
8
9
|
from fosslight_util.write_yaml import write_yaml
|
|
10
|
+
from fosslight_util.write_spdx import write_spdx
|
|
11
|
+
from fosslight_util.write_cyclonedx import write_cyclonedx
|
|
12
|
+
from typing import Tuple
|
|
9
13
|
|
|
10
|
-
SUPPORT_FORMAT = {'excel': '.xlsx', 'csv': '.csv', 'opossum': '.json', 'yaml': '.yaml'
|
|
14
|
+
SUPPORT_FORMAT = {'excel': '.xlsx', 'csv': '.csv', 'opossum': '.json', 'yaml': '.yaml',
|
|
15
|
+
'spdx-yaml': '.yaml', 'spdx-json': '.json', 'spdx-xml': '.xml',
|
|
16
|
+
'spdx-tag': '.tag', 'cyclonedx-json': '.json', 'cyclonedx-xml': '.xml'}
|
|
11
17
|
|
|
12
18
|
|
|
13
19
|
def check_output_format(output='', format='', customized_format={}):
|
|
@@ -26,7 +32,7 @@ def check_output_format(output='', format='', customized_format={}):
|
|
|
26
32
|
format = format.lower()
|
|
27
33
|
if format not in list(support_format.keys()):
|
|
28
34
|
success = False
|
|
29
|
-
msg = 'Enter the supported format
|
|
35
|
+
msg = '(-f option) Enter the supported format: ' + ', '.join(list(support_format.keys()))
|
|
30
36
|
else:
|
|
31
37
|
output_extension = support_format[format]
|
|
32
38
|
|
|
@@ -42,11 +48,12 @@ def check_output_format(output='', format='', customized_format={}):
|
|
|
42
48
|
if format:
|
|
43
49
|
if output_extension != basename_extension:
|
|
44
50
|
success = False
|
|
45
|
-
msg = f"Enter the same extension of output file(-o:'{output}')
|
|
51
|
+
msg = f"(-o & -f option) Enter the same extension of output file(-o:'{output}') \
|
|
52
|
+
with format(-f:'{format}')."
|
|
46
53
|
else:
|
|
47
54
|
if basename_extension not in support_format.values():
|
|
48
55
|
success = False
|
|
49
|
-
msg = 'Enter the supported file extension: ' + ', '.join(list(support_format.values()))
|
|
56
|
+
msg = '(-o option) Enter the supported file extension: ' + ', '.join(list(support_format.values()))
|
|
50
57
|
if success:
|
|
51
58
|
output_file = basename_file
|
|
52
59
|
output_extension = basename_extension
|
|
@@ -56,29 +63,150 @@ def check_output_format(output='', format='', customized_format={}):
|
|
|
56
63
|
return success, msg, output_path, output_file, output_extension
|
|
57
64
|
|
|
58
65
|
|
|
59
|
-
def
|
|
66
|
+
def check_output_formats(output='', formats=[], customized_format={}):
|
|
60
67
|
success = True
|
|
61
68
|
msg = ''
|
|
69
|
+
output_path = ''
|
|
70
|
+
output_files = []
|
|
71
|
+
output_extensions = []
|
|
72
|
+
|
|
73
|
+
if customized_format:
|
|
74
|
+
support_format = customized_format
|
|
75
|
+
else:
|
|
76
|
+
support_format = SUPPORT_FORMAT
|
|
77
|
+
|
|
78
|
+
if formats:
|
|
79
|
+
# If -f option exist
|
|
80
|
+
formats = [format.lower() for format in formats]
|
|
81
|
+
for format in formats:
|
|
82
|
+
if format not in list(support_format.keys()):
|
|
83
|
+
success = False
|
|
84
|
+
msg = '(-f option) Enter the supported format: ' + ', '.join(list(support_format.keys()))
|
|
85
|
+
else:
|
|
86
|
+
output_extensions.append(support_format[format])
|
|
62
87
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
88
|
+
if success:
|
|
89
|
+
if output != '':
|
|
90
|
+
basename_extension = ''
|
|
91
|
+
if not os.path.isdir(output):
|
|
92
|
+
output_path = os.path.dirname(output)
|
|
68
93
|
|
|
94
|
+
basename = os.path.basename(output)
|
|
95
|
+
basename_file, basename_extension = os.path.splitext(basename)
|
|
96
|
+
if basename_extension:
|
|
97
|
+
if formats:
|
|
98
|
+
if basename_extension not in output_extensions:
|
|
99
|
+
success = False
|
|
100
|
+
msg = f"(-o & -f option) The format of output file(-o:'{output}') \
|
|
101
|
+
should be in the format list(-f:'{formats}')."
|
|
102
|
+
else:
|
|
103
|
+
if basename_extension not in support_format.values():
|
|
104
|
+
success = False
|
|
105
|
+
msg = '(-o option) Enter the supported file extension: ' + ', '.join(list(support_format.values()))
|
|
106
|
+
output_extensions.append(basename_extension)
|
|
107
|
+
output_files = [basename_file for _ in range(len(output_extensions))]
|
|
108
|
+
else:
|
|
109
|
+
output_path = output
|
|
110
|
+
if not output_extensions:
|
|
111
|
+
output_extensions = ['.xlsx']
|
|
112
|
+
|
|
113
|
+
return success, msg, output_path, output_files, output_extensions
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def check_output_formats_v2(output='', formats=[], customized_format={}):
|
|
117
|
+
success = True
|
|
118
|
+
msg = ''
|
|
119
|
+
output_path = ''
|
|
120
|
+
output_files = []
|
|
121
|
+
output_extensions = []
|
|
122
|
+
|
|
123
|
+
if customized_format:
|
|
124
|
+
support_format = customized_format
|
|
125
|
+
else:
|
|
126
|
+
support_format = SUPPORT_FORMAT
|
|
127
|
+
|
|
128
|
+
if formats:
|
|
129
|
+
# If -f option exist
|
|
130
|
+
formats = [format.lower() for format in formats]
|
|
131
|
+
for format in formats:
|
|
132
|
+
if format not in list(support_format.keys()):
|
|
133
|
+
success = False
|
|
134
|
+
msg = '(-f option) Enter the supported format with -f option: ' + ', '.join(list(support_format.keys()))
|
|
135
|
+
else:
|
|
136
|
+
output_extensions.append(support_format[format])
|
|
137
|
+
|
|
138
|
+
if success:
|
|
139
|
+
if output != '':
|
|
140
|
+
basename_extension = ''
|
|
141
|
+
if not os.path.isdir(output):
|
|
142
|
+
output_path = os.path.dirname(output)
|
|
143
|
+
|
|
144
|
+
basename = os.path.basename(output)
|
|
145
|
+
basename_file, basename_extension = os.path.splitext(basename)
|
|
146
|
+
if basename_extension:
|
|
147
|
+
if formats:
|
|
148
|
+
if basename_extension not in output_extensions:
|
|
149
|
+
success = False
|
|
150
|
+
msg = f"(-o & -f option) The format of output file(-o:'{output}') \
|
|
151
|
+
should be in the format list(-f:'{formats}')."
|
|
152
|
+
else:
|
|
153
|
+
if basename_extension not in support_format.values():
|
|
154
|
+
success = False
|
|
155
|
+
msg = '(-o option) Enter the supported file extension: ' + ', '.join(list(support_format.values()))
|
|
156
|
+
output_extensions.append(basename_extension)
|
|
157
|
+
output_files = [basename_file for _ in range(len(output_extensions))]
|
|
158
|
+
else:
|
|
159
|
+
output_path = output
|
|
160
|
+
if not output_extensions:
|
|
161
|
+
output_extensions = ['.xlsx']
|
|
162
|
+
if not formats:
|
|
163
|
+
formats = []
|
|
164
|
+
for ext in output_extensions:
|
|
165
|
+
for key, value in support_format.items():
|
|
166
|
+
if value == ext:
|
|
167
|
+
formats.append(key)
|
|
168
|
+
break
|
|
169
|
+
return success, msg, output_path, output_files, output_extensions, formats
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def write_output_file(output_file_without_ext: str, file_extension: str, scan_item, extended_header: dict = {},
|
|
173
|
+
hide_header: dict = {}, format: str = '', spdx_version: str = '2.3') -> Tuple[bool, str, str]:
|
|
174
|
+
success = True
|
|
175
|
+
msg = ''
|
|
176
|
+
|
|
177
|
+
if file_extension == '':
|
|
178
|
+
file_extension = '.xlsx'
|
|
179
|
+
result_file = output_file_without_ext + file_extension
|
|
180
|
+
|
|
181
|
+
if format:
|
|
182
|
+
if format == 'excel':
|
|
183
|
+
success, msg = write_result_to_excel(result_file, scan_item, extended_header, hide_header)
|
|
184
|
+
elif format == 'csv':
|
|
185
|
+
success, msg, _ = write_result_to_csv(result_file, scan_item, False, extended_header)
|
|
186
|
+
elif format == 'opossum':
|
|
187
|
+
success, msg = write_opossum(result_file, scan_item)
|
|
188
|
+
elif format == 'yaml':
|
|
189
|
+
success, msg, _ = write_yaml(result_file, scan_item, False)
|
|
190
|
+
elif format.startswith('spdx') or format.startswith('cyclonedx'):
|
|
191
|
+
if platform.system() == 'Windows' or platform.system() == 'Darwin':
|
|
192
|
+
success = False
|
|
193
|
+
msg = f'{platform.system()} not support spdx format.'
|
|
194
|
+
else:
|
|
195
|
+
if format.startswith('spdx'):
|
|
196
|
+
success, msg, _ = write_spdx(output_file_without_ext, file_extension, scan_item, spdx_version)
|
|
197
|
+
elif format.startswith('cyclonedx'):
|
|
198
|
+
success, msg, _ = write_cyclonedx(output_file_without_ext, file_extension, scan_item)
|
|
199
|
+
else:
|
|
69
200
|
if file_extension == '.xlsx':
|
|
70
|
-
success, msg = write_result_to_excel(result_file,
|
|
201
|
+
success, msg = write_result_to_excel(result_file, scan_item, extended_header, hide_header)
|
|
71
202
|
elif file_extension == '.csv':
|
|
72
|
-
success, msg, result_file = write_result_to_csv(result_file,
|
|
203
|
+
success, msg, result_file = write_result_to_csv(result_file, scan_item, False, extended_header)
|
|
73
204
|
elif file_extension == '.json':
|
|
74
|
-
success, msg = write_opossum(result_file,
|
|
205
|
+
success, msg = write_opossum(result_file, scan_item)
|
|
75
206
|
elif file_extension == '.yaml':
|
|
76
|
-
success, msg, result_file = write_yaml(result_file,
|
|
207
|
+
success, msg, result_file = write_yaml(result_file, scan_item, False)
|
|
77
208
|
else:
|
|
78
209
|
success = False
|
|
79
|
-
msg = f'Not supported file extension({file_extension})'
|
|
80
|
-
else:
|
|
81
|
-
result_file = ""
|
|
82
|
-
msg = "Nothing is detected from the scanner so output file is not generated."
|
|
210
|
+
msg = f'(-f option) Not supported file extension({file_extension})'
|
|
83
211
|
|
|
84
212
|
return success, msg, result_file
|
fosslight_util/parsing_yaml.py
CHANGED
|
@@ -8,8 +8,8 @@ import codecs
|
|
|
8
8
|
import os
|
|
9
9
|
import re
|
|
10
10
|
import sys
|
|
11
|
-
from .constant import LOGGER_NAME
|
|
12
|
-
from .oss_item import OssItem
|
|
11
|
+
from fosslight_util.constant import LOGGER_NAME
|
|
12
|
+
from fosslight_util.oss_item import OssItem, FileItem
|
|
13
13
|
|
|
14
14
|
_logger = logging.getLogger(LOGGER_NAME)
|
|
15
15
|
SUPPORT_OSS_INFO_FILES = [r"oss-pkg-info[\s\S]*.ya?ml", r"sbom(-|_)info[\s\S]*.ya?ml"]
|
|
@@ -17,7 +17,7 @@ EXAMPLE_OSS_PKG_INFO_LINK = "https://github.com/fosslight/fosslight_prechecker/b
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
def parsing_yml(yaml_file, base_path, print_log=True):
|
|
20
|
-
|
|
20
|
+
fileitems = []
|
|
21
21
|
license_list = []
|
|
22
22
|
idx = 1
|
|
23
23
|
err_reason = ""
|
|
@@ -38,37 +38,65 @@ def parsing_yml(yaml_file, base_path, print_log=True):
|
|
|
38
38
|
err_reason = "empty"
|
|
39
39
|
if print_log:
|
|
40
40
|
_logger.warning(f"The yaml file is empty file: {yaml_file}")
|
|
41
|
-
return
|
|
41
|
+
return fileitems, license_list, err_reason
|
|
42
42
|
|
|
43
43
|
is_old_format = any(x in doc for x in OLD_YAML_ROOT_ELEMENT)
|
|
44
44
|
|
|
45
|
+
filepath_list = []
|
|
45
46
|
for root_element in doc:
|
|
46
47
|
oss_items = doc[root_element]
|
|
47
48
|
if oss_items:
|
|
48
49
|
if not isinstance(oss_items, list) or 'version' not in oss_items[0]:
|
|
49
50
|
raise AttributeError(f"- Ref. {EXAMPLE_OSS_PKG_INFO_LINK}")
|
|
50
51
|
for oss in oss_items:
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
52
|
+
source_paths = get_source_name_or_path_in_yaml(oss)
|
|
53
|
+
for source_path in source_paths:
|
|
54
|
+
if os.path.join(relative_path, source_path) not in filepath_list:
|
|
55
|
+
filepath_list.append(os.path.join(relative_path, source_path))
|
|
56
|
+
fileitem = FileItem(relative_path)
|
|
57
|
+
fileitem.source_name_or_path = source_path
|
|
58
|
+
fileitems.append(fileitem)
|
|
59
|
+
else:
|
|
60
|
+
fileitem = next((i for i in fileitems if i.source_name_or_path == source_path), None)
|
|
61
|
+
ossitem = OssItem()
|
|
62
|
+
if not is_old_format:
|
|
63
|
+
ossitem.name = root_element
|
|
64
|
+
for key, value in oss.items():
|
|
65
|
+
if key:
|
|
66
|
+
key = key.lower().strip()
|
|
67
|
+
set_value_switch(ossitem, key, value, yaml_file)
|
|
68
|
+
fileitem.oss_items.append(ossitem)
|
|
69
|
+
license_list.extend(ossitem.license)
|
|
70
|
+
idx += 1
|
|
61
71
|
except AttributeError as ex:
|
|
62
72
|
if print_log:
|
|
63
73
|
_logger.warning(f"Not supported yaml file format: {yaml_file} {ex}")
|
|
64
|
-
|
|
74
|
+
fileitems = []
|
|
65
75
|
err_reason = "not_supported"
|
|
66
76
|
except yaml.YAMLError:
|
|
67
77
|
if print_log:
|
|
68
78
|
_logger.warning(f"Error to parse yaml - skip to parse yaml file: {yaml_file}")
|
|
69
|
-
|
|
79
|
+
fileitems = []
|
|
70
80
|
err_reason = "yaml_error"
|
|
71
|
-
|
|
81
|
+
|
|
82
|
+
return fileitems, set(license_list), err_reason
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def get_source_name_or_path_in_yaml(oss):
|
|
86
|
+
source_name_or_path = []
|
|
87
|
+
find = False
|
|
88
|
+
for key in oss.keys():
|
|
89
|
+
if key in ['file name or path', 'source name or path', 'source path',
|
|
90
|
+
'file', 'binary name', 'binary path']:
|
|
91
|
+
if isinstance(oss[key], list):
|
|
92
|
+
source_name_or_path = oss[key]
|
|
93
|
+
else:
|
|
94
|
+
source_name_or_path.append(oss[key])
|
|
95
|
+
find = True
|
|
96
|
+
break
|
|
97
|
+
if not find:
|
|
98
|
+
source_name_or_path.append('')
|
|
99
|
+
return source_name_or_path
|
|
72
100
|
|
|
73
101
|
|
|
74
102
|
def find_sbom_yaml_files(path_to_find):
|
|
@@ -101,8 +129,6 @@ def set_value_switch(oss, key, value, yaml_file=""):
|
|
|
101
129
|
oss.download_location = value
|
|
102
130
|
elif key in ['license', 'license text']:
|
|
103
131
|
oss.license = value
|
|
104
|
-
elif key in ['file name or path', 'source name or path', 'file', 'binary name']:
|
|
105
|
-
oss.source_name_or_path = value
|
|
106
132
|
elif key in ['copyright text', 'copyright']:
|
|
107
133
|
oss.copyright = value
|
|
108
134
|
elif key == 'exclude':
|
|
@@ -111,10 +137,6 @@ def set_value_switch(oss, key, value, yaml_file=""):
|
|
|
111
137
|
oss.comment = value
|
|
112
138
|
elif key == 'homepage':
|
|
113
139
|
oss.homepage = value
|
|
114
|
-
elif key == 'yocto_package':
|
|
115
|
-
oss.yocto_package = value
|
|
116
|
-
elif key == 'yocto_recipe':
|
|
117
|
-
oss.yocto_recipe = value
|
|
118
140
|
else:
|
|
119
141
|
if yaml_file != "":
|
|
120
142
|
_logger.debug(f"file:{yaml_file} - key:{key} cannot be parsed")
|