scanoss 1.19.6__py3-none-any.whl → 1.20.1__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.
Files changed (71) hide show
  1. protoc_gen_swagger/__init__.py +13 -13
  2. protoc_gen_swagger/options/__init__.py +13 -13
  3. protoc_gen_swagger/options/annotations_pb2.py +12 -9
  4. protoc_gen_swagger/options/annotations_pb2_grpc.py +1 -1
  5. protoc_gen_swagger/options/openapiv2_pb2.py +98 -96
  6. protoc_gen_swagger/options/openapiv2_pb2_grpc.py +1 -1
  7. scanoss/__init__.py +18 -18
  8. scanoss/api/__init__.py +17 -17
  9. scanoss/api/common/__init__.py +17 -17
  10. scanoss/api/common/v2/__init__.py +17 -17
  11. scanoss/api/common/v2/scanoss_common_pb2.py +18 -18
  12. scanoss/api/common/v2/scanoss_common_pb2_grpc.py +1 -1
  13. scanoss/api/components/__init__.py +17 -17
  14. scanoss/api/components/v2/__init__.py +17 -17
  15. scanoss/api/components/v2/scanoss_components_pb2.py +48 -38
  16. scanoss/api/components/v2/scanoss_components_pb2_grpc.py +142 -96
  17. scanoss/api/cryptography/v2/scanoss_cryptography_pb2.py +22 -16
  18. scanoss/api/cryptography/v2/scanoss_cryptography_pb2_grpc.py +75 -49
  19. scanoss/api/dependencies/__init__.py +17 -17
  20. scanoss/api/dependencies/v2/__init__.py +17 -17
  21. scanoss/api/dependencies/v2/scanoss_dependencies_pb2.py +30 -24
  22. scanoss/api/dependencies/v2/scanoss_dependencies_pb2_grpc.py +75 -49
  23. scanoss/api/provenance/__init__.py +23 -0
  24. scanoss/api/provenance/v2/__init__.py +23 -0
  25. scanoss/api/provenance/v2/scanoss_provenance_pb2.py +42 -0
  26. scanoss/api/provenance/v2/scanoss_provenance_pb2_grpc.py +108 -0
  27. scanoss/api/scanning/__init__.py +17 -17
  28. scanoss/api/scanning/v2/__init__.py +17 -17
  29. scanoss/api/scanning/v2/scanoss_scanning_pb2.py +10 -8
  30. scanoss/api/scanning/v2/scanoss_scanning_pb2_grpc.py +40 -32
  31. scanoss/api/semgrep/__init__.py +17 -17
  32. scanoss/api/semgrep/v2/__init__.py +17 -17
  33. scanoss/api/semgrep/v2/scanoss_semgrep_pb2.py +22 -18
  34. scanoss/api/semgrep/v2/scanoss_semgrep_pb2_grpc.py +71 -49
  35. scanoss/api/vulnerabilities/__init__.py +17 -17
  36. scanoss/api/vulnerabilities/v2/__init__.py +17 -17
  37. scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2.py +37 -27
  38. scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2_grpc.py +109 -72
  39. scanoss/cli.py +578 -264
  40. scanoss/components.py +99 -48
  41. scanoss/csvoutput.py +83 -56
  42. scanoss/cyclonedx.py +48 -46
  43. scanoss/data/build_date.txt +1 -1
  44. scanoss/file_filters.py +13 -15
  45. scanoss/filecount.py +43 -36
  46. scanoss/inspection/__init__.py +17 -17
  47. scanoss/inspection/copyleft.py +71 -58
  48. scanoss/inspection/policy_check.py +76 -53
  49. scanoss/inspection/undeclared_component.py +98 -75
  50. scanoss/inspection/utils/license_utils.py +66 -44
  51. scanoss/results.py +51 -60
  52. scanoss/scancodedeps.py +61 -38
  53. scanoss/scanner.py +203 -135
  54. scanoss/scanoss_settings.py +5 -3
  55. scanoss/scanossapi.py +98 -69
  56. scanoss/scanossbase.py +19 -19
  57. scanoss/scanossgrpc.py +107 -51
  58. scanoss/scanpostprocessor.py +9 -6
  59. scanoss/scantype.py +22 -21
  60. scanoss/spdxlite.py +265 -171
  61. scanoss/threadeddependencies.py +91 -61
  62. scanoss/threadedscanning.py +37 -31
  63. scanoss/utils/file.py +4 -4
  64. scanoss/winnowing.py +111 -47
  65. {scanoss-1.19.6.dist-info → scanoss-1.20.1.dist-info}/METADATA +1 -1
  66. scanoss-1.20.1.dist-info/RECORD +74 -0
  67. scanoss-1.19.6.dist-info/RECORD +0 -70
  68. {scanoss-1.19.6.dist-info → scanoss-1.20.1.dist-info}/LICENSE +0 -0
  69. {scanoss-1.19.6.dist-info → scanoss-1.20.1.dist-info}/WHEEL +0 -0
  70. {scanoss-1.19.6.dist-info → scanoss-1.20.1.dist-info}/entry_points.txt +0 -0
  71. {scanoss-1.19.6.dist-info → scanoss-1.20.1.dist-info}/top_level.txt +0 -0
