scanoss 1.12.2__py3-none-any.whl → 1.43.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 (109) 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 +18 -12
  4. protoc_gen_swagger/options/annotations_pb2.pyi +48 -0
  5. protoc_gen_swagger/options/annotations_pb2_grpc.py +20 -0
  6. protoc_gen_swagger/options/openapiv2_pb2.py +110 -99
  7. protoc_gen_swagger/options/openapiv2_pb2.pyi +1317 -0
  8. protoc_gen_swagger/options/openapiv2_pb2_grpc.py +20 -0
  9. scanoss/__init__.py +18 -18
  10. scanoss/api/__init__.py +17 -17
  11. scanoss/api/common/__init__.py +17 -17
  12. scanoss/api/common/v2/__init__.py +17 -17
  13. scanoss/api/common/v2/scanoss_common_pb2.py +49 -20
  14. scanoss/api/common/v2/scanoss_common_pb2_grpc.py +25 -0
  15. scanoss/api/components/__init__.py +17 -17
  16. scanoss/api/components/v2/__init__.py +17 -17
  17. scanoss/api/components/v2/scanoss_components_pb2.py +68 -43
  18. scanoss/api/components/v2/scanoss_components_pb2_grpc.py +83 -22
  19. scanoss/api/cryptography/v2/scanoss_cryptography_pb2.py +136 -21
  20. scanoss/api/cryptography/v2/scanoss_cryptography_pb2_grpc.py +766 -13
  21. scanoss/api/dependencies/__init__.py +17 -17
  22. scanoss/api/dependencies/v2/__init__.py +17 -17
  23. scanoss/api/dependencies/v2/scanoss_dependencies_pb2.py +56 -29
  24. scanoss/api/dependencies/v2/scanoss_dependencies_pb2_grpc.py +94 -8
  25. scanoss/api/geoprovenance/__init__.py +23 -0
  26. scanoss/api/geoprovenance/v2/__init__.py +23 -0
  27. scanoss/api/geoprovenance/v2/scanoss_geoprovenance_pb2.py +92 -0
  28. scanoss/api/geoprovenance/v2/scanoss_geoprovenance_pb2_grpc.py +381 -0
  29. scanoss/api/licenses/__init__.py +23 -0
  30. scanoss/api/licenses/v2/__init__.py +23 -0
  31. scanoss/api/licenses/v2/scanoss_licenses_pb2.py +84 -0
  32. scanoss/api/licenses/v2/scanoss_licenses_pb2_grpc.py +302 -0
  33. scanoss/api/scanning/__init__.py +17 -17
  34. scanoss/api/scanning/v2/__init__.py +17 -17
  35. scanoss/api/scanning/v2/scanoss_scanning_pb2.py +42 -13
  36. scanoss/api/scanning/v2/scanoss_scanning_pb2_grpc.py +86 -7
  37. scanoss/api/semgrep/__init__.py +17 -17
  38. scanoss/api/semgrep/v2/__init__.py +17 -17
  39. scanoss/api/semgrep/v2/scanoss_semgrep_pb2.py +50 -23
  40. scanoss/api/semgrep/v2/scanoss_semgrep_pb2_grpc.py +151 -16
  41. scanoss/api/vulnerabilities/__init__.py +17 -17
  42. scanoss/api/vulnerabilities/v2/__init__.py +17 -17
  43. scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2.py +78 -31
  44. scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2_grpc.py +282 -18
  45. scanoss/cli.py +2359 -370
  46. scanoss/components.py +187 -94
  47. scanoss/constants.py +22 -0
  48. scanoss/cryptography.py +308 -0
  49. scanoss/csvoutput.py +91 -58
  50. scanoss/cyclonedx.py +221 -63
  51. scanoss/data/build_date.txt +1 -1
  52. scanoss/data/osadl-copyleft.json +133 -0
  53. scanoss/data/scanoss-settings-schema.json +254 -0
  54. scanoss/delta.py +197 -0
  55. scanoss/export/__init__.py +23 -0
  56. scanoss/export/dependency_track.py +227 -0
  57. scanoss/file_filters.py +582 -0
  58. scanoss/filecount.py +75 -69
  59. scanoss/gitlabqualityreport.py +214 -0
  60. scanoss/header_filter.py +563 -0
  61. scanoss/inspection/__init__.py +23 -0
  62. scanoss/inspection/policy_check/__init__.py +0 -0
  63. scanoss/inspection/policy_check/dependency_track/__init__.py +0 -0
  64. scanoss/inspection/policy_check/dependency_track/project_violation.py +479 -0
  65. scanoss/inspection/policy_check/policy_check.py +222 -0
  66. scanoss/inspection/policy_check/scanoss/__init__.py +0 -0
  67. scanoss/inspection/policy_check/scanoss/copyleft.py +243 -0
  68. scanoss/inspection/policy_check/scanoss/undeclared_component.py +309 -0
  69. scanoss/inspection/summary/__init__.py +0 -0
  70. scanoss/inspection/summary/component_summary.py +170 -0
  71. scanoss/inspection/summary/license_summary.py +191 -0
  72. scanoss/inspection/summary/match_summary.py +341 -0
  73. scanoss/inspection/utils/file_utils.py +44 -0
  74. scanoss/inspection/utils/license_utils.py +123 -0
  75. scanoss/inspection/utils/markdown_utils.py +63 -0
  76. scanoss/inspection/utils/scan_result_processor.py +417 -0
  77. scanoss/osadl.py +125 -0
  78. scanoss/results.py +275 -0
  79. scanoss/scancodedeps.py +87 -38
  80. scanoss/scanner.py +431 -539
  81. scanoss/scanners/__init__.py +23 -0
  82. scanoss/scanners/container_scanner.py +476 -0
  83. scanoss/scanners/folder_hasher.py +358 -0
  84. scanoss/scanners/scanner_config.py +73 -0
  85. scanoss/scanners/scanner_hfh.py +252 -0
  86. scanoss/scanoss_settings.py +337 -0
  87. scanoss/scanossapi.py +140 -101
  88. scanoss/scanossbase.py +59 -22
  89. scanoss/scanossgrpc.py +799 -251
  90. scanoss/scanpostprocessor.py +294 -0
  91. scanoss/scantype.py +22 -21
  92. scanoss/services/dependency_track_service.py +132 -0
  93. scanoss/spdxlite.py +532 -174
  94. scanoss/threadeddependencies.py +148 -47
  95. scanoss/threadedscanning.py +53 -37
  96. scanoss/utils/__init__.py +23 -0
  97. scanoss/utils/abstract_presenter.py +103 -0
  98. scanoss/utils/crc64.py +96 -0
  99. scanoss/utils/file.py +84 -0
  100. scanoss/utils/scanoss_scan_results_utils.py +41 -0
  101. scanoss/utils/simhash.py +198 -0
  102. scanoss/winnowing.py +241 -63
  103. {scanoss-1.12.2.dist-info → scanoss-1.43.1.dist-info}/METADATA +18 -9
  104. scanoss-1.43.1.dist-info/RECORD +110 -0
  105. {scanoss-1.12.2.dist-info → scanoss-1.43.1.dist-info}/WHEEL +1 -1
  106. scanoss-1.12.2.dist-info/RECORD +0 -58
  107. {scanoss-1.12.2.dist-info → scanoss-1.43.1.dist-info}/entry_points.txt +0 -0
  108. {scanoss-1.12.2.dist-info → scanoss-1.43.1.dist-info/licenses}/LICENSE +0 -0
  109. {scanoss-1.12.2.dist-info → scanoss-1.43.1.dist-info}/top_level.txt +0 -0
