fosslight-util 1.4.48__tar.gz → 2.0.1__tar.gz

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.
Files changed (44) hide show
  1. {fosslight_util-1.4.48 → fosslight_util-2.0.1}/PKG-INFO +1 -1
  2. {fosslight_util-1.4.48 → fosslight_util-2.0.1}/requirements.txt +1 -2
  3. {fosslight_util-1.4.48 → fosslight_util-2.0.1}/setup.py +1 -1
  4. {fosslight_util-1.4.48 → fosslight_util-2.0.1}/src/fosslight_util/compare_yaml.py +18 -11
  5. {fosslight_util-1.4.48 → fosslight_util-2.0.1}/src/fosslight_util/constant.py +11 -0
  6. {fosslight_util-1.4.48 → fosslight_util-2.0.1}/src/fosslight_util/convert_excel_to_yaml.py +1 -1
  7. fosslight_util-2.0.1/src/fosslight_util/correct.py +89 -0
  8. {fosslight_util-1.4.48 → fosslight_util-2.0.1}/src/fosslight_util/help.py +3 -4
  9. fosslight_util-2.0.1/src/fosslight_util/oss_item.py +221 -0
  10. {fosslight_util-1.4.48 → fosslight_util-2.0.1}/src/fosslight_util/output_format.py +88 -12
  11. {fosslight_util-1.4.48 → fosslight_util-2.0.1}/src/fosslight_util/parsing_yaml.py +45 -30
  12. {fosslight_util-1.4.48 → fosslight_util-2.0.1}/src/fosslight_util/read_excel.py +29 -35
  13. {fosslight_util-1.4.48 → fosslight_util-2.0.1}/src/fosslight_util/set_log.py +20 -3
  14. {fosslight_util-1.4.48 → fosslight_util-2.0.1}/src/fosslight_util/spdx_licenses.py +2 -1
  15. fosslight_util-2.0.1/src/fosslight_util/write_excel.py +245 -0
  16. {fosslight_util-1.4.48 → fosslight_util-2.0.1}/src/fosslight_util/write_opossum.py +14 -20
  17. fosslight_util-2.0.1/src/fosslight_util/write_scancodejson.py +64 -0
  18. fosslight_util-2.0.1/src/fosslight_util/write_spdx.py +259 -0
  19. {fosslight_util-1.4.48 → fosslight_util-2.0.1}/src/fosslight_util/write_txt.py +2 -1
  20. fosslight_util-2.0.1/src/fosslight_util/write_yaml.py +91 -0
  21. {fosslight_util-1.4.48 → fosslight_util-2.0.1}/src/fosslight_util.egg-info/PKG-INFO +1 -1
  22. {fosslight_util-1.4.48 → fosslight_util-2.0.1}/src/fosslight_util.egg-info/requires.txt +1 -2
  23. fosslight_util-1.4.48/src/fosslight_util/correct.py +0 -133
  24. fosslight_util-1.4.48/src/fosslight_util/oss_item.py +0 -226
  25. fosslight_util-1.4.48/src/fosslight_util/write_excel.py +0 -313
  26. fosslight_util-1.4.48/src/fosslight_util/write_scancodejson.py +0 -64
  27. fosslight_util-1.4.48/src/fosslight_util/write_spdx.py +0 -227
  28. fosslight_util-1.4.48/src/fosslight_util/write_yaml.py +0 -102
  29. {fosslight_util-1.4.48 → fosslight_util-2.0.1}/LICENSE +0 -0
  30. {fosslight_util-1.4.48 → fosslight_util-2.0.1}/MANIFEST.in +0 -0
  31. {fosslight_util-1.4.48 → fosslight_util-2.0.1}/README.md +0 -0
  32. {fosslight_util-1.4.48 → fosslight_util-2.0.1}/setup.cfg +0 -0
  33. {fosslight_util-1.4.48 → fosslight_util-2.0.1}/src/fosslight_util/__init__.py +0 -0
  34. {fosslight_util-1.4.48 → fosslight_util-2.0.1}/src/fosslight_util/_get_downloadable_url.py +0 -0
  35. {fosslight_util-1.4.48 → fosslight_util-2.0.1}/src/fosslight_util/cover.py +0 -0
  36. {fosslight_util-1.4.48 → fosslight_util-2.0.1}/src/fosslight_util/download.py +0 -0
  37. {fosslight_util-1.4.48 → fosslight_util-2.0.1}/src/fosslight_util/resources/frequentLicenselist.json +0 -0
  38. {fosslight_util-1.4.48 → fosslight_util-2.0.1}/src/fosslight_util/resources/frequent_license_nick_list.json +0 -0
  39. {fosslight_util-1.4.48 → fosslight_util-2.0.1}/src/fosslight_util/resources/licenses.json +0 -0
  40. {fosslight_util-1.4.48 → fosslight_util-2.0.1}/src/fosslight_util/timer_thread.py +0 -0
  41. {fosslight_util-1.4.48 → fosslight_util-2.0.1}/src/fosslight_util.egg-info/SOURCES.txt +0 -0
  42. {fosslight_util-1.4.48 → fosslight_util-2.0.1}/src/fosslight_util.egg-info/dependency_links.txt +0 -0
  43. {fosslight_util-1.4.48 → fosslight_util-2.0.1}/src/fosslight_util.egg-info/entry_points.txt +0 -0
  44. {fosslight_util-1.4.48 → fosslight_util-2.0.1}/src/fosslight_util.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fosslight_util