@@ -1,26 +1,27 @@
1
1
  """
2
- SPDX-License-Identifier: MIT
3
-
4
- Copyright (c) 2024, SCANOSS
5
-
6
- Permission is hereby granted, free of charge, to any person obtaining a copy
7
- of this software and associated documentation files (the "Software"), to deal
8
- in the Software without restriction, including without limitation the rights
9
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
- copies of the Software, and to permit persons to whom the Software is
11
- furnished to do so, subject to the following conditions:
12
-
13
- The above copyright notice and this permission notice shall be included in
14
- all copies or substantial portions of the Software.
15
-
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
- THE SOFTWARE.
2
+ SPDX-License-Identifier: MIT
3
+
4
+ Copyright (c) 2024, SCANOSS
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in
14
+ all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ THE SOFTWARE.
23
23
  """
24
+
24
25
  import json
25
26
  import os.path
26
27
  from abc import abstractmethod
@@ -39,13 +40,17 @@ class PolicyStatus(Enum):
39
40
  FAIL (int): Indicates that the policy check failed (value: 1).
40
41
  ERROR (int): Indicates that an error occurred during the policy check (value: 2).
41
42
  """
43
+
42
44
  SUCCESS = 0
43
45
  FAIL = 1
44
46
  ERROR = 2
47
+
48
+
45
49
  #
46
50
  # End of PolicyStatus Class
47
51
  #
48
52
 
53
+
49
54
  class ComponentID(Enum):
50
55
  """
51
56
  Enumeration representing different types of software components.
@@ -55,13 +60,17 @@ class ComponentID(Enum):
55
60
  SNIPPET (str): Represents a code snippet component (value: "snippet").
56
61
  DEPENDENCY (str): Represents a dependency component (value: "dependency").
57
62
  """
58
- FILE = "file"
59
- SNIPPET = "snippet"
60
- DEPENDENCY = "dependency"
63
+
64
+ FILE = 'file'
65
+ SNIPPET = 'snippet'
66
+ DEPENDENCY = 'dependency'
67
+
68
+
61
69
  #
62
70
  # End of ComponentID Class
63
71
  #
64
72
 
73
+
65
74
  class PolicyCheck(ScanossBase):
66
75
  """
67
76
  A base class for implementing various software policy checks.
@@ -78,8 +87,17 @@ class PolicyCheck(ScanossBase):
78
87
 
79
88
  VALID_FORMATS = {'md', 'json', 'jira_md'}
80
89
 
81
- def __init__(self, debug: bool = False, trace: bool = True, quiet: bool = False, filepath: str = None,
82
- format_type: str = None, status: str = None, output: str = None, name: str = None):
90
+ def __init__(
91
+ self,
92
+ debug: bool = False,
93
+ trace: bool = True,
94
+ quiet: bool = False,
95
+ filepath: str = None,
96
+ format_type: str = None,
97
+ status: str = None,
98
+ output: str = None,
99
+ name: str = None,
100
+ ):
83
101
  super().__init__(debug, trace, quiet)
84
102
  self.license_util = LicenseUtil()
85
103
  self.filepath = filepath
@@ -110,14 +128,14 @@ class PolicyCheck(ScanossBase):
110
128
  @abstractmethod
111
129
  def _json(self, components: list) -> Dict[str, Any]:
112
130
  """
113
- Format the policy checks results as JSON.
114
- This method should be implemented by subclasses to create a Markdown representation
115
- of the policy check results.
116
-
117
- :param components: List of components to be formatted.
118
- :return: A dictionary containing two keys:
119
- - 'details': A JSON-formatted string with the full list of components
120
- - 'summary': A string summarizing the number of components found
131
+ Format the policy checks results as JSON.
132
+ This method should be implemented by subclasses to create a Markdown representation
133
+ of the policy check results.
134
+
135
+ :param components: List of components to be formatted.
136
+ :return: A dictionary containing two keys:
137
+ - 'details': A JSON-formatted string with the full list of components
138
+ - 'summary': A string summarizing the number of components found
121
139
  """
122
140
  pass
123
141
 
@@ -147,8 +165,9 @@ class PolicyCheck(ScanossBase):
147
165
  """
148
166
  pass
149
167
 
150
- def _append_component(self,components: Dict[str, Any], new_component: Dict[str, Any],
151
- id: str, status: str) -> Dict[str, Any]:
168
+ def _append_component(
169
+ self, components: Dict[str, Any], new_component: Dict[str, Any], id: str, status: str
170
+ ) -> Dict[str, Any]:
152
171
  """
153
172
  Append a new component to the component's dictionary.
154
173
 
@@ -169,12 +188,12 @@ class PolicyCheck(ScanossBase):
169
188
  else:
170
189
  purl = new_component['purl']
171
190
 
172
- component_key = f"{purl}@{new_component['version']}"
191
+ component_key = f'{purl}@{new_component["version"]}'
173
192
  components[component_key] = {
174
- 'purl': purl,
175
- 'version': new_component['version'],
176
- 'licenses': {},
177
- 'status': status,
193
+ 'purl': purl,
194
+ 'version': new_component['version'],
195
+ 'licenses': {},
196
+ 'status': status,
178
197
  }
179
198
 
180
199
  if not new_component.get('licenses'):
@@ -191,16 +210,16 @@ class PolicyCheck(ScanossBase):
191
210
  }
192
211
  return components
193
212
 
194
- def _get_components_from_results(self,results: Dict[str, Any]) -> list or None:
213
+ def _get_components_from_results(self, results: Dict[str, Any]) -> list or None:
195
214
  """
196
- Process the results dictionary to extract and format component information.
215
+ Process the results dictionary to extract and format component information.
197
216
 
198
- This function iterates through the results dictionary, identifying components from
199
- different sources (files, snippets, and dependencies). It consolidates this information
200
- into a list of unique components, each with its associated licenses and other details.
217
+ This function iterates through the results dictionary, identifying components from
218
+ different sources (files, snippets, and dependencies). It consolidates this information
219
+ into a list of unique components, each with its associated licenses and other details.
201
220
 
202
- :param results: A dictionary containing the raw results of a component scan
203
- :return: A list of dictionaries, each representing a unique component with its details
221
+ :param results: A dictionary containing the raw results of a component scan
222
+ :return: A list of dictionaries, each representing a unique component with its details
204
223
  """
205
224
  if results is None:
206
225
  self.print_stderr(f'ERROR: Results cannot be empty')
@@ -226,7 +245,7 @@ class PolicyCheck(ScanossBase):
226
245
  if not c.get('version'):
227
246
  self.print_stderr(f'WARNING: Result missing version. Skipping.')
228
247
  continue
229
- component_key = f"{c['purl'][0]}@{c['version']}"
248
+ component_key = f'{c["purl"][0]}@{c["version"]}'
230
249
  # Initialize or update the component entry
231
250
  if component_key not in components:
232
251
  components = self._append_component(components, c, component_id, status)
@@ -244,7 +263,7 @@ class PolicyCheck(ScanossBase):
244
263
  if not d.get('version'):
245
264
  self.print_stderr(f'WARNING: Result missing version. Skipping.')
246
265
  continue
247
- component_key = f"{d['purl']}@{d['version']}"
266
+ component_key = f'{d["purl"]}@{d["version"]}'
248
267
  if component_key not in components:
249
268
  components = self._append_component(components, d, component_id, status)
250
269
  # End of dependencies loop
@@ -271,11 +290,13 @@ class PolicyCheck(ScanossBase):
271
290
  if headers is None:
272
291
  self.print_stderr('ERROR: Header are no set')
273
292
  return None
293
+
274
294
  # Decide which separator to use
275
295
  def create_separator(index):
276
296
  if centered_columns is None:
277
297
  return '-'
278
298
  return ':-:' if index in centered_column_set else '-'
299
+
279
300
  # Build the row separator
280
301
  row_separator = col_sep + col_sep.join(create_separator(index) for index, _ in enumerate(headers)) + col_sep
281
302
  # build table rows
@@ -297,7 +318,7 @@ class PolicyCheck(ScanossBase):
297
318
 
298
319
  return table
299
320
 
300
- def _get_formatter(self)-> Callable[[List[dict]], Dict[str,Any]] or None:
321
+ def _get_formatter(self) -> Callable[[List[dict]], Dict[str, Any]] or None:
301
322
  """
302
323
  Get the appropriate formatter function based on the specified format.
303
324
 
@@ -348,11 +369,11 @@ class PolicyCheck(ScanossBase):
348
369
 
349
370
  Returns:
350
371
  Dict[str, Any]: The parsed JSON data
351
- """
372
+ """
352
373
  if not os.path.exists(self.filepath):
353
374
  self.print_stderr(f'ERROR: The file "{self.filepath}" does not exist.')
354
375
  return None
355
- with open(self.filepath, "r") as jsonfile:
376
+ with open(self.filepath, 'r') as jsonfile:
356
377
  try:
357
378
  return json.load(jsonfile)
358
379
  except Exception as e:
@@ -381,6 +402,8 @@ class PolicyCheck(ScanossBase):
381
402
  return None
382
403
  components = self._get_components_from_results(self.results)
383
404
  return components
405
+
406
+
384
407
  #
385
408
  # End of PolicyCheck Class
386
409
  #
@@ -1,38 +1,49 @@
1
1
  """
2
- SPDX-License-Identifier: MIT
3
-
4
- Copyright (c) 2024, SCANOSS
5
-
6
- Permission is hereby granted, free of charge, to any person obtaining a copy
7
- of this software and associated documentation files (the "Software"), to deal
8
- in the Software without restriction, including without limitation the rights
9
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
- copies of the Software, and to permit persons to whom the Software is
11
- furnished to do so, subject to the following conditions:
12
-
13
- The above copyright notice and this permission notice shall be included in
14
- all copies or substantial portions of the Software.
15
-
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
- THE SOFTWARE.
2
+ SPDX-License-Identifier: MIT
3
+
4
+ Copyright (c) 2024, SCANOSS
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in
14
+ all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ THE SOFTWARE.
23
23
  """
24
+
24
25
  import json
25
26
  from typing import Dict, Any
26
27
  from .policy_check import PolicyCheck, PolicyStatus
27
28
 
29
+
28
30
  class UndeclaredComponent(PolicyCheck):
29
31
  """
30
32
  SCANOSS UndeclaredComponent class
31
33
  Inspects for undeclared components
32
34
  """
33
35
 
34
- def __init__(self, debug: bool = False, trace: bool = True, quiet: bool = False, filepath: str = None,
35
- format_type: str = 'json', status: str = None, output: str = None, sbom_format: str = 'settings'):
36
+ def __init__(
37
+ self,
38
+ debug: bool = False,
39
+ trace: bool = True,
40
+ quiet: bool = False,
41
+ filepath: str = None,
42
+ format_type: str = 'json',
43
+ status: str = None,
44
+ output: str = None,
45
+ sbom_format: str = 'settings',
46
+ ):
36
47
  """
37
48
  Initialize the UndeclaredComponent class.
38
49
 
@@ -45,20 +56,21 @@ class UndeclaredComponent(PolicyCheck):
45
56
  :param output: Path to save detailed output
46
57
  :param sbom_format: Sbom format for status output (default 'settings')
47
58
  """
48
- super().__init__(debug, trace, quiet, filepath, format_type, status, output,
49
- name='Undeclared Components Policy')
59
+ super().__init__(
60
+ debug, trace, quiet, filepath, format_type, status, output, name='Undeclared Components Policy'
61
+ )
50
62
  self.filepath = filepath
51
63
  self.format = format
52
64
  self.output = output
53
65
  self.status = status
54
66
  self.sbom_format = sbom_format
55
67
 
56
- def _get_undeclared_component(self, components: list)-> list or None:
68
+ def _get_undeclared_component(self, components: list) -> list or None:
57
69
  """
58
- Filter the components list to include only undeclared components.
70
+ Filter the components list to include only undeclared components.
59
71
 