scanoss/results.py ADDED
@@ -0,0 +1,275 @@
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.
23
+ """
24
+
25
+ import json
26
+ from typing import Any, Dict, List
27
+
28
+ from scanoss.utils.abstract_presenter import AbstractPresenter
29
+
30
+ from .scanossbase import ScanossBase
31
+
32
+ MATCH_TYPES = ['file', 'snippet']
33
+ STATUSES = ['pending', 'identified']
34
+
35
+
36
+ AVAILABLE_FILTER_VALUES = {
37
+ 'match_type': [e for e in MATCH_TYPES],
38
+ 'status': [e for e in STATUSES],
39
+ }
40
+
41
+
42
+ ARG_TO_FILTER_MAP = {
43
+ 'match_type': 'id',
44
+ 'status': 'status',
45
+ }
46
+
47
+ PENDING_IDENTIFICATION_FILTERS = {
48
+ 'match_type': ['file', 'snippet'],
49
+ 'status': ['pending'],
50
+ }
51
+
52
+
53
+ class ResultsPresenter(AbstractPresenter):
54
+ """
55
+ SCANOSS Results presenter class
56
+ Handles the presentation of the scan results
57
+ """
58
+
59
+ def __init__(self, results_instance, **kwargs):
60
+ super().__init__(**kwargs)
61
+ self.results = results_instance
62
+
63
+ def _format_json_output(self) -> str:
64
+ """
65
+ Format the output data into a JSON object
66
+ """
67
+
68
+ formatted_data = []
69
+ for item in self.results.data:
70
+ formatted_data.append(
71
+ {
72
+ 'file': item.get('filename'),
73
+ 'status': item.get('status', 'N/A'),
74
+ 'match_type': item['id'],
75
+ 'matched': item.get('matched', 'N/A'),
76
+ 'purl': (item.get('purl')[0] if item.get('purl') else 'N/A'),
77
+ 'license': (item.get('licenses')[0].get('name', 'N/A') if item.get('licenses') else 'N/A'),
78
+ }
79
+ )
80
+ try:
81
+ return json.dumps({'results': formatted_data, 'total': len(formatted_data)}, indent=2)
82
+ except Exception as e:
83
+ self.base.print_stderr(f'ERROR: Problem formatting JSON output: {e}')
84
+ return ''
85
+
86
+ def _format_cyclonedx_output(self) -> str:
87
+ raise NotImplementedError('CycloneDX output is not implemented')
88
+
89
+ def _format_spdxlite_output(self) -> str:
90
+ raise NotImplementedError('SPDXlite output is not implemented')
91
+
92
+ def _format_csv_output(self) -> str:
93
+ raise NotImplementedError('CSV output is not implemented')
94
+
95
+ def _format_raw_output(self) -> str:
96
+ raise NotImplementedError('Raw output is not implemented')
97
+
98
+ def _format_plain_output(self) -> str:
99
+ """Format the output data into a plain text string
100
+
101
+ Returns:
102
+ str: The formatted output data
103
+ """
104
+ if not self.results.data:
105
+ msg = 'No results to present'
106
+ return msg
107
+
108
+ formatted = ''
109
+ for item in self.results.data:
110
+ formatted += f'{self._format_plain_output_item(item)}\n'
111
+ return formatted
112
+
113
+ @staticmethod
114
+ def _format_plain_output_item(item):
115
+ purls = item.get('purl', [])
116
+ licenses = item.get('licenses', [])
117
+
118
+ return (
119
+ f'File: {item.get("filename")}\n'
120
+ f'Match type: {item.get("id")}\n'
121
+ f'Status: {item.get("status", "N/A")}\n'
122
+ f'Matched: {item.get("matched", "N/A")}\n'
123
+ f'Purl: {purls[0] if purls else "N/A"}\n'
124
+ f'License: {licenses[0].get("name", "N/A") if licenses else "N/A"}\n'
125
+ )
126
+
127
+
128
+ class Results:
129
+ """
130
+ SCANOSS Results class \n
131
+ Handles the parsing and filtering of the scan results
132
+ """
133
+
134
+ def __init__( # noqa: PLR0913
135
+ self,
136
+ debug: bool = False,
137
+ trace: bool = False,
138
+ quiet: bool = False,
139
+ filepath: str = None,
140
+ match_type: str = None,
141
+ status: str = None,
142
+ output_file: str = None,
143
+ output_format: str = None,
144
+ ):
145
+ """Initialise the Results class
146
+
147
+ Args:
148
+ debug (bool, optional): Debug. Defaults to False.
149
+ trace (bool, optional): Trace. Defaults to False.
150
+ quiet (bool, optional): Quiet. Defaults to False.
151
+ filepath (str, optional): Path to the scan results file. Defaults to None.
152
+ match_type (str, optional): Comma separated match type filters. Defaults to None.
153
+ status (str, optional): Comma separated status filters. Defaults to None.
154
+ output_file (str, optional): Path to the output file. Defaults to None.
155
+ output_format (str, optional): Output format. Defaults to None.
156
+ """
157
+
158
+ self.base = ScanossBase(debug, trace, quiet)
159
+ self.data = self._load_and_transform(filepath)
160
+ self.filters = self._load_filters(match_type=match_type, status=status)
161
+ self.presenter = ResultsPresenter(
162
+ self,
163
+ debug=debug,
164
+ trace=trace,
165
+ quiet=quiet,
166
+ output_file=output_file,
167
+ output_format=output_format,
168
+ )
169
+
170
+ def load_file(self, file: str) -> Dict[str, Any]:
171
+ """Load the JSON file
172
+
173
+ Args:
174
+ file (str): Path to the JSON file
175
+
176
+ Returns:
177
+ Dict[str, Any]: The parsed JSON data
178
+ """
179
+ with open(file, 'r') as jsonfile:
180
+ try:
181
+ return json.load(jsonfile)
182
+ except Exception as e:
183
+ self.base.print_stderr(f'ERROR: Problem parsing input JSON: {e}')
184
+
185
+ def _load_and_transform(self, file: str) -> List[Dict[str, Any]]:
186
+ """
187
+ Load the file and transform the data into a list of dictionaries with the filename and the file data
188
+ """
189
+
190
+ raw_data = self.load_file(file)
191
+ return self._transform_data(raw_data)
192
+
193
+ @staticmethod
194
+ def _transform_data(data: dict) -> list:
195
+ """Transform the data into a list of dictionaries with the filename and the file data
196
+
197
+ Args:
198
+ data (dict): The raw data
199
+
200
+ Returns:
201
+ list: The transformed data
202
+ """
203
+ result = []
204
+ for filename, file_data in data.items():
205
+ if file_data:
206
+ file_obj = {'filename': filename}
207
+ file_obj.update(file_data[0])
208
+ result.append(file_obj)
209
+ return result
210
+
211
+ def _load_filters(self, **kwargs):
212
+ """Extract and parse the filters
213
+
214
+ Returns:
215
+ dict: Parsed filters
216
+ """
217
+ filters = {}
218
+
219
+ for key, value in kwargs.items():
220
+ if value:
221
+ filters[key] = self._extract_comma_separated_values(value)
222
+
223
+ return filters
224
+
225
+ @staticmethod
226
+ def _extract_comma_separated_values(values: str):
227
+ return [value.strip() for value in values.split(',')]
228
+
229
+ def apply_filters(self):
230
+ """Apply the filters to the data"""
231
+ filtered_data = []
232
+ for item in self.data:
233
+ if self._item_matches_filters(item):
234
+ filtered_data.append(item)
235
+ self.data = filtered_data
236
+
237
+ return self
238
+
239
+ def _item_matches_filters(self, item):
240
+ for filter_key, filter_values in self.filters.items():
241
+ if not filter_values:
242
+ continue
243
+
244
+ self._validate_filter_values(filter_key, filter_values)
245
+
246
+ item_value = item.get(ARG_TO_FILTER_MAP[filter_key])
247
+ if isinstance(filter_values, list):
248
+ if item_value not in filter_values:
249
+ return False
250
+ elif item_value != filter_values:
251
+ return False
252
+ return True
253
+
254
+ @staticmethod
255
+ def _validate_filter_values(filter_key: str, filter_value: List[str]):
256
+ if any(value not in AVAILABLE_FILTER_VALUES.get(filter_key, []) for value in filter_value):
257
+ valid_values = ', '.join(AVAILABLE_FILTER_VALUES.get(filter_key, []))
258
+ raise ValueError(
259
+ f"ERROR: Invalid filter value '{filter_value}' for filter '{filter_key}'. "
260
+ f'Valid values are: {valid_values}'
261
+ )
262
+
263
+ def get_pending_identifications(self):
264
+ """Get files with 'pending' status and 'file' or 'snippet' match type"""
265
+ self.filters = PENDING_IDENTIFICATION_FILTERS
266
+ self.apply_filters()
267
+
268
+ return self
269
+
270
+ def has_results(self):
271
+ return bool(self.data)
272
+
273
+ def present(self, output_format: str = None, output_file: str = None):
274
+ """Present the results in the selected format"""
275
+ self.presenter.present(output_format=output_format, output_file=output_file)
scanoss/scancodedeps.py CHANGED
@@ -1,25 +1,25 @@
1
1
  """
