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/components.py CHANGED
@@ -1,33 +1,37 @@
1
1
  """
2
- SPDX-License-Identifier: MIT
3
-
4
- Copyright (c) 2023, 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) 2023, 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
26
27
  import sys
27
- from typing import TextIO
28
+ from typing import List, Optional, TextIO
28
29
 
29
30
  from pypac.parser import PACFile
30
31
 
32
+ from scanoss.cyclonedx import CycloneDx
33
+ from scanoss.utils.file import validate_json_file
34
+
31
35
  from .scanner import Scanner
32
36
  from .scanossbase import ScanossBase
33
37
  from .scanossgrpc import ScanossGrpc
@@ -38,10 +42,22 @@ class Components(ScanossBase):
38
42
  Class for Component functionality
39
43
  """
40
44
 
41
- def __init__(self, debug: bool = False, trace: bool = False, quiet: bool = False,
42
- grpc_url: str = None, api_key: str = None, timeout: int = 600,
43
- proxy: str = None, grpc_proxy: str = None, ca_cert: str = None, pac: PACFile = None
44
- ):
45
+ def __init__( # noqa: PLR0913, PLR0915
46
+ self,
47
+ debug: bool = False,
48
+ trace: bool = False,
49
+ quiet: bool = False,
50
+ grpc_url: str = None,
51
+ api_key: str = None,
52
+ timeout: int = 600,
53
+ proxy: str = None,
54
+ grpc_proxy: str = None,
55
+ ca_cert: str = None,
56
+ pac: PACFile = None,
57
+ req_headers: dict = None,
58
+ ignore_cert_errors: bool = False,
59
+ use_grpc: bool = False,
60
+ ):
45
61
  """
46
62
  Handle all component style requests
47
63
 
@@ -55,43 +71,76 @@ class Components(ScanossBase):
55
71
  :param grpc_proxy: Specific gRPC proxy (optional)
56
72
  :param ca_cert: TLS client certificate (optional)
57
73
  :param pac: Proxy Auto-Config file (optional)
74
+ :param req_headers: Additional headers to send with requests (optional)
75
+ :param ignore_cert_errors: Ignore TLS certificate errors (optional)
76
+ :param use_grpc: Use gRPC instead of HTTP (optional)
58
77
  """
59
78
  super().__init__(debug, trace, quiet)
60
79
  ver_details = Scanner.version_details()
61
- self.grpc_api = ScanossGrpc(url=grpc_url, debug=debug, quiet=quiet, trace=trace, api_key=api_key,
62
- ver_details=ver_details, ca_cert=ca_cert, proxy=proxy, pac=pac,
63
- grpc_proxy=grpc_proxy, timeout=timeout)
80
+ self.use_grpc = use_grpc
81
+ self.grpc_api = ScanossGrpc(
82
+ url=grpc_url,
83
+ debug=debug,
84
+ quiet=quiet,
85
+ trace=trace,
86
+ api_key=api_key,
87
+ ver_details=ver_details,
88
+ ca_cert=ca_cert,
89
+ proxy=proxy,
90
+ pac=pac,
91
+ grpc_proxy=grpc_proxy,
92
+ timeout=timeout,
93
+ req_headers=req_headers,
94
+ ignore_cert_errors=ignore_cert_errors,
95
+ )
96
+ self.cdx = CycloneDx(debug=self.debug)
64
97
 
65
- def load_purls(self, json_file: str = None, purls: [] = None) -> dict:
98
+ def load_comps(self, json_file: Optional[str] = None, purls: Optional[List[str]] = None) -> Optional[dict]:
99
+ """
100
+ Load the specified components and return a dictionary
101
+
102
+ :param json_file: JSON Components file (optional)
103
+ :param purls: list pf PURLs (optional)
104
+ :return: Components Request dictionary or None
105
+ """
106
+ return self.load_purls(json_file, purls, 'components')
107
+
108
+ def load_purls(
109
+ self, json_file: Optional[str] = None, purls: Optional[List[str]] = None, field: str = 'purls'
110
+ ) -> Optional[dict]:
66
111
  """
67
112
  Load the specified purls and return a dictionary
68
113
 
69
114
  :param json_file: JSON PURL file (optional)
70
115
  :param purls: list of PURLs (optional)
71
- :return: PURL Request dictionary
116
+ :param field: Name of the dictionary field to store the purls in (default: 'purls')
117
+ :return: PURL Request dictionary or None
72
118
  """