60
- :param components: List of all components
61
- :return: List of undeclared components
72
+ :param components: List of all components
73
+ :return: List of undeclared components
62
74
  """
63
75
  if components is None:
64
76
  self.print_debug(f'WARNING: No components provided!')
@@ -73,24 +85,29 @@ class UndeclaredComponent(PolicyCheck):
73
85
 
74
86
  def _get_jira_summary(self, components: list) -> str:
75
87
  """
76
- Get a summary of the undeclared components.
88
+ Get a summary of the undeclared components.
77
89
 
78
- :param components: List of all components
79
- :return: Component summary markdown
80
- """
90
+ :param components: List of all components
91
+ :return: Component summary markdown
92
+ """
81
93
  if len(components) > 0:
82
94
  if self.sbom_format == 'settings':
83
- json_str = (json.dumps(self._generate_scanoss_file(components), indent=2).replace('\n', '\\n')
84
- .replace('"', '\\"'))
95
+ json_str = (
96
+ json.dumps(self._generate_scanoss_file(components), indent=2)
97
+ .replace('\n', '\\n')
98
+ .replace('"', '\\"')
99
+ )
85
100
  return f'{len(components)} undeclared component(s) were found.\nAdd the following snippet into your `scanoss.json` file\n{{code:json}}\n{json.dumps(self._generate_scanoss_file(components), indent=2)}\n{{code}}\n'
86
101
  else:
87
- json_str = (json.dumps(self._generate_scanoss_file(components), indent=2).replace('\n', '\\n')
88
- .replace('"', '\\"'))
102
+ json_str = (
103
+ json.dumps(self._generate_scanoss_file(components), indent=2)
104
+ .replace('\n', '\\n')
105
+ .replace('"', '\\"')
106
+ )
89
107
  return f'{len(components)} undeclared component(s) were found.\nAdd the following snippet into your `sbom.json` file\n{{code:json}}\n{json.dumps(self._generate_scanoss_file(components), indent=2)}\n{{code}}\n'
90
108
 
91
109
  return f'{len(components)} undeclared component(s) were found.\\n'
92
110
 
93
-
94
111
  def _get_summary(self, components: list) -> str:
95
112
  """
96
113
  Get a summary of the undeclared components.
@@ -101,11 +118,15 @@ class UndeclaredComponent(PolicyCheck):
101
118
  summary = f'{len(components)} undeclared component(s) were found.\n'
102
119
  if len(components) > 0:
103
120
  if self.sbom_format == 'settings':
104
- summary += (f'Add the following snippet into your `scanoss.json` file\n'
105
- f'\n```json\n{json.dumps(self._generate_scanoss_file(components), indent=2)}\n```\n')
121
+ summary += (
122
+ f'Add the following snippet into your `scanoss.json` file\n'
123
+ f'\n```json\n{json.dumps(self._generate_scanoss_file(components), indent=2)}\n```\n'
124
+ )
106
125
  else:
107
- summary += (f'Add the following snippet into your `sbom.json` file\n'
108
- f'\n```json\n{json.dumps(self._generate_sbom_file(components), indent=2)}\n```\n')
126
+ summary += (
127
+ f'Add the following snippet into your `sbom.json` file\n'
128
+ f'\n```json\n{json.dumps(self._generate_sbom_file(components), indent=2)}\n```\n'
129
+ )
109
130
 
110
131
  return summary
111
132
 
@@ -120,71 +141,71 @@ class UndeclaredComponent(PolicyCheck):
120
141
  if len(components) > 0:
121
142
  details = {'components': components}
122
143
  return {
123
- 'details': f'{json.dumps(details, indent=2)}\n',
144
+ 'details': f'{json.dumps(details, indent=2)}\n',
124
145
  'summary': self._get_summary(components),
125
146
  }
126
147
 
127
- def _markdown(self, components: list) -> Dict[str,Any]:
148
+ def _markdown(self, components: list) -> Dict[str, Any]:
128
149
  """
129
- Format the undeclared components as Markdown.
150
+ Format the undeclared components as Markdown.
130
151
 
131
- :param components: List of undeclared components
132
- :return: Dictionary with formatted Markdown details and summary
133
- """
152
+ :param components: List of undeclared components
153
+ :return: Dictionary with formatted Markdown details and summary
154
+ """
134
155
  headers = ['Component', 'Version', 'License']