2
- SPDX-License-Identifier: MIT
3
-
4
- Copyright (c) 2021, 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) 2021, 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
25
  import json
@@ -33,8 +33,17 @@ class ScancodeDeps(ScanossBase):
33
33
  """
34
34
  SCANOSS dependency scanning class
35
35
  """
36
- def __init__(self, debug: bool = False, quiet: bool = False, trace: bool = False, output_file: str = None,
37
- scan_output: str = None, timeout: int = 600, sc_command: str = None):
36
+
37
+ def __init__(
38
+ self,
39
+ debug: bool = False,
40
+ quiet: bool = False,
41
+ trace: bool = False,
42
+ output_file: str = None,
43
+ scan_output: str = None,
44
+ timeout: int = 600,
45
+ sc_command: str = None,
46
+ ):
38
47
  """
39
48
  Initialise ScancodeDeps class
40
49
  """
@@ -54,7 +63,7 @@ class ScancodeDeps(ScanossBase):
54
63
  if not outfile and self.scan_output:
55
64
  outfile = self.scan_output
56
65
  if outfile:
57
- with open(outfile, "a") as rf:
66
+ with open(outfile, 'a') as rf:
58
67
  rf.write(string + '\n')
59
68
  else:
60
69
  print(string)
@@ -85,7 +94,7 @@ class ScancodeDeps(ScanossBase):
85
94
  self.print_debug(f'Processing Scancode results into Dependency data...')