73
119
  if json_file:
74
- if not os.path.isfile(json_file) or not os.access(json_file, os.R_OK):
75
- self.print_stderr(f'ERROR: JSON file does not exist, is not a file, or is not readable: {json_file}')
120
+ result = validate_json_file(json_file)
121
+ if not result.is_valid:
122
+ self.print_stderr(f'ERROR: Problem parsing input JSON: {result.error}')
76
123
  return None
77
- with open(json_file, 'r') as f:
78
- try:
79
- purl_request = json.loads(f.read())
80
- except Exception as e:
81
- self.print_stderr(f'ERROR: Problem parsing input JSON: {e}')
82
- return None
124
+
125
+ if self.cdx.is_cyclonedx_json(json.dumps(result.data)):
126
+ purl_request = self.cdx.get_purls_request_from_cdx(result.data, field)
127
+ else:
128
+ purl_request = result.data
83
129
  elif purls:
130
+ if not all(isinstance(purl, str) for purl in purls):
131
+ self.print_stderr('ERROR: PURLs must be a list of strings.')
132
+ return None
84
133
  parsed_purls = []
85
134
  for p in purls:
86
135
  parsed_purls.append({'purl': p})
87
- purl_request = {'purls': parsed_purls}
136
+ purl_request = {field: parsed_purls}
88
137
  else:
89
138
  self.print_stderr('ERROR: No purls specified to process.')
90
139
  return None
91
- purl_count = len(purl_request.get('purls', []))
92
- self.print_debug(f'Parsed Purls ({purl_count}): {purl_request}')
140
+ purl_count = len(purl_request.get(field, []))
141
+ self.print_debug(f'Parsed {field} ({purl_count}): {purl_request}')
93
142
  if purl_count == 0:
94
- self.print_stderr('ERROR: No PURLs parsed from request.')
143
+ self.print_stderr(f'ERROR: No {field} parsed from request.')
95
144
  return None
96
145
  return purl_request
97
146
 
@@ -117,8 +166,8 @@ class Components(ScanossBase):
117
166
  """
118
167
  Open the given filename if requested, otherwise return STDOUT
119
168
 
120
- :param filename:
121
- :return:
169
+ :param filename: filename to open or None to return STDOUT
170
+ :return: file descriptor or None
122
171
  """
123
172
  file = sys.stdout
124
173
  if filename:
@@ -141,32 +190,6 @@ class Components(ScanossBase):
141
190
  self.print_trace(f'Closing file: {filename}')
142
191
  file.close()
143
192
 
144
- def get_crypto_details(self, json_file: str = None, purls: [] = None, output_file: str = None) -> bool:
145
- """
146
- Retrieve the cryptographic details for the supplied PURLs
147
-
148
- :param json_file: PURL JSON request file (optional)
149
- :param purls: PURL request array (optional)
150
- :param output_file: output filename (optional). Default: STDOUT
151
- :return: True on success, False otherwise
152
- """
153
- success = False
154
- purls_request = self.load_purls(json_file, purls)
155
- if purls_request is None or len(purls_request) == 0:
156
- return False
157
- file = self._open_file_or_sdtout(output_file)
158
- if file is None:
159
- return False
160
- self.print_msg('Sending PURLs to Crypto API for decoration...')
161
- response = self.grpc_api.get_crypto_json(purls_request)
162
- if response:
163
- print(json.dumps(response, indent=2, sort_keys=True), file=file)
164
- success = True
165
- if output_file:
166
- self.print_msg(f'Results written to: {output_file}')
167
- self._close_file(output_file, file)
168
- return success
169
-
170
193
  def get_vulnerabilities(self, json_file: str = None, purls: [] = None, output_file: str = None) -> bool:
171
194
  """
172
195
  Retrieve any vulnerabilities related to the given PURLs
@@ -177,14 +200,14 @@ class Components(ScanossBase):
177
200
  :return: True on success, False otherwise
178
201
  """
179
202
  success = False
180
- purls_request = self.load_purls(json_file, purls)
203
+ purls_request = self.load_comps(json_file, purls)
181
204
  if purls_request is None or len(purls_request) == 0:
182
205
  return False
183
206
  file = self._open_file_or_sdtout(output_file)
184
207
  if file is None:
185
208
  return False
186
209
  self.print_msg('Sending PURLs to Vulnerability API for decoration...')