3
- Version: 1.4.48
3
+ Version: 2.0.1
4
4
  Summary: FOSSLight Util
5
5
  Home-page: https://github.com/fosslight/fosslight_util
6
6
  Author: LG Electronics
@@ -1,6 +1,5 @@
1
1
  XlsxWriter
2
2
  pandas
3
- xlrd==1.2.0
4
3
  openpyxl
5
4
  progress
6
5
  PyYAML
@@ -9,7 +8,7 @@ coloredlogs
9
8
  python3-wget
10
9
  beautifulsoup4
11
10
  jsonmerge
12
- spdx-tools==0.7.0rc0
11
+ spdx-tools
13
12
  setuptools>=65.5.1 # not directly required, pinned by Snyk to avoid a vulnerability
14
13
  numpy; python_version < '3.8'
15
14
  numpy>=1.22.2; python_version >= '3.8'
@@ -14,7 +14,7 @@ with open('requirements.txt', 'r', 'utf-8') as f:
14
14
  if __name__ == "__main__":
15
15
  setup(
16
16
  name='fosslight_util',
17
- version='1.4.48',
17
+ version='2.0.1',
18
18
  package_dir={"": "src"},
19
19
  packages=find_packages(where='src'),
20
20
  description='FOSSLight Util',
@@ -4,9 +4,7 @@
4
4
  # SPDX-License-Identifier: Apache-2.0
5
5
 
6
6
  import logging
7
- import os
8
7
  from fosslight_util.constant import LOGGER_NAME
9
- from fosslight_util.parsing_yaml import parsing_yml
10
8
 
11
9
  logger = logging.getLogger(LOGGER_NAME)
12
10
  VERSION = 'version'
@@ -14,12 +12,16 @@ LICENSE = 'license'
14
12
  NAME = 'name'
15
13
 
16
14
 
17
- def compare_yaml(before_file, after_file):
18
- before_oss_items, _, _ = parsing_yml(before_file, os.path.dirname(before_file))
19
- after_oss_items, _, _ = parsing_yml(after_file, os.path.dirname(after_file))
15
+ def compare_yaml(before_fileitems, after_fileitems):
16
+ bf_raw = []
17
+ af_raw = []
18
+ for bf in before_fileitems:
19
+ bf_raw.extend(bf.get_print_json())
20
+ for af in after_fileitems:
21
+ af_raw.extend(af.get_print_json())
20
22
 
21
- before_items = get_merged_item(before_oss_items)
22
- after_items = get_merged_item(after_oss_items)
23
+ before_items = get_merged_item(bf_raw)
24
+ after_items = get_merged_item(af_raw)
23
25
 
24
26
  new_before = []
25
27
  for bi in before_items:
@@ -72,13 +74,18 @@ def compare_yaml(before_file, after_file):
72
74
  def get_merged_item(oss_items):
73
75
  item_list = []
74
76
  for oi in oss_items:
75
- if oi.exclude:
77
+ if oi.get("exclude", None):
76
78
  continue
77
- item_info = {NAME: oi.name, VERSION: oi.version, LICENSE: oi.license}
79
+ oi_name = oi.get("name", '')
80
+ oi_version = oi.get("version", '')
81
+ oi_license = oi.get("license", '')
82
+ if not (oi_name and oi_version and oi_license):
83
+ continue
84
+ item_info = {NAME: oi_name, VERSION: oi_version, LICENSE: oi_license}
78
85
 
79
- filtered = next(filter(lambda oss_dict: oss_dict[NAME] == oi.name and oss_dict[VERSION] == oi.version, item_list), None)
86
+ filtered = next(filter(lambda oss_dict: oss_dict[NAME] == oi_name and oss_dict[VERSION] == oi_version, item_list), None)
80
87
  if filtered:
81
- filtered[LICENSE].extend(oi.license)
88
+ filtered[LICENSE].extend(oi_license)
82
89
  filtered[LICENSE] = list(set(filtered[LICENSE]))
83
90
  else:
84
91
  item_list.append(item_info)
@@ -15,6 +15,17 @@ supported_sheet_and_scanner = {'SRC': FL_SOURCE,
15
15
  f'BIN_{FL_BINARY}': FL_BINARY,
16
16
  f'DEP_{FL_DEPENDENCY}': FL_DEPENDENCY}
17
17
 
18
+ FOSSLIGHT_SCANNER = 'fosslight_scanner'
19
+ FOSSLIGHT_SOURCE = 'fosslight_source'
20
+ FOSSLIGHT_DEPENDENCY = 'fosslight_dependency'
21
+ FOSSLIGHT_BINARY = 'fosslight_binary'
22
+
23
+ SHEET_NAME_FOR_SCANNER = {
24
+ FOSSLIGHT_SOURCE: 'SRC_FL_Source',
25
+ FOSSLIGHT_BINARY: 'BIN_FL_Binary',
26
+ FOSSLIGHT_DEPENDENCY: 'DEP_FL_Dependency'
27
+ }
28
+
18
29
  # Github : https://github.com/(owner)/(repo)
19
30
  # npm : https://www.npmjs.com/package/(package)/v/(version)
20
31
  # npm2 : https://www.npmjs.com/package/@(group)/(package)/v/(version)
@@ -33,7 +33,7 @@ def find_report_file(path_to_find):
33
33
  return ""
34
34
 
35
35
 
36
- def convert_excel_to_yaml(oss_report_to_read, output_file, sheet_names=""):
36
+ def convert_excel_to_yaml(oss_report_to_read: str, output_file: str, sheet_names: str = "") -> None:
37
37
  _file_extension = ".yaml"
38
38
  yaml_dict = {}
39
39
 
@@ -0,0 +1,89 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ # Copyright (c) 2023 LG Electronics Inc.
4
+ # SPDX-License-Identifier: Apache-2.0
5
+
6
+ import logging
7
+ import os
8
+ import copy
9
+ import re
10
+ from fosslight_util.constant import LOGGER_NAME, FOSSLIGHT_SOURCE
11
+ from fosslight_util.parsing_yaml import parsing_yml
12
+
13
+ logger = logging.getLogger(LOGGER_NAME)
14
+ SBOM_INFO_YAML = r"sbom(-|_)info[\s\S]*.ya?ml"
15
+
16
+
17
+ def correct_with_yaml(correct_filepath, path_to_scan, scan_item):
18
+ success = True
19
+ msg = ""
20
+ correct_yaml = ""
21
+ if correct_filepath == "":
22
+ correct_filepath = path_to_scan
23
+
24
+ path_to_scan = os.path.normpath(path_to_scan)
25
+ correct_filepath = os.path.normpath(correct_filepath)
26
+ for filename in os.listdir(correct_filepath):
27
+ if re.search(SBOM_INFO_YAML, filename, re.IGNORECASE):
28
+ correct_yaml = os.path.join(correct_filepath, filename)
29
+ break
30
+ if not correct_yaml:
31
+ msg = f"Cannot find sbom-info.yaml in {correct_filepath}."
32
+ success = False
33
+ return success, msg, scan_item
34
+
35
+ rel_path = os.path.relpath(path_to_scan, correct_filepath)
36
+
37
+ yaml_file_list, _, err_msg = parsing_yml(correct_yaml, os.path.dirname(correct_yaml), print_log=True)
38
+ find_match = False
39
+ for scanner_name, _ in scan_item.file_items.items():
40
+ correct_fileitems = []
41
+ exclude_fileitems = []
42
+ for yaml_file_item in yaml_file_list:
43
+ yaml_path_exists = False
44
+ if yaml_file_item.source_name_or_path == '':
45
+ if scanner_name == FOSSLIGHT_SOURCE:
46
+ correct_item = copy.deepcopy(yaml_file_item)
47
+ correct_item.comment = 'Added by sbom-info.yaml'
48
+ correct_fileitems.append(correct_item)
49
+ continue
50
+ for idx, scan_file_item in enumerate(scan_item.file_items[scanner_name]):
51
+ oss_rel_path = os.path.normpath(os.path.join(rel_path, scan_file_item.source_name_or_path))
52
+ yi_path = yaml_file_item.source_name_or_path
53
+ if ((os.path.normpath(yi_path) == os.path.normpath(oss_rel_path)) or
54
+ ((os.path.normpath(oss_rel_path).startswith(os.path.normpath(yi_path.rstrip('*')))))):
55
+ correct_item = copy.deepcopy(scan_file_item)
56
+ correct_item.exclude = yaml_file_item.exclude
57
+ correct_item.oss_items = copy.deepcopy(yaml_file_item.oss_items)
58
+ correct_item.comment = ''
59
+ correct_item.comment = 'Loaded from sbom-info.yaml'
60
+ correct_fileitems.append(correct_item)
61
+
62
+ yaml_path_exists = True
63
+ exclude_fileitems.append(idx)
64
+
65
+ if not yaml_path_exists:
66
+ correct_item = copy.deepcopy(yaml_file_item)
67
+ if os.path.exists(os.path.normpath(yaml_file_item.source_name_or_path)):
68
+ correct_item.comment = 'Loaded from sbom-info.yaml'
69
+ correct_fileitems.append(correct_item)
70
+ else:
71
+ if scanner_name == FOSSLIGHT_SOURCE:
72
+ correct_item.exclude = True
73
+ correct_item.comment = 'Added by sbom-info.yaml'
74
+ correct_fileitems.append(correct_item)
75
+ if correct_fileitems:
76
+ scan_item.append_file_items(correct_fileitems, scanner_name)
77
+ find_match = True
78
+ if exclude_fileitems:
79
+ exclude_fileitems = list(set(exclude_fileitems))
80
+ for e_idx in exclude_fileitems:
81
+ scan_item.file_items[scanner_name][e_idx].exclude = True
82
+ scan_item.file_items[scanner_name][e_idx].comment = 'Excluded by sbom-info.yaml'
83
+
84
+ if not find_match:
85
+ success = False
86
+ err_msg = 'No match items in sbom-info.yaml'
87
+ return success, err_msg, scan_item
88
+
89
+ return success, msg, scan_item
@@ -35,12 +35,11 @@ _HELP_MESSAGE_DOWNLOAD = """
35
35
 
36
36
 
37
37
  class PrintHelpMsg():
38
- message_suffix = ""
39
38
 
40
- def __init__(self, value):
39
+ def __init__(self, value: str = ""):
41
40
  self.message_suffix = value
42
41
 
43
- def print_help_msg(self, exitopt):
42
+ def print_help_msg(self, exitopt: bool) -> None:
44
43
  print(_HELP_MESSAGE_COMMON)
45
44
  print(self.message_suffix)
46
45
 
@@ -48,7 +47,7 @@ class PrintHelpMsg():
48
47
  sys.exit()
49
48
 
50
49
 
51
- def print_package_version(pkg_name, msg="", exitopt=True):
50
+ def print_package_version(pkg_name: str, msg: str = "", exitopt: bool = True) -> str:
52
51
  if msg == "":
53
52
  msg = f"{pkg_name} Version:"
54
53
  cur_version = pkg_resources.get_distribution(pkg_name).version
@@ -0,0 +1,221 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ # Copyright (c) 2021 LG Electronics Inc.
4
+ # SPDX-License-Identifier: Apache-2.0
5
+
6
+ import logging
7
+ import os
8
+ from fosslight_util.constant import LOGGER_NAME, FOSSLIGHT_SCANNER
9
+ from fosslight_util.cover import CoverItem
10
+ from typing import List, Dict
11
+
12
+ _logger = logging.getLogger(LOGGER_NAME)
13
+ CHECKSUM_NULL = "0"
14
+
15
+
16
+ class OssItem:
17
+
18
+ def __init__(self, name="", version="", license="", dl_url=""):
19
+ self.name = name
20
+ self.version = version
21
+ self._license = []
22
+ self.license = license
23
+ self.download_location = dl_url
24
+ self.exclude = False
25
+ self.comment = ""
26
+ self.homepage = ""
27
+ self._copyright = ""
28
+
29
+ def __del__(self):
30
+ pass
31
+
32
+ @property
33
+ def license(self):
34
+ return self._license
35
+
36
+ @license.setter
37
+ def license(self, value):
38
+ if value != "":
39
+ if not isinstance(value, list):
40
+ value = value.split(",")
41
+ self._license.extend(value)
42
+ self._license = [item.strip() for item in self._license]
43
+ self._license = list(set(self._license))
44
+
45
+ @property
46
+ def exclude(self):
47
+ return self._exclude
48
+
49
+ @exclude.setter
50
+ def exclude(self, value):
51
+ if value:
52
+ self._exclude = True
53
+ else:
54
+ self._exclude = False
55
+
56
+ @property
57
+ def copyright(self):
58
+ return self._copyright
59
+
60
+ @copyright.setter
61
+ def copyright(self, value):
62
+ if value != "":
63
+ if isinstance(value, list):
64
+ value = "\n".join(value)
65
+ value = value.strip()
66
+ self._copyright = value
67
+
68
+ @property
69
+ def version(self):
70
+ return self._version
71
+
72
+ @version.setter
73
+ def version(self, value):
74
+ if value:
75
+ self._version = str(value)
76
+ else:
77
+ self._version = ""
78
+
79
+ @property
80
+ def comment(self):
81
+ return self._comment
82
+
83
+ @comment.setter
84
+ def comment(self, value):
85
+ if not value:
86
+ self._comment = ""
87
+ else:
88
+ if self._comment:
89
+ self._comment = f"{self._comment} / {value}"
90
+ else:
91
+ self._comment = value
92
+
93
+
94
+ class FileItem:
95
+ def __init__(self, value):
96
+ self.relative_path = value
97
+ self.source_name_or_path = ""
98
+ self._exclude = False
99
+ self._comment = ""
100
+ self.is_binary = False
101
+ self.oss_items: List[OssItem] = []
102
+ self.checksum = CHECKSUM_NULL
103
+
104
+ def __del__(self):
105
+ pass
106
+
107
+ @property
108
+ def exclude(self):
109
+ return self._exclude
110
+
111
+ @exclude.setter
112
+ def exclude(self, value):
113
+ if value:
114
+ self._exclude = True
115
+ else:
116
+ self._exclude = False
117
+ for oss in self.oss_items:
118
+ oss.exclude = value
119
+
120
+ @property
121
+ def comment(self):
122
+ return self._comment
123
+
124
+ @comment.setter
125
+ def comment(self, value):
126
+ if not value:
127
+ self._comment = ""
128
+ else:
129
+ if self._comment:
130
+ self._comment = f"{self._comment} / {value}"
131
+ else:
132
+ self._comment = value
133
+ for oss in self.oss_items:
134
+ oss.comment = value
135
+
136
+ def get_print_array(self):
137
+ items = []
138
+
139
+ for oss in self.oss_items:
140
+ exclude = "Exclude" if self.exclude or oss.exclude else ""
141
+ lic = ",".join(oss.license)
142
+
143
+ oss_item = [os.path.join(self.relative_path, self.source_name_or_path), oss.name, oss.version, lic,
144
+ oss.download_location, oss.homepage, oss.copyright, exclude, oss.comment]
145
+ items.append(oss_item)
146
+ return items
147
+
148
+ def get_print_json(self):
149
+ items = []
150
+
151
+ for oss in self.oss_items:
152
+ json_item = {}
153
+ json_item["name"] = oss.name
154
+ json_item["version"] = oss.version
155
+
156
+ if self.source_name_or_path != "":
157
+ json_item["source path"] = self.source_name_or_path
158
+ if len(oss.license) > 0:
159
+ json_item["license"] = oss.license
160
+ if oss.download_location != "":
161
+ json_item["download location"] = oss.download_location
162
+ if oss.homepage != "":
163
+ json_item["homepage"] = oss.homepage
164
+ if oss.copyright != "":
165
+ json_item["copyright text"] = oss.copyright
166
+ if self.exclude or oss.exclude:
167
+ json_item["exclude"] = True
168
+ if oss.comment != "":
169
+ json_item["comment"] = oss.comment
170
+ items.append(json_item)
171
+ return items
172
+
173
+
174
+ def invalid(cmd):
175
+ _logger.info('[{}] is invalid'.format(cmd))
176
+
177
+
178
+ class ScannerItem:
179
+ def __init__(self, pkg_name, start_time=""):
180
+ self.cover = CoverItem(tool_name=pkg_name, start_time=start_time)
181
+ self.file_items: Dict[str, List[FileItem]] = {pkg_name: []} if pkg_name != FOSSLIGHT_SCANNER else {}
182
+ self.external_sheets: Dict[str, List[List[str]]] = {}
183
+
184
+ def set_cover_pathinfo(self, input_dir, path_to_exclude):
185
+ self.cover.input_path = input_dir
186
+ self.cover.exclude_path = ", ".join(path_to_exclude)
187
+
188
+ def set_cover_comment(self, value):
189
+ if value:
190
+ if self.cover.comment:
191
+ self.cover.comment = f"{self.cover.comment} / {value}"
192
+ else:
193
+ self.cover.comment = value
194
+
195
+ def get_cover_comment(self):
196
+ return [item.strip() for item in self.cover.comment.split(" / ")]
197
+
198
+ def append_file_items(self, file_item: List[FileItem], pkg_name=""):
199
+ if pkg_name == "":
200
+ if len(self.file_items.keys()) != 1:
201
+ _logger.error("Package name is not set. Cannot append file_item into ScannerItem.")
202
+ else:
203
+ pkg_name = list(self.file_items.keys())[0]
204
+ if pkg_name not in self.file_items:
205
+ self.file_items[pkg_name] = []
206
+ self.file_items[pkg_name].extend(file_item)
207
+
208
+ def get_print_array(self, scanner_name):
209
+ items = []
210
+ for file_item in self.file_items[scanner_name]:
211
+ items.extend(file_item.get_print_array())
212
+ return items
213
+
214
+ def get_print_json(self, scanner_name):
215
+ items = []
216
+ for file_item in self.file_items[scanner_name]:
217
+ items.extend(file_item.get_print_json())
218
+ return items
219
+
220
+ def __del__(self):
221
+ pass
@@ -3,11 +3,16 @@
3
3
  # Copyright (c) 2021 LG Electronics Inc.
4
4
  # SPDX-License-Identifier: Apache-2.0
5
5
  import os
6
+ import platform
6
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 typing import Tuple
9
12
 
10
- SUPPORT_FORMAT = {'excel': '.xlsx', 'csv': '.csv', 'opossum': '.json', 'yaml': '.yaml'}
13
+ SUPPORT_FORMAT = {'excel': '.xlsx', 'csv': '.csv', 'opossum': '.json', 'yaml': '.yaml',
14
+ 'spdx-yaml': '.yaml', 'spdx-json': '.json', 'spdx-xml': '.xml',
15
+ 'spdx-tag': '.tag'}
11
16
 
12
17
 
13
18
  def check_output_format(output='', format='', customized_format={}):
@@ -105,7 +110,62 @@ def check_output_formats(output='', formats=[], customized_format={}):
105
110
  return success, msg, output_path, output_files, output_extensions
106
111
 
107
112
 
108
- def write_output_file(output_file_without_ext, file_extension, sheet_list, extended_header={}, hide_header={}, cover=""):
113
+ def check_output_formats_v2(output='', formats=[], customized_format={}):
114
+ success = True
115
+ msg = ''
116
+ output_path = ''
117
+ output_files = []
118
+ output_extensions = []
119
+
120
+ if customized_format:
121
+ support_format = customized_format
122
+ else:
123
+ support_format = SUPPORT_FORMAT
124
+
125
+ if formats:
126
+ # If -f option exist
127
+ formats = [format.lower() for format in formats]
128
+ for format in formats:
129
+ if format not in list(support_format.keys()):
130
+ success = False
131
+ msg = 'Enter the supported format with -f option: ' + ', '.join(list(support_format.keys()))
132
+ else:
133
+ output_extensions.append(support_format[format])
134
+
135
+ if success:
136
+ if output != '':
137
+ basename_extension = ''
138
+ if not os.path.isdir(output):
139
+ output_path = os.path.dirname(output)
140
+
141
+ basename = os.path.basename(output)
142
+ basename_file, basename_extension = os.path.splitext(basename)
143
+ if basename_extension:
144
+ if formats:
145
+ if basename_extension not in output_extensions:
146
+ success = False
147
+ msg = f"The format of output file(-o:'{output}') should be in the format list(-f:'{formats}')."
148
+ else:
149
+ if basename_extension not in support_format.values():
150
+ success = False
151
+ msg = 'Enter the supported file extension: ' + ', '.join(list(support_format.values()))
152
+ output_extensions.append(basename_extension)
153
+ output_files = [basename_file for _ in range(len(output_extensions))]
154
+ else:
155
+ output_path = output
156
+ if not output_extensions:
157
+ output_extensions = ['.xlsx']
158
+ if not formats:
159
+ for ext in output_extensions:
160
+ for key, value in support_format.items():
161
+ if value == ext:
162
+ formats.append(key)
163
+ break
164
+ return success, msg, output_path, output_files, output_extensions, formats
165
+
166
+
167
+ def write_output_file(output_file_without_ext: str, file_extension: str, scan_item, extended_header: dict = {},
168
+ hide_header: dict = {}, format: str = '', spdx_version: str = '2.3') -> Tuple[bool, str, str]:
109
169
  success = True
110
170
  msg = ''
111
171
 
@@ -113,16 +173,32 @@ def write_output_file(output_file_without_ext, file_extension, sheet_list, exten
113
173
  file_extension = '.xlsx'
114
174
  result_file = output_file_without_ext + file_extension
115
175
 
116
- if file_extension == '.xlsx':
117
- success, msg = write_result_to_excel(result_file, sheet_list, extended_header, hide_header, cover)
118
- elif file_extension == '.csv':
119
- success, msg, result_file = write_result_to_csv(result_file, sheet_list, False, extended_header)
120
- elif file_extension == '.json':
121
- success, msg = write_opossum(result_file, sheet_list)
122
- elif file_extension == '.yaml':
123
- success, msg, result_file = write_yaml(result_file, sheet_list, False)
176
+ if format:
177
+ if format == 'excel':
178
+ success, msg = write_result_to_excel(result_file, scan_item, extended_header, hide_header)
179
+ elif format == 'csv':
180
+ success, msg, _ = write_result_to_csv(result_file, scan_item, False, extended_header)
181
+ elif format == 'opossum':
182
+ success, msg = write_opossum(result_file, scan_item)
183
+ elif format == 'yaml':
184
+ success, msg, _ = write_yaml(result_file, scan_item, False)
185
+ elif format.startswith('spdx'):
186
+ if platform.system() != 'Windows':
187
+ success, msg, _ = write_spdx(output_file_without_ext, file_extension, scan_item, spdx_version)
188
+ else:
189
+ success = False
190
+ msg = 'Windows not support spdx format.'
124
191
  else:
125
- success = False
126
- msg = f'Not supported file extension({file_extension})'
192
+ if file_extension == '.xlsx':
193
+ success, msg = write_result_to_excel(result_file, scan_item, extended_header, hide_header)
194
+ elif file_extension == '.csv':
195
+ success, msg, result_file = write_result_to_csv(result_file, scan_item, False, extended_header)
196
+ elif file_extension == '.json':
197
+ success, msg = write_opossum(result_file, scan_item)
198
+ elif file_extension == '.yaml':
199
+ success, msg, result_file = write_yaml(result_file, scan_item, False)
200
+ else:
201
+ success = False
202
+ msg = f'Not supported file extension({file_extension})'
127
203
 
128
204
  return success, msg, result_file