86
95
  files = []
87
96
  for t in data:
88
- if t == 'files': # Only interested in 'files' details
97
+ if t == 'files': # Only interested in 'files' details
89
98
  files_details = data.get(t)
90
99
  if not files_details or files_details == '':
91
100
  continue
@@ -105,32 +114,40 @@ class ScancodeDeps(ScanossBase):
105
114
  continue
106
115
  self.print_debug(f'Path: {f_path}, Packages: {len(f_packages)}')
107
116
  purls = []
117
+ scopes = []
108
118
  for pkgs in f_packages:
109
119
  pk_deps = pkgs.get('dependencies')
120
+
110
121
  if not pk_deps or pk_deps == '':
111
122
  continue
112
- self.print_debug(f'Path: {f_path}, Dependencies: {len(pk_deps)}')
113
123
  for d in pk_deps:
114
124
  dp = d.get('purl')
115
125
  if not dp or dp == '':
116
126
  continue
127
+
117
128
  dp = dp.replace('"', '').replace('%22', '') # remove unwanted quotes on purls
118
129
  dp_data = {'purl': dp}
119
130
  rq = d.get('extracted_requirement') # scancode format 2.0
120
131
  if not rq or rq == '':
121
- rq = d.get('requirement') # scancode format 1.0
132
+ rq = d.get('requirement') # scancode format 1.0
122
133
  # skip requirement if it ends with the purl (i.e. exact version) or if it's local (file)