187
- response = self.grpc_api.get_vulnerabilities_json(purls_request)
210
+ response = self.grpc_api.get_vulnerabilities_json(purls_request, use_grpc=self.use_grpc)
188
211
  if response:
189
212
  print(json.dumps(response, indent=2, sort_keys=True), file=file)
190
213
  success = True
@@ -203,14 +226,14 @@ class Components(ScanossBase):
203
226
  :return: True on success, False otherwise
204
227
  """
205
228
  success = False
206
- purls_request = self.load_purls(json_file, purls)
229
+ purls_request = self.load_comps(json_file, purls)
207
230
  if purls_request is None or len(purls_request) == 0:
208
231
  return False
209
232
  file = self._open_file_or_sdtout(output_file)
210
233
  if file is None:
211
234
  return False
212
235
  self.print_msg('Sending PURLs to Semgrep API for decoration...')
213
- response = self.grpc_api.get_semgrep_json(purls_request)
236
+ response = self.grpc_api.get_semgrep_json(purls_request, use_grpc=self.use_grpc)
214
237
  if response:
215
238
  print(json.dumps(response, indent=2, sort_keys=True), file=file)
216
239
  success = True
@@ -219,9 +242,17 @@ class Components(ScanossBase):
219
242
  self._close_file(output_file, file)
220
243
  return success
221
244
 
222
- def search_components(self, output_file: str = None, json_file: str = None,
223
- search: str = None, vendor: str = None, comp: str = None, package: str = None,
224
- limit: int = None, offset: int = None) -> bool:
245
+ def search_components( # noqa: PLR0913, PLR0915
246
+ self,
247
+ output_file: str = None,
248
+ json_file: str = None,
249
+ search: str = None,
250
+ vendor: str = None,
251
+ comp: str = None,
252
+ package: str = None,
253
+ limit: int = None,
254
+ offset: int = None,
255
+ ) -> bool:
225
256
  """
226
257
  Search for a component based on the given search criteria
227
258
 
@@ -242,22 +273,17 @@ class Components(ScanossBase):
242
273
  if request is None:
243
274
  return False
244
275
  else: # Construct a query dictionary from parameters
245
- request = {
246
- "search": search,
247
- "vendor": vendor,
248
- "component": comp,
249
- "package": package
250
- }
276
+ request = {'search': search, 'vendor': vendor, 'component': comp, 'package': package}
251
277
  if limit is not None and limit > 0:
252
- request["limit"] = limit
278
+ request['limit'] = limit
253
279
  if offset is not None and offset > 0:
254
- request["offset"] = offset
280
+ request['offset'] = offset
255
281
 
256
282
  file = self._open_file_or_sdtout(output_file)
257
283
  if file is None:
258
284
  return False
259
285
  self.print_msg('Sending search data to Components API...')
260
- response = self.grpc_api.search_components_json(request)
286
+ response = self.grpc_api.search_components_json(request, use_grpc=self.use_grpc)
261
287
  if response:
262
288
  print(json.dumps(response, indent=2, sort_keys=True), file=file)
263
289
  success = True
@@ -266,8 +292,9 @@ class Components(ScanossBase):
266
292
  self._close_file(output_file, file)
267
293
  return success
268
294
 