135
- rows: [[]]= []
156
+ rows: [[]] = []
136
157
  # TODO look at using SpdxLite license name lookup method
137
158
  for component in components:
138
- licenses = " - ".join(lic.get('spdxid', 'Unknown') for lic in component['licenses'])
159
+ licenses = ' - '.join(lic.get('spdxid', 'Unknown') for lic in component['licenses'])
139
160
  rows.append([component['purl'], component['version'], licenses])
140
- return {
141
- 'details': f'### Undeclared components\n{self.generate_table(headers,rows)}\n',
161
+ return {
162
+ 'details': f'### Undeclared components\n{self.generate_table(headers, rows)}\n',
142
163
  'summary': self._get_summary(components),
143
164
  }
144
165
 
145
- def _jira_markdown(self, components: list) -> Dict[str,Any]:
166
+ def _jira_markdown(self, components: list) -> Dict[str, Any]:
146
167
  """
147
- Format the undeclared components as Markdown.
168
+ Format the undeclared components as Markdown.
148
169
 
149
- :param components: List of undeclared components
150
- :return: Dictionary with formatted Markdown details and summary
151
- """
170
+ :param components: List of undeclared components
171
+ :return: Dictionary with formatted Markdown details and summary
172
+ """
152
173
  headers = ['Component', 'Version', 'License']
153
- rows: [[]]= []
174
+ rows: [[]] = []
154
175
  # TODO look at using SpdxLite license name lookup method
155
176
  for component in components:
156
- licenses = " - ".join(lic.get('spdxid', 'Unknown') for lic in component['licenses'])
177
+ licenses = ' - '.join(lic.get('spdxid', 'Unknown') for lic in component['licenses'])
157
178
  rows.append([component['purl'], component['version'], licenses])
158
- return {
159
- 'details': f'{self.generate_jira_table(headers,rows)}',
179
+ return {
180
+ 'details': f'{self.generate_jira_table(headers, rows)}',
160
181
  'summary': self._get_jira_summary(components),
161
182
  }
162
183
 
163
184
  def _get_unique_components(self, components: list) -> list:
164
185
  """
165
- Generate a list of unique components.
186
+ Generate a list of unique components.
166
187
 
167
- :param components: List of undeclared components
168
- :return: list of unique components
169
- """
188
+ :param components: List of undeclared components
189
+ :return: list of unique components
190
+ """
170
191
  unique_components = {}
171
192
  if components is None:
172
193
  self.print_stderr(f'WARNING: No components provided!')
173
194
  return []
174
195
 
175
196
  for component in components:
176
- unique_components[component['purl']] = {'purl': component['purl']}
197
+ unique_components[component['purl']] = {'purl': component['purl']}
177
198
  return list(unique_components.values())
178
199
 
179
200
  def _generate_scanoss_file(self, components: list) -> dict:
180
201
  """
181
- Generate a list of PURLs for the scanoss.json file.
202
+ Generate a list of PURLs for the scanoss.json file.
182
203
 
183
- :param components: List of undeclared components
184
- :return: scanoss.json Dictionary
185
- """
204
+ :param components: List of undeclared components
205
+ :return: scanoss.json Dictionary
206
+ """
186
207
  scanoss_settings = {
187
- 'bom':{
208
+ 'bom': {
188
209
  'include': self._get_unique_components(components),
189
210
  }
190
211
  }
@@ -193,11 +214,11 @@ class UndeclaredComponent(PolicyCheck):
193
214
 
194
215
  def _generate_sbom_file(self, components: list) -> dict:
195
216
  """
196
- Generate a list of PURLs for the SBOM file.
217
+ Generate a list of PURLs for the SBOM file.
197
218
 
198
- :param components: List of undeclared components
199
- :return: SBOM Dictionary with components
200
- """
219
+ :param components: List of undeclared components
220
+ :return: SBOM Dictionary with components
221
+ """
201
222
  sbom = {
202
223
  'components': self._get_unique_components(components),
203
224
  }
@@ -236,6 +257,8 @@ class UndeclaredComponent(PolicyCheck):
236
257
  if len(undeclared_components) <= 0:
237
258
  return PolicyStatus.FAIL.value, results
238
259
  return PolicyStatus.SUCCESS.value, results
260
+
261
+
239
262
  #
240
263
  # End of UndeclaredComponent Class
241
264
  #