123
134
  if rq and rq != '' and not dp.endswith(rq) and not rq.startswith('file:'):
124
135
  dp_data['requirement'] = rq
136
+
137
+ # Gets dependency scope
138
+ scope = d.get('scope')
139
+ if scope and scope != '':
140
+ dp_data['scope'] = scope
141
+
125
142
  purls.append(dp_data)
126
- # self.print_stderr(f'Path: {f_path}, Purls: {purls}')
143
+ # end for loop
144
+
127
145
  if len(purls) > 0:
128
146
  files.append({'file': f_path, 'purls': purls})
129
147
  # End packages
130
148
  # End file details
131
149
  # End dependencies json
132
150
  deps = {'files': files}
133
- # self.print_debug(f'Dep Data: {deps}')
134
151
  return deps
135
152
 
136
153
  def produce_from_file(self, json_file: str = None) -> json:
@@ -179,6 +196,7 @@ class ScancodeDeps(ScanossBase):
179
196
  return False
180
197
  self.print_msg('Producing summary...')
181
198
  deps = self.produce_from_file(output_file)
199
+ deps = self.__remove_dep_scope(deps)
182
200
  self.remove_interim_file(output_file)
183
201
  if not deps:
184
202
  return False
@@ -196,17 +214,32 @@ class ScancodeDeps(ScanossBase):
196
214
  output_file = self.output_file