269
- def get_component_versions(self, output_file: str = None, json_file: str = None,
270
- purl: str = None, limit: int = None) -> bool:
295
+ def get_component_versions(
296
+ self, output_file: str = None, json_file: str = None, purl: str = None, limit: int = None
297
+ ) -> bool:
271
298
  """
272
299
  Search for a component versions based on the given search criteria
273
300
 
@@ -284,17 +311,83 @@ class Components(ScanossBase):
284
311
  if request is None:
285
312
  return False
286
313
  else: # Construct a query dictionary from parameters
287
- request = {
288
- "purl": purl
289
- }
314
+ request = {'purl': purl}
290
315
  if limit is not None and limit > 0:
291
- request["limit"] = limit
316
+ request['limit'] = limit
292
317
 
293
318
  file = self._open_file_or_sdtout(output_file)
294
319
  if file is None:
295
320
  return False
296
321
  self.print_msg('Sending PURLs to Component Versions API...')
297
- response = self.grpc_api.get_component_versions_json(request)
322
+ response = self.grpc_api.get_component_versions_json(request, use_grpc=self.use_grpc)
323
+ if response:
324
+ print(json.dumps(response, indent=2, sort_keys=True), file=file)
325
+ success = True
326
+ if output_file:
327
+ self.print_msg(f'Results written to: {output_file}')
328
+ self._close_file(output_file, file)
329
+ return success
330
+
331
+ def get_provenance_details(
332
+ self, json_file: str = None, purls: [] = None, output_file: str = None, origin: bool = False
333
+ ) -> bool:
334
+ """
335
+ Retrieve the provenance details for the supplied PURLs
336
+
337
+ Args:
338
+ json_file (str, optional): Input JSON file. Defaults to None.
339
+ purls (None, optional): PURLs to retrieve provenance details for. Defaults to None.
340
+ output_file (str, optional): Output file. Defaults to None.
341
+ origin (bool, optional): Retrieve origin details. Defaults to False.
342
+
343
+ Returns:
344
+ bool: True on success, False otherwise
345
+ """
346
+ success = False
347
+ purls_request = self.load_comps(json_file, purls)
348
+ if purls_request is None or len(purls_request) == 0:
349
+ return False
350
+ file = self._open_file_or_sdtout(output_file)
351
+ if file is None:
352
+ return False
353
+ if origin:
354
+ self.print_msg('Sending PURLs to Geo Provenance Origin API for decoration...')
355
+ response = self.grpc_api.get_provenance_origin(purls_request, use_grpc=self.use_grpc)
356
+ else:
357
+ self.print_msg('Sending PURLs to Geo Provenance Declared API for decoration...')
358
+ response = self.grpc_api.get_provenance_json(purls_request, use_grpc=self.use_grpc)
359
+ if response:
360
+ print(json.dumps(response, indent=2, sort_keys=True), file=file)
361
+ success = True
362
+ if output_file:
363
+ self.print_msg(f'Results written to: {output_file}')
364
+ self._close_file(output_file, file)
365
+ return success
366
+
367
+ def get_licenses(self, json_file: str = None, purls: [] = None, output_file: str = None) -> bool:
368
+ """
369
+ Retrieve the license details for the supplied PURLs
370
+
371
+ Args:
372
+ json_file (str, optional): Input JSON file. Defaults to None.
373
+ purls (None, optional): PURLs to retrieve license details for. Defaults to None.
374
+ output_file (str, optional): Output file. Defaults to None.
375
+
376
+ Returns:
377
+ bool: True on success, False otherwise
378
+ """
379
+ success = False
380
+
381
+ purls_request = self.load_purls(json_file, purls)
382
+ if not purls_request:
383
+ return False
384
+ file = self._open_file_or_sdtout(output_file)
385
+ if file is None:
386
+ return False
387
+
388
+ # We'll use the new ComponentBatchRequest instead of deprecated PurlRequest for the license api
389
+ component_batch_request = {'components': purls_request.get('purls')}
390
+ response = self.grpc_api.get_licenses(component_batch_request, use_grpc=self.use_grpc)
298
391
  if response:
299
392
  print(json.dumps(response, indent=2, sort_keys=True), file=file)
300
393
  success = True
scanoss/constants.py ADDED
@@ -0,0 +1,22 @@
1
+ DEFAULT_POST_SIZE = 32
2
+ DEFAULT_TIMEOUT = 180
3
+ DEFAULT_RETRY = 5
4
+ MIN_TIMEOUT = 5
5
+
6
+ PYTHON_MAJOR_VERSION = 3
7
+
8
+ DEFAULT_SC_TIMEOUT = 600
9
+ DEFAULT_NB_THREADS = 5
10
+
11
+ DEFAULT_URL = 'https://api.osskb.org' # default free service URL
12
+ DEFAULT_URL2 = 'https://api.scanoss.com' # default premium service URL
13
+
14
+ DEFAULT_API_TIMEOUT = 600
15
+
16
+ DEFAULT_HFH_RANK_THRESHOLD = 5
17
+ DEFAULT_HFH_DEPTH = 1
18
+ DEFAULT_HFH_RECURSIVE_THRESHOLD = 0.8
19
+ DEFAULT_HFH_MIN_ACCEPTED_SCORE = 0.15
20
+
21
+ VALID_LICENSE_SOURCES = ['component_declared', 'license_file', 'file_header', 'file_spdx_tag', 'scancode']
22
+ DEFAULT_COPYLEFT_LICENSE_SOURCES = ['component_declared', 'license_file']