fosslight-util 2.0.0__py3-none-any.whl → 2.1.29__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.
@@ -5,11 +5,13 @@
5
5
 
6
6
  import logging
7
7
  import os
8
+ import hashlib
8
9
  from fosslight_util.constant import LOGGER_NAME, FOSSLIGHT_SCANNER
9
10
  from fosslight_util.cover import CoverItem
10
11
  from typing import List, Dict
11
12
 
12
13
  _logger = logging.getLogger(LOGGER_NAME)
14
+ CHECKSUM_NULL = "0"
13
15
 
14
16
 
15
17
  class OssItem:
@@ -58,10 +60,12 @@ class OssItem:
58
60
 
59
61
  @copyright.setter
60
62
  def copyright(self, value):
61
- if value != "":
63
+ if value:
62
64
  if isinstance(value, list):
63
- value = "\n".join(value)
64
- value = value.strip()
65
+ value = list(set(value))
66
+ else:
67
+ value = set(value.split("\n"))
68
+ value = "\n".join(value).strip()
65
69
  self._copyright = value
66
70
 
67
71
  @property
@@ -98,6 +102,7 @@ class FileItem:
98
102
  self._comment = ""
99
103
  self.is_binary = False
100
104
  self.oss_items: List[OssItem] = []
105
+ self.checksum = CHECKSUM_NULL
101
106
 
102
107
  def __del__(self):
103
108
  pass
@@ -169,6 +174,22 @@ class FileItem:
169
174
  return items
170
175
 
171
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
191
+
192
+
172
193
  def invalid(cmd):
173
194
  _logger.info('[{}] is invalid'.format(cmd))
174
195
 
@@ -3,12 +3,17 @@
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 fosslight_util.write_cyclonedx import write_cyclonedx
9
12
  from typing import Tuple
10
13
 
11
- 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'}
12
17
 
13
18
 
14
19
  def check_output_format(output='', format='', customized_format={}):
@@ -27,7 +32,7 @@ def check_output_format(output='', format='', customized_format={}):
27
32
  format = format.lower()
28
33
  if format not in list(support_format.keys()):
29
34
  success = False
30
- msg = 'Enter the supported format with -f option: ' + ', '.join(list(support_format.keys()))
35
+ msg = '(-f option) Enter the supported format: ' + ', '.join(list(support_format.keys()))
31
36
  else:
32
37
  output_extension = support_format[format]
33
38
 
@@ -43,11 +48,12 @@ def check_output_format(output='', format='', customized_format={}):
43
48
  if format:
44
49
  if output_extension != basename_extension:
45
50
  success = False
46
- msg = f"Enter the same extension of output file(-o:'{output}') with format(-f:'{format}')."
51
+ msg = f"(-o & -f option) Enter the same extension of output file(-o:'{output}') \
52
+ with format(-f:'{format}')."
47
53
  else:
48
54
  if basename_extension not in support_format.values():
49
55
  success = False
50
- 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()))
51
57
  if success:
52
58
  output_file = basename_file
53
59
  output_extension = basename_extension
@@ -75,7 +81,7 @@ def check_output_formats(output='', formats=[], customized_format={}):
75
81
  for format in formats:
76
82
  if format not in list(support_format.keys()):
77
83
  success = False
78
- msg = 'Enter the supported format with -f option: ' + ', '.join(list(support_format.keys()))
84
+ msg = '(-f option) Enter the supported format: ' + ', '.join(list(support_format.keys()))
79
85
  else:
80
86
  output_extensions.append(support_format[format])
81
87
 
@@ -91,11 +97,12 @@ def check_output_formats(output='', formats=[], customized_format={}):
91
97
  if formats:
92
98
  if basename_extension not in output_extensions:
93
99
  success = False
94
- msg = f"The format of output file(-o:'{output}') should be in the format list(-f:'{formats}')."
100
+ msg = f"(-o & -f option) The format of output file(-o:'{output}') \
101
+ should be in the format list(-f:'{formats}')."
95
102
  else:
96
103
  if basename_extension not in support_format.values():
97
104
  success = False
98
- msg = 'Enter the supported file extension: ' + ', '.join(list(support_format.values()))
105
+ msg = '(-o option) Enter the supported file extension: ' + ', '.join(list(support_format.values()))
99
106
  output_extensions.append(basename_extension)
100
107
  output_files = [basename_file for _ in range(len(output_extensions))]
101
108
  else:
@@ -106,8 +113,64 @@ def check_output_formats(output='', formats=[], customized_format={}):
106
113
  return success, msg, output_path, output_files, output_extensions
107
114
 
108
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
+
109
172
  def write_output_file(output_file_without_ext: str, file_extension: str, scan_item, extended_header: dict = {},
110
- hide_header: dict = {}) -> Tuple[bool, str, str]:
173
+ hide_header: dict = {}, format: str = '', spdx_version: str = '2.3') -> Tuple[bool, str, str]:
111
174
  success = True
112
175
  msg = ''
113
176
 
@@ -115,16 +178,35 @@ def write_output_file(output_file_without_ext: str, file_extension: str, scan_it
115
178
  file_extension = '.xlsx'
116
179
  result_file = output_file_without_ext + file_extension
117
180
 
118
- if file_extension == '.xlsx':
119
- success, msg = write_result_to_excel(result_file, scan_item, extended_header, hide_header)
120
- elif file_extension == '.csv':
121
- success, msg, result_file = write_result_to_csv(result_file, scan_item, False, extended_header)
122
- elif file_extension == '.json':
123
- success, msg = write_opossum(result_file, scan_item)
124
- elif file_extension == '.yaml':
125
- success, msg, result_file = write_yaml(result_file, scan_item, False)
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)
126
199
  else:
127
- success = False
128
- msg = f'Not supported file extension({file_extension})'
200
+ if file_extension == '.xlsx':
201
+ success, msg = write_result_to_excel(result_file, scan_item, extended_header, hide_header)
202
+ elif file_extension == '.csv':
203
+ success, msg, result_file = write_result_to_csv(result_file, scan_item, False, extended_header)
204
+ elif file_extension == '.json':
205
+ success, msg = write_opossum(result_file, scan_item)
206
+ elif file_extension == '.yaml':
207
+ success, msg, result_file = write_yaml(result_file, scan_item, False)
208
+ else:
209
+ success = False
210
+ msg = f'(-f option) Not supported file extension({file_extension})'
129
211
 
130
212
  return success, msg, result_file
fosslight_util/set_log.py CHANGED
@@ -6,7 +6,6 @@
6
6
  import logging
7
7
  import os
8
8
  from pathlib import Path
9
- import pkg_resources
10
9
  import sys
11
10
  import platform
12
11
  from . import constant as constant
@@ -15,6 +14,11 @@ import coloredlogs
15
14
  from typing import Tuple
16
15
  from logging import Logger
17
16
 
17
+ try:
18
+ from importlib.metadata import version, PackageNotFoundError
19
+ except ImportError:
20
+ from importlib_metadata import version, PackageNotFoundError # Python <3.8
21
+
18
22
 
19
23
  def init_check_latest_version(pkg_version="", main_package_name=""):
20
24
 