197
215
  try:
198
216
  open(output_file, 'w').close()
199
- self.print_trace(f'About to execute {self.sc_command} -p --only-findings --quiet --json {output_file}'
200
- f' {what_to_scan}')
201
- result = subprocess.run([self.sc_command, '-p', '--only-findings', '--quiet', '--strip-root', '--json',
202
- output_file, what_to_scan],
203
- cwd=os.getcwd(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
204
- text=True, timeout=self.timeout
205
- )
217
+ self.print_trace(
218
+ f'About to execute {self.sc_command} -p --only-findings --quiet --json {output_file} {what_to_scan}'
219
+ )
220
+ result = subprocess.run(
221
+ [
222
+ self.sc_command,
223
+ '-p',
224
+ '--only-findings',
225
+ '--quiet',
226
+ '--strip-root',
227
+ '--json',
228
+ output_file,
229
+ what_to_scan,
230
+ ],
231
+ cwd=os.getcwd(),
232
+ stdout=subprocess.PIPE,
233
+ stderr=subprocess.STDOUT,
234
+ text=True,
235
+ timeout=self.timeout,
236
+ )
206
237
  self.print_trace(f'Subprocess return: {result}')
207
238
  if result.returncode:
208
- self.print_stderr(f'ERROR: Scancode dependency scan of {what_to_scan} failed with exit code'
209
- f' {result.returncode}:\n{result.stdout}')
239
+ self.print_stderr(
240
+ f'ERROR: Scancode dependency scan of {what_to_scan} failed with exit code'
241
+ f' {result.returncode}:\n{result.stdout}'
242
+ )
210
243
  return False
211
244
  except subprocess.TimeoutExpired as e:
212
245
  self.print_stderr(f'ERROR: Timed out attempting to run scancode dependency scan on {what_to_scan}: {e}')
@@ -235,6 +268,22 @@ class ScancodeDeps(ScanossBase):
235
268
  self.print_stderr(f'ERROR: Problem loading input JSON: {e}')
236
269
  return None
237
270
 
271
+ @staticmethod
272
+ def __remove_dep_scope(deps: json) -> json:
273
+ """
274
+ :param deps: dependencies with scopes
275
+ :return dependencies without scopes
276
+ """
277
+ files = deps.get('files')
278
+ for file in files:
279
+ if 'purls' in file:
280
+ purls = file.get('purls')
281
+ for purl in purls:
282
+ purl.pop('scope', None)
283
+
284
+ return {'files': files}
285
+
286
+
238
287
  #
239
288
  # End of ScancodeDeps Class
240
289
  #