@@ -92,9 +96,11 @@ def init_log(log_file: str, create_file: bool = True, stream_log_level: int = lo
92
96
  if main_package_name != "":
93
97
  pkg_info = main_package_name
94
98
  try:
95
- pkg_version = pkg_resources.get_distribution(main_package_name).version
99
+ pkg_version = version(main_package_name)
96
100
  init_check_latest_version(pkg_version, main_package_name)
97
101
  pkg_info = main_package_name + " v" + pkg_version
102
+ except PackageNotFoundError:
103
+ logger.debug('Cannot check the version: Package not found')
98
104
  except Exception as error:
99
105
  logger.debug('Cannot check the version:' + str(error))
100
106
  _result_log["Tool Info"] = pkg_info
@@ -0,0 +1,210 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ # Copyright (c) 2024 LG Electronics Inc.
4
+ # Copyright (c) OWASP Foundation.
5
+ # SPDX-License-Identifier: Apache-2.0
6
+
7
+ import os
8
+ import logging
9
+ import re
10
+ from pathlib import Path
11
+ from fosslight_util.constant import (LOGGER_NAME, FOSSLIGHT_DEPENDENCY, FOSSLIGHT_SCANNER,
12
+ FOSSLIGHT_SOURCE)
13
+ import traceback
14
+
15
+ logger = logging.getLogger(LOGGER_NAME)
16
+
17
+ try:
18
+ from packageurl import PackageURL
19
+ from cyclonedx.builder.this import this_component as cdx_lib_component
20
+ from cyclonedx.exception import MissingOptionalDependencyException
21
+ from cyclonedx.factory.license import LicenseFactory
22
+ from cyclonedx.model import XsUri, ExternalReferenceType
23
+ from cyclonedx.model.bom import Bom
24
+ from cyclonedx.model.component import Component, ComponentType, HashAlgorithm, HashType, ExternalReference
25
+ from cyclonedx.output import make_outputter, BaseOutput
26
+ from cyclonedx.output.json import JsonV1Dot6
27
+ from cyclonedx.schema import OutputFormat, SchemaVersion
28
+ from cyclonedx.validation.json import JsonStrictValidator
29
+ from cyclonedx.output.json import Json as JsonOutputter
30
+ from cyclonedx.validation.xml import XmlValidator
31
+ except Exception:
32
+ logger.info('No import cyclonedx-python-lib')
33
+
34
+
35
+ def write_cyclonedx(output_file_without_ext, output_extension, scan_item):
36
+ success = True
37
+ error_msg = ''
38
+
39
+ bom = Bom()
40
+ if scan_item:
41
+ try:
42
+ cover_name = scan_item.cover.get_print_json()["Tool information"].split('(').pop(0).strip()
43
+ match = re.search(r"(.+) v([0-9.]+)", cover_name)
44
+ if match:
45
+ scanner_name = match.group(1)
46
+ else:
47
+ scanner_name = FOSSLIGHT_SCANNER
48
+ except Exception:
49
+ cover_name = FOSSLIGHT_SCANNER
50
+ scanner_name = FOSSLIGHT_SCANNER
51
+
52
+ lc_factory = LicenseFactory()
53
+ bom.metadata.tools.components.add(cdx_lib_component())
54
+ bom.metadata.tools.components.add(Component(name=scanner_name.upper(),
55
+ type=ComponentType.APPLICATION))
56
+ comp_id = 0
57
+ bom.metadata.component = root_component = Component(name='Root Component',
58
+ type=ComponentType.APPLICATION,
59
+ bom_ref=str(comp_id))
60
+ relation_tree = {}
61
+
62
+ output_dir = os.path.dirname(output_file_without_ext)
63
+ Path(output_dir).mkdir(parents=True, exist_ok=True)
64
+ try:
65
+ root_package = False
66
+ for scanner_name, file_items in scan_item.file_items.items():
67
+ for file_item in file_items:
68
+ if file_item.exclude:
69
+ continue
70
+ if scanner_name == FOSSLIGHT_SOURCE:
71
+ comp_type = ComponentType.FILE
72
+ else:
73
+ comp_type = ComponentType.LIBRARY
74
+
75
+ for oss_item in file_item.oss_items:
76
+ if oss_item.name == '' or oss_item.name == '-':
77
+ if scanner_name == FOSSLIGHT_DEPENDENCY:
78
+ continue
79
+ else:
80
+ comp_name = file_item.source_name_or_path
81
+ else:
82
+ comp_name = oss_item.name
83
+
84
+ comp_id += 1
85
+ comp = Component(type=comp_type,
86
+ name=comp_name,
87
+ bom_ref=str(comp_id))
88
+
89
+ if oss_item.version != '':
90
+ comp.version = oss_item.version
91
+ if oss_item.copyright != '':
92
+ comp.copyright = oss_item.copyright
93
+ if scanner_name == FOSSLIGHT_DEPENDENCY and file_item.purl:
94
+ comp.purl = PackageURL.from_string(file_item.purl)
95
+ if scanner_name != FOSSLIGHT_DEPENDENCY:
96
+ if file_item.checksum != '0':
97
+ comp.hashes = [HashType(alg=HashAlgorithm.SHA_1, content=file_item.checksum)]
98
+
99
+ if oss_item.download_location != '':
100
+ comp.external_references = [ExternalReference(url=XsUri(oss_item.download_location),
101
+ type=ExternalReferenceType.WEBSITE)]
102
+
103
+ oss_licenses = []
104
+ for ol in oss_item.license:
105
+ try:
106
+ oss_licenses.append(lc_factory.make_from_string(ol))
107
+ except Exception:
108
+ logger.info(f'No spdx license name: {ol}')
109
+ if oss_licenses:
110
+ comp.licenses = oss_licenses
111
+
112
+ root_package = False
113
+ if scanner_name == FOSSLIGHT_DEPENDENCY:
114
+ if oss_item.comment:
115
+ oss_comment = oss_item.comment.split('/')
116
+ for oc in oss_comment:
117
+ if oc in ['direct', 'transitive', 'root package']:
118
+ if oc == 'direct':
119
+ bom.register_dependency(root_component, [comp])
120
+ elif oc == 'root package':
121
+ root_package = True
122
+ root_component.name = comp_name
123
+ root_component.type = comp_type
124
+ comp_id -= 1
125
+ else:
126
+ bom.register_dependency(root_component, [comp])
127
+ if len(file_item.depends_on) > 0:
128
+ purl = file_item.purl
129
+ relation_tree[purl] = []
130
+ relation_tree[purl].extend(file_item.depends_on)
131
+
132
+ if not root_package:
133
+ bom.components.add(comp)
134
+
135
+ if len(bom.components) > 0:
136
+ for comp_purl in relation_tree:
137
+ comp = bom.get_component_by_purl(PackageURL.from_string(comp_purl))
138
+ if comp:
139
+ dep_comp_list = []
140
+ for dep_comp_purl in relation_tree[comp_purl]:
141
+ dep_comp = bom.get_component_by_purl(PackageURL.from_string(dep_comp_purl))
142
+ if dep_comp:
143
+ dep_comp_list.append(dep_comp)
144
+ bom.register_dependency(comp, dep_comp_list)
145
+
146
+ except Exception as e:
147
+ success = False
148
+ error_msg = f'Failed to create CycloneDX document object:{e}, {traceback.format_exc()}'
149
+ else:
150
+ success = False
151
+ error_msg = 'No item to write in output file.'
152
+
153
+ result_file = ''
154
+ if success:
155
+ result_file = output_file_without_ext + output_extension
156
+ try:
157
+ if output_extension == '.json':
158
+ write_cyclonedx_json(bom, result_file)
159
+ elif output_extension == '.xml':
160
+ write_cyclonedx_xml(bom, result_file)
161
+ else:
162
+ success = False
163
+ error_msg = f'Not supported output_extension({output_extension})'
164
+ except Exception as e:
165
+ success = False
166
+ error_msg = f'Failed to write CycloneDX document: {e}'
167
+ if os.path.exists(result_file):
168
+ os.remove(result_file)
169
+
170
+ return success, error_msg, result_file
171
+
172
+
173
+ def write_cyclonedx_json(bom, result_file):
174
+ success = True
175
+ try:
176
+ my_json_outputter: 'JsonOutputter' = JsonV1Dot6(bom)
177
+ my_json_outputter.output_to_file(result_file)
178
+ serialized_json = my_json_outputter.output_as_string(indent=2)
179
+ my_json_validator = JsonStrictValidator(SchemaVersion.V1_6)
180
+ try:
181
+ validation_errors = my_json_validator.validate_str(serialized_json)
182
+ if validation_errors:
183
+ logger.warning(f'JSON invalid, ValidationError: {repr(validation_errors)}')
184
+ except MissingOptionalDependencyException as error:
185
+ logger.debug(f'JSON-validation was skipped due to {error}')
186
+ except Exception as e:
187
+ logger.warning(f'Fail to write cyclonedx json: {e}')
188
+ success = False
189
+ return success
190
+
191
+
192
+ def write_cyclonedx_xml(bom, result_file):
193
+ success = True
194
+ try:
195
+ my_xml_outputter: BaseOutput = make_outputter(bom=bom,
196
+ output_format=OutputFormat.XML,
197
+ schema_version=SchemaVersion.V1_6)
198
+ my_xml_outputter.output_to_file(filename=result_file)
199
+ serialized_xml = my_xml_outputter.output_as_string(indent=2)
200
+ my_xml_validator = XmlValidator(SchemaVersion.V1_6)
201
+ try:
202
+ validation_errors = my_xml_validator.validate_str(serialized_xml)
203
+ if validation_errors:
204
+ logger.warning(f'XML invalid, ValidationError: {repr(validation_errors)}')
205
+ except MissingOptionalDependencyException as error:
206
+ logger.debug(f'XML-validation was skipped due to {error}')
207
+ except Exception as e:
208
+ logger.warning(f'Fail to write cyclonedx xml: {e}')
209
+ success = False
210
+ return success
@@ -34,6 +34,7 @@ IDX_FILE = 0
34
34
  IDX_EXCLUDE = 7
35
35
  logger = logging.getLogger(LOGGER_NAME)
36
36
  COVER_SHEET_NAME = 'Scanner Info'
37
+ MAX_EXCEL_URL_LENGTH = 255
37
38
 
38
39
 
39
40
  def get_header_row(sheet_name, extended_header={}):
@@ -181,7 +182,10 @@ def write_result_to_sheet(worksheet, sheet_contents):
181
182
  for row_item in sheet_contents:
182
183
  worksheet.write(row, 0, row)
183
184
  for col_num, value in enumerate(row_item):
184
- worksheet.write(row, col_num + 1, str(value))
185
+ if len(value) > MAX_EXCEL_URL_LENGTH and (value.startswith("http://") or value.startswith("https://")):
186
+ worksheet.write_string(row, col_num + 1, str(value))
187
+ else:
188
+ worksheet.write(row, col_num + 1, str(value))
185
189
  row += 1
186
190
 
187
191
 
@@ -6,7 +6,7 @@
6
6
  import logging
7
7
  import os
8
8
  import json
9
- from fosslight_util.constant import LOGGER_NAME
9
+ from fosslight_util.constant import LOGGER_NAME, FOSSLIGHT_DEPENDENCY
10
10
  from fosslight_util.oss_item import ScannerItem
11
11
  from typing import List
12
12
 
@@ -20,22 +20,27 @@ def write_scancodejson(output_dir: str, output_filename: str, oss_list: List[Sca
20
20
  json_output['summary'] = {}
21
21
  json_output['license_detections'] = []
22
22
  json_output['files'] = []
23
+ json_output['dependencies'] = []
23
24
 
24
- for file_items in oss_list.file_items.values():
25
+ for scanner, file_items in oss_list.file_items.items():
25
26
  for fi in file_items:
26
- if fi.exclude:
27
- continue
28
- if fi.oss_items and (all(oss_item.exclude for oss_item in fi.oss_items)):
29
- continue
30
- if not fi.source_name_or_path:
31
- fi.source_name_or_path = EMPTY_FILE_PATH
32
- json_output['files'] = add_item_in_files(fi, json_output['files'])
27
+ if scanner == FOSSLIGHT_DEPENDENCY:
28
+ json_output['dependencies'] = add_item_in_deps(fi, json_output['dependencies'])
29
+ else:
30
+ if fi.exclude:
31
+ continue
32
+ if fi.oss_items and (all(oss_item.exclude for oss_item in fi.oss_items)):
33
+ continue
34
+ if not fi.source_name_or_path:
35
+ fi.source_name_or_path = EMPTY_FILE_PATH
36
+ json_output['files'] = add_item_in_files(fi, json_output['files'])
33
37
 
34
38
  with open(os.path.join(output_dir, output_filename), 'w') as f:
35
39
  json.dump(json_output, f, sort_keys=False, indent=4)
36
40
 
37
41
 
38
- def append_oss_item_in_filesitem(oss_items, files_item):
42
+ def get_oss_item_list(oss_items):
43
+ scan_oss_items = []
39
44
  for oi in oss_items:
40
45
  if oi.exclude:
41
46
  continue
@@ -46,9 +51,9 @@ def append_oss_item_in_filesitem(oss_items, files_item):
46
51
  oss_item['copyright'] = oi.copyright
47
52
  oss_item['download_location'] = oi.download_location
48
53
  oss_item['comment'] = oi.comment
49
- files_item['oss'].append(oss_item)
54
+ scan_oss_items.append(oss_item)
50
55
 
51
- return files_item
56
+ return scan_oss_items
52
57
 
53
58
 
54
59
  def add_item_in_files(file_item, files_list):
@@ -57,8 +62,20 @@ def add_item_in_files(file_item, files_list):
57
62
  files_item['name'] = os.path.basename(file_item.source_name_or_path)
58
63
  files_item['is_binary'] = file_item.is_binary
59
64
  files_item['base_name'], files_item['extension'] = os.path.splitext(os.path.basename(file_item.source_name_or_path))
60
- files_item['oss'] = []
61
- files_item = append_oss_item_in_filesitem(file_item.oss_items, files_item)
65
+ files_item['oss'] = get_oss_item_list(file_item.oss_items)
66
+
62
67
  files_list.append(files_item)
63
68
 
64
69
  return files_list
70
+
71
+
72
+ def add_item_in_deps(file_item, deps_list):
73
+ deps_item = {}
74
+ deps_item['purl'] = file_item.purl
75
+ deps_item['scope'] = 'dependencies'
76
+ deps_item['depends_on'] = file_item.depends_on
77
+ deps_item['oss'] = get_oss_item_list(file_item.oss_items)
78
+
79
+ deps_list.append(deps_item)
80
+
81
+ return deps_list