scanoss 1.20.4__tar.gz → 1.20.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. {scanoss-1.20.4/src/scanoss.egg-info → scanoss-1.20.6}/PKG-INFO +3 -2
  2. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/__init__.py +1 -1
  3. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/cli.py +41 -2
  4. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/components.py +5 -3
  5. scanoss-1.20.6/src/scanoss/data/build_date.txt +1 -0
  6. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/scanner.py +25 -20
  7. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/scanossapi.py +29 -7
  8. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/scanossgrpc.py +117 -58
  9. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/spdxlite.py +281 -30
  10. {scanoss-1.20.4 → scanoss-1.20.6/src/scanoss.egg-info}/PKG-INFO +3 -2
  11. scanoss-1.20.4/src/scanoss/data/build_date.txt +0 -1
  12. {scanoss-1.20.4 → scanoss-1.20.6}/LICENSE +0 -0
  13. {scanoss-1.20.4 → scanoss-1.20.6}/PACKAGE.md +0 -0
  14. {scanoss-1.20.4 → scanoss-1.20.6}/README.md +0 -0
  15. {scanoss-1.20.4 → scanoss-1.20.6}/pyproject.toml +0 -0
  16. {scanoss-1.20.4 → scanoss-1.20.6}/setup.cfg +0 -0
  17. {scanoss-1.20.4 → scanoss-1.20.6}/src/protoc_gen_swagger/__init__.py +0 -0
  18. {scanoss-1.20.4 → scanoss-1.20.6}/src/protoc_gen_swagger/options/__init__.py +0 -0
  19. {scanoss-1.20.4 → scanoss-1.20.6}/src/protoc_gen_swagger/options/annotations_pb2.py +0 -0
  20. {scanoss-1.20.4 → scanoss-1.20.6}/src/protoc_gen_swagger/options/annotations_pb2_grpc.py +0 -0
  21. {scanoss-1.20.4 → scanoss-1.20.6}/src/protoc_gen_swagger/options/openapiv2_pb2.py +0 -0
  22. {scanoss-1.20.4 → scanoss-1.20.6}/src/protoc_gen_swagger/options/openapiv2_pb2_grpc.py +0 -0
  23. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/api/__init__.py +0 -0
  24. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/api/common/__init__.py +0 -0
  25. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/api/common/v2/__init__.py +0 -0
  26. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/api/common/v2/scanoss_common_pb2.py +0 -0
  27. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/api/common/v2/scanoss_common_pb2_grpc.py +0 -0
  28. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/api/components/__init__.py +0 -0
  29. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/api/components/v2/__init__.py +0 -0
  30. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/api/components/v2/scanoss_components_pb2.py +0 -0
  31. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/api/components/v2/scanoss_components_pb2_grpc.py +0 -0
  32. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/api/cryptography/v2/scanoss_cryptography_pb2.py +0 -0
  33. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/api/cryptography/v2/scanoss_cryptography_pb2_grpc.py +0 -0
  34. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/api/dependencies/__init__.py +0 -0
  35. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/api/dependencies/v2/__init__.py +0 -0
  36. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/api/dependencies/v2/scanoss_dependencies_pb2.py +0 -0
  37. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/api/dependencies/v2/scanoss_dependencies_pb2_grpc.py +0 -0
  38. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/api/provenance/__init__.py +0 -0
  39. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/api/provenance/v2/__init__.py +0 -0
  40. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/api/provenance/v2/scanoss_provenance_pb2.py +0 -0
  41. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/api/provenance/v2/scanoss_provenance_pb2_grpc.py +0 -0
  42. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/api/scanning/__init__.py +0 -0
  43. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/api/scanning/v2/__init__.py +0 -0
  44. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/api/scanning/v2/scanoss_scanning_pb2.py +0 -0
  45. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/api/scanning/v2/scanoss_scanning_pb2_grpc.py +0 -0
  46. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/api/semgrep/__init__.py +0 -0
  47. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/api/semgrep/v2/__init__.py +0 -0
  48. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/api/semgrep/v2/scanoss_semgrep_pb2.py +0 -0
  49. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/api/semgrep/v2/scanoss_semgrep_pb2_grpc.py +0 -0
  50. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/api/vulnerabilities/__init__.py +0 -0
  51. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/api/vulnerabilities/v2/__init__.py +0 -0
  52. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2.py +0 -0
  53. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2_grpc.py +0 -0
  54. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/csvoutput.py +0 -0
  55. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/cyclonedx.py +0 -0
  56. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/data/scanoss-settings-schema.json +0 -0
  57. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/data/spdx-exceptions.json +0 -0
  58. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/data/spdx-licenses.json +0 -0
  59. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/file_filters.py +0 -0
  60. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/filecount.py +0 -0
  61. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/inspection/__init__.py +0 -0
  62. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/inspection/copyleft.py +0 -0
  63. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/inspection/policy_check.py +0 -0
  64. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/inspection/undeclared_component.py +0 -0
  65. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/inspection/utils/license_utils.py +0 -0
  66. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/results.py +0 -0
  67. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/scancodedeps.py +0 -0
  68. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/scanoss_settings.py +0 -0
  69. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/scanossbase.py +0 -0
  70. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/scanpostprocessor.py +0 -0
  71. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/scantype.py +0 -0
  72. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/threadeddependencies.py +0 -0
  73. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/threadedscanning.py +0 -0
  74. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/utils/__init__.py +0 -0
  75. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/utils/file.py +0 -0
  76. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss/winnowing.py +0 -0
  77. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss.egg-info/SOURCES.txt +0 -0
  78. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss.egg-info/dependency_links.txt +0 -0
  79. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss.egg-info/entry_points.txt +0 -0
  80. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss.egg-info/requires.txt +0 -0
  81. {scanoss-1.20.4 → scanoss-1.20.6}/src/scanoss.egg-info/top_level.txt +0 -0
  82. {scanoss-1.20.4 → scanoss-1.20.6}/tests/test_csv_output.py +0 -0
  83. {scanoss-1.20.4 → scanoss-1.20.6}/tests/test_file_filters.py +0 -0
  84. {scanoss-1.20.4 → scanoss-1.20.6}/tests/test_policy_inspect.py +0 -0
  85. {scanoss-1.20.4 → scanoss-1.20.6}/tests/test_scan_post_processor.py +0 -0
  86. {scanoss-1.20.4 → scanoss-1.20.6}/tests/test_spdxlite.py +0 -0
  87. {scanoss-1.20.4 → scanoss-1.20.6}/tests/test_winnowing.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: scanoss
3
- Version: 1.20.4
3
+ Version: 1.20.6
4
4
  Summary: Simple Python library to leverage the SCANOSS APIs
5
5
  Home-page: https://scanoss.com
6
6
  Author: SCANOSS
@@ -31,6 +31,7 @@ Requires-Dist: pathspec
31
31
  Requires-Dist: jsonschema
32
32
  Provides-Extra: fast-winnowing
33
33
  Requires-Dist: scanoss_winnowing>=0.5.0; extra == "fast-winnowing"
34
+ Dynamic: license-file
34
35
 
35
36
  # SCANOSS Python Package
36
37
  The SCANOSS python package provides a simple easy to consume library for interacting with SCANOSS APIs/Engine.
@@ -22,4 +22,4 @@ SPDX-License-Identifier: MIT
22
22
  THE SOFTWARE.
23
23
  """
24
24
 
25
- __version__ = '1.20.4'
25
+ __version__ = '1.20.6'
@@ -28,6 +28,7 @@ import sys
28
28
  from pathlib import Path
29
29
 
30
30
  import pypac
31
+ from typing import List
31
32
 
32
33
  from . import __version__
33
34
  from .components import Components
@@ -50,6 +51,7 @@ DEFAULT_TIMEOUT = 180
50
51
  MIN_TIMEOUT_VALUE = 5
51
52
  DEFAULT_RETRY = 5
52
53
  PYTHON3_OR_LATER = 3
54
+ HEADER_PARTS_COUNT = 2
53
55
 
54
56
  def print_stderr(*args, **kwargs):
55
57
  """
@@ -567,6 +569,12 @@ def setup_args() -> None: # noqa: PLR0915
567
569
  help='GRPC Proxy URL to use for connections (optional). '
568
570
  'Can also use the environment variable "grcp_proxy=<ip>:<port>"',
569
571
  )
572
+ p.add_argument(
573
+ '--header','-hdr',
574
+ action='append', # This allows multiple -H flags
575
+ type=str,
576
+ help='Headers to be sent on request (e.g., -hdr "Name: Value") - can be used multiple times'
577
+ )
570
578
 
571
579
  # Help/Trace command options
572
580
  for p in [
@@ -605,7 +613,6 @@ def setup_args() -> None: # noqa: PLR0915
605
613
  sys.exit(1)
606
614
  args.func(parser, args) # Execute the function associated with the sub-command
607
615
 
608
-
609
616
  def ver(*_):
610
617
  """
611
618
  Run the "ver" sub-command
@@ -903,6 +910,7 @@ def scan(parser, args): # noqa: PLR0912, PLR0915
903
910
  strip_hpsm_ids=args.strip_hpsm,
904
911
  strip_snippet_ids=args.strip_snippet,
905
912
  scan_settings=scan_settings,
913
+ req_headers= process_req_headers(args.header),
906
914
  )
907
915
  if args.wfp:
908
916
  if not scanner.is_file_or_snippet_scan():
@@ -1228,6 +1236,7 @@ def comp_crypto(parser, args):
1228
1236
  print_stderr(f'Error: Certificate file does not exist: {args.ca_cert}.')
1229
1237
  sys.exit(1)
1230
1238
  pac_file = get_pac_file(args.pac)
1239
+
1231
1240
  comps = Components(
1232
1241
  debug=args.debug,
1233
1242
  trace=args.trace,
@@ -1239,6 +1248,7 @@ def comp_crypto(parser, args):
1239
1248
  grpc_proxy=args.grpc_proxy,
1240
1249
  pac=pac_file,
1241
1250
  timeout=args.timeout,
1251
+ req_headers= process_req_headers(args.header),
1242
1252
  )
1243
1253
  if not comps.get_crypto_details(args.input, args.purl, args.output):
1244
1254
  sys.exit(1)
@@ -1273,6 +1283,7 @@ def comp_vulns(parser, args):
1273
1283
  grpc_proxy=args.grpc_proxy,
1274
1284
  pac=pac_file,
1275
1285
  timeout=args.timeout,
1286
+ req_headers=process_req_headers(args.header),
1276
1287
  )
1277
1288
  if not comps.get_vulnerabilities(args.input, args.purl, args.output):
1278
1289
  sys.exit(1)
@@ -1307,6 +1318,7 @@ def comp_semgrep(parser, args):
1307
1318
  grpc_proxy=args.grpc_proxy,
1308
1319
  pac=pac_file,
1309
1320
  timeout=args.timeout,
1321
+ req_headers=process_req_headers(args.header),
1310
1322
  )
1311
1323
  if not comps.get_semgrep_details(args.input, args.purl, args.output):
1312
1324
  sys.exit(1)
@@ -1344,6 +1356,7 @@ def comp_search(parser, args):
1344
1356
  grpc_proxy=args.grpc_proxy,
1345
1357
  pac=pac_file,
1346
1358
  timeout=args.timeout,
1359
+ req_headers=process_req_headers(args.header),
1347
1360
  )
1348
1361
  if not comps.search_components(
1349
1362
  args.output,
@@ -1388,6 +1401,7 @@ def comp_versions(parser, args):
1388
1401
  grpc_proxy=args.grpc_proxy,
1389
1402
  pac=pac_file,
1390
1403
  timeout=args.timeout,
1404
+ req_headers=process_req_headers(args.header),
1391
1405
  )
1392
1406
  if not comps.get_component_versions(args.output, json_file=args.input, purl=args.purl, limit=args.limit):
1393
1407
  sys.exit(1)
@@ -1412,7 +1426,7 @@ def comp_provenance(parser, args):
1412
1426
  pac_file = get_pac_file(args.pac)
1413
1427
  comps = Components(debug=args.debug, trace=args.trace, quiet=args.quiet, grpc_url=args.api2url, api_key=args.key,
1414
1428
  ca_cert=args.ca_cert, proxy=args.proxy, grpc_proxy=args.grpc_proxy, pac=pac_file,
1415
- timeout=args.timeout)
1429
+ timeout=args.timeout, req_headers=process_req_headers(args.header))
1416
1430
  if not comps.get_provenance_details(args.input, args.purl, args.output):
1417
1431
  sys.exit(1)
1418
1432
 
@@ -1456,6 +1470,31 @@ def results(parser, args):
1456
1470
  results.apply_filters().present()
1457
1471
 
1458
1472
 
1473
+ def process_req_headers(headers_array: List[str]) -> dict:
1474
+ """
1475
+ Process a list of header strings in the format "Name: Value" into a dictionary.
1476
+
1477
+ Args:
1478
+ headers_array (list): List of header strings from command line args
1479
+
1480
+ Returns:
1481
+ dict: Dictionary of header name-value pairs
1482
+ """
1483
+ # Check if headers_array is empty
1484
+ if not headers_array:
1485
+ # Array is empty
1486
+ return {}
1487
+
1488
+ dict_headers = {}
1489
+ for header_str in headers_array:
1490
+ # Split each "Name: Value" header
1491
+ parts = header_str.split(":", 1)
1492
+ if len(parts) == HEADER_PARTS_COUNT:
1493
+ name = parts[0].strip()
1494
+ value = parts[1].strip()
1495
+ dict_headers[name] = value
1496
+ return dict_headers
1497
+
1459
1498
  def main():
1460
1499
  """
1461
1500
  Run the ScanOSS CLI
@@ -25,7 +25,7 @@ SPDX-License-Identifier: MIT
25
25
  import json
26
26
  import os
27
27
  import sys
28
- from typing import TextIO, Optional, List
28
+ from typing import List, Optional, TextIO
29
29
 
30
30
  from pypac.parser import PACFile
31
31
 
@@ -39,7 +39,7 @@ class Components(ScanossBase):
39
39
  Class for Component functionality
40
40
  """
41
41
 
42
- def __init__(
42
+ def __init__( # noqa: PLR0913, PLR0915
43
43
  self,
44
44
  debug: bool = False,
45
45
  trace: bool = False,
@@ -51,6 +51,7 @@ class Components(ScanossBase):
51
51
  grpc_proxy: str = None,
52
52
  ca_cert: str = None,
53
53
  pac: PACFile = None,
54
+ req_headers: dict = None,
54
55
  ):
55
56
  """
56
57
  Handle all component style requests
@@ -80,6 +81,7 @@ class Components(ScanossBase):
80
81
  pac=pac,
81
82
  grpc_proxy=grpc_proxy,
82
83
  timeout=timeout,
84
+ req_headers=req_headers,
83
85
  )
84
86
 
85
87
  def load_purls(self, json_file: Optional[str] = None, purls: Optional[List[str]] = None) -> Optional[dict]:
@@ -242,7 +244,7 @@ class Components(ScanossBase):
242
244
  self._close_file(output_file, file)
243
245
  return success
244
246
 
245
- def search_components(
247
+ def search_components( # noqa: PLR0913, PLR0915
246
248
  self,
247
249
  output_file: str = None,
248
250
  json_file: str = None,
@@ -0,0 +1 @@
1
+ date: 20250320002157, utime: 1742430117
@@ -69,7 +69,7 @@ class Scanner(ScanossBase):
69
69
  Handle the scanning of files, snippets and dependencies
70
70
  """
71
71
 
72
- def __init__(
72
+ def __init__( # noqa: PLR0913, PLR0915
73
73
  self,
74
74
  wfp: str = None,
75
75
  scan_output: str = None,
@@ -106,6 +106,7 @@ class Scanner(ScanossBase):
106
106
  strip_snippet_ids=None,
107
107
  skip_md5_ids=None,
108
108
  scan_settings: 'ScanossSettings | None' = None,
109
+ req_headers: dict = None,
109
110
  ):
110
111
  """
111
112
  Initialise scanning class, including Winnowing, ScanossApi, ThreadedScanning
@@ -129,6 +130,7 @@ class Scanner(ScanossBase):
129
130
  self.skip_folders = skip_folders
130
131
  self.skip_size = skip_size
131
132
  self.skip_extensions = skip_extensions
133
+ self.req_headers = req_headers
132
134
  ver_details = Scanner.version_details()
133
135
 
134
136
  self.winnowing = Winnowing(
@@ -156,6 +158,7 @@ class Scanner(ScanossBase):
156
158
  ca_cert=ca_cert,
157
159
  pac=pac,
158
160
  retry=retry,
161
+ req_headers= self.req_headers,
159
162
  )
160
163
  sc_deps = ScancodeDeps(debug=debug, quiet=quiet, trace=trace, timeout=sc_timeout, sc_command=sc_command)
161
164
  grpc_api = ScanossGrpc(
@@ -169,6 +172,7 @@ class Scanner(ScanossBase):
169
172
  proxy=proxy,
170
173
  pac=pac,
171
174
  grpc_proxy=grpc_proxy,
175
+ req_headers=self.req_headers,
172
176
  )
173
177
  self.threaded_deps = ThreadedDependencies(sc_deps, grpc_api, debug=debug, quiet=quiet, trace=trace)
174
178
  self.nb_threads = nb_threads
@@ -302,7 +306,7 @@ class Scanner(ScanossBase):
302
306
 
303
307
  success = True
304
308
  if not scan_dir:
305
- raise Exception(f'ERROR: Please specify a folder to scan')
309
+ raise Exception('ERROR: Please specify a folder to scan')
306
310
  if not os.path.exists(scan_dir) or not os.path.isdir(scan_dir):
307
311
  raise Exception(f'ERROR: Specified folder does not exist or is not a folder: {scan_dir}')
308
312
  if not self.is_file_or_snippet_scan() and not self.is_dependency_scan():
@@ -386,7 +390,8 @@ class Scanner(ScanossBase):
386
390
  file_count += 1
387
391
  if self.threaded_scan:
388
392
  wfp_size = len(wfp.encode('utf-8'))
389
- # If the WFP is bigger than the max post size and we already have something stored in the scan block, add it to the queue
393
+ # If the WFP is bigger than the max post size and we already have something stored in the scan block,
394
+ # add it to the queue
390
395
  if scan_block != '' and (wfp_size + scan_size) >= self.max_post_size:
391
396
  self.threaded_scan.queue_add(scan_block)
392
397
  queue_size += 1
@@ -436,7 +441,7 @@ class Scanner(ScanossBase):
436
441
  self.threaded_scan.update_bar(create=True, file_count=file_count)
437
442
  if not scan_started:
438
443
  if not self.threaded_scan.run(wait=False): # Run the scan but do not wait for it to complete
439
- self.print_stderr(f'Warning: Some errors encounted while scanning. Results might be incomplete.')
444
+ self.print_stderr('Warning: Some errors encounted while scanning. Results might be incomplete.')
440
445
  success = False
441
446
  return success
442
447
 
@@ -457,14 +462,14 @@ class Scanner(ScanossBase):
457
462
  dep_responses = None
458
463
  if self.is_file_or_snippet_scan():
459
464
  if not self.threaded_scan.complete(): # Wait for the scans to complete
460
- self.print_stderr(f'Warning: Scanning analysis ran into some trouble.')
465
+ self.print_stderr('Warning: Scanning analysis ran into some trouble.')
461
466
  success = False
462
467
  self.threaded_scan.complete_bar()
463
468
  scan_responses = self.threaded_scan.responses
464
469
  if self.is_dependency_scan():
465
470
  self.print_msg('Retrieving dependency data...')
466
471
  if not self.threaded_deps.complete():
467
- self.print_stderr(f'Warning: Dependency analysis ran into some trouble.')
472
+ self.print_stderr('Warning: Dependency analysis ran into some trouble.')
468
473
  success = False
469
474
  dep_responses = self.threaded_deps.responses
470
475
 
@@ -546,7 +551,7 @@ class Scanner(ScanossBase):
546
551
  """
547
552
  success = True
548
553
  if not file:
549
- raise Exception(f'ERROR: Please specify a file to scan')
554
+ raise Exception('ERROR: Please specify a file to scan')
550
555
  if not os.path.exists(file) or not os.path.isfile(file):
551
556
  raise Exception(f'ERROR: Specified file does not exist or is not a file: {file}')
552
557
  if not self.is_file_or_snippet_scan() and not self.is_dependency_scan():
@@ -583,7 +588,7 @@ class Scanner(ScanossBase):
583
588
  """
584
589
  success = True
585
590
  if not file:
586
- raise Exception(f'ERROR: Please specify a file to scan')
591
+ raise Exception('ERROR: Please specify a file to scan')
587
592
  if not os.path.exists(file) or not os.path.isfile(file):
588
593
  raise Exception(f'ERROR: Specified files does not exist or is not a file: {file}')
589
594
  self.print_debug(f'Fingerprinting {file}...')
@@ -608,7 +613,7 @@ class Scanner(ScanossBase):
608
613
  """
609
614
  success = True
610
615
  if not files:
611
- raise Exception(f'ERROR: Please provide a non-empty list of filenames to scan')
616
+ raise Exception('ERROR: Please provide a non-empty list of filenames to scan')
612
617
 
613
618
  file_filters = FileFilters(
614
619
  debug=self.debug,
@@ -671,7 +676,7 @@ class Scanner(ScanossBase):
671
676
  scan_started = True
672
677
  if not self.threaded_scan.run(wait=False):
673
678
  self.print_stderr(
674
- f'Warning: Some errors encounted while scanning. Results might be incomplete.'
679
+ 'Warning: Some errors encounted while scanning. Results might be incomplete.'
675
680
  )
676
681
  success = False
677
682
 
@@ -704,12 +709,12 @@ class Scanner(ScanossBase):
704
709
  """
705
710
  success = True
706
711
  if not files:
707
- raise Exception(f'ERROR: Please specify a list of files to scan')
712
+ raise Exception('ERROR: Please specify a list of files to scan')
708
713
  if not self.is_file_or_snippet_scan():
709
714
  raise Exception(f'ERROR: file or snippet scan options have to be set to scan files: {files}')
710
715
  if self.is_dependency_scan() or deps_file:
711
716
  raise Exception(
712
- f'ERROR: The dependency scan option is currently not supported when scanning a list of files'
717
+ 'ERROR: The dependency scan option is currently not supported when scanning a list of files'
713
718
  )
714
719
  if self.scan_output:
715
720
  self.print_msg(f'Writing results to {self.scan_output}...')
@@ -731,9 +736,9 @@ class Scanner(ScanossBase):
731
736
  """
732
737
  success = True
733
738
  if not filename:
734
- raise Exception(f'ERROR: Please specify a filename to scan')
739
+ raise Exception('ERROR: Please specify a filename to scan')
735
740
  if not contents:
736
- raise Exception(f'ERROR: Please specify a file contents to scan')
741
+ raise Exception('ERROR: Please specify a file contents to scan')
737
742
 
738
743
  self.print_debug(f'Fingerprinting {filename}...')
739
744
  wfp = self.winnowing.wfp_for_contents(filename, False, contents)
@@ -924,7 +929,7 @@ class Scanner(ScanossBase):
924
929
  scan_started = True
925
930
  if not self.threaded_scan.run(wait=False):
926
931
  self.print_stderr(
927
- f'Warning: Some errors encounted while scanning. Results might be incomplete.'
932
+ 'Warning: Some errors uncounted while scanning. Results might be incomplete.'
928
933
  )
929
934
  success = False
930
935
  # End for loop
@@ -948,7 +953,7 @@ class Scanner(ScanossBase):
948
953
  """
949
954
  success = True
950
955
  if not wfp:
951
- raise Exception(f'ERROR: Please specify a WFP to scan')
956
+ raise Exception('ERROR: Please specify a WFP to scan')
952
957
  raw_output = '{\n'
953
958
  scan_resp = self.scanoss_api.scan(wfp)
954
959
  if scan_resp is not None:
@@ -984,9 +989,9 @@ class Scanner(ScanossBase):
984
989
  :return:
985
990
  """
986
991
  if not filename:
987
- raise Exception(f'ERROR: Please specify a filename to scan')
992
+ raise Exception('ERROR: Please specify a filename to scan')
988
993
  if not contents:
989
- raise Exception(f'ERROR: Please specify a file contents to scan')
994
+ raise Exception('ERROR: Please specify a file contents to scan')
990
995
 
991
996
  self.print_debug(f'Fingerprinting {filename}...')
992
997
  wfp = self.winnowing.wfp_for_contents(filename, False, contents)
@@ -1005,7 +1010,7 @@ class Scanner(ScanossBase):
1005
1010
  Fingerprint the specified file
1006
1011
  """
1007
1012
  if not scan_file:
1008
- raise Exception(f'ERROR: Please specify a file to fingerprint')
1013
+ raise Exception('ERROR: Please specify a file to fingerprint')
1009
1014
  if not os.path.exists(scan_file) or not os.path.isfile(scan_file):
1010
1015
  raise Exception(f'ERROR: Specified file does not exist or is not a file: {scan_file}')
1011
1016
 
@@ -1026,7 +1031,7 @@ class Scanner(ScanossBase):
1026
1031
  Fingerprint the specified folder producing fingerprints
1027
1032
  """
1028
1033
  if not scan_dir:
1029
- raise Exception(f'ERROR: Please specify a folder to fingerprint')
1034
+ raise Exception('ERROR: Please specify a folder to fingerprint')
1030
1035
  if not os.path.exists(scan_dir) or not os.path.isdir(scan_dir):
1031
1036
  raise Exception(f'ERROR: Specified folder does not exist or is not a folder: {scan_dir}')
1032
1037
  file_filters = FileFilters(
@@ -52,7 +52,7 @@ class ScanossApi(ScanossBase):
52
52
  Currently support posting scan requests to the SCANOSS streaming API
53
53
  """
54
54
 
55
- def __init__(
55
+ def __init__( # noqa: PLR0913, PLR0915
56
56
  self,
57
57
  scan_format: str = None,
58
58
  flags: str = None,
@@ -68,6 +68,7 @@ class ScanossApi(ScanossBase):
68
68
  ca_cert: str = None,
69
69
  pac: PACFile = None,
70
70
  retry: int = 5,
71
+ req_headers: dict = None,
71
72
  ):
72
73
  """
73
74
  Initialise the SCANOSS API
@@ -86,17 +87,17 @@ class ScanossApi(ScanossBase):
86
87
  HTTPS_PROXY='http://<ip>:<port>'
87
88
  """
88
89
  super().__init__(debug, trace, quiet)
89
- self.url = url if url else SCANOSS_SCAN_URL
90
- self.api_key = api_key if api_key else SCANOSS_API_KEY
91
- if self.api_key and not url and not os.environ.get('SCANOSS_SCAN_URL'):
92
- self.url = DEFAULT_URL2 # API key specific and no alternative URL, so use the default premium
90
+ self.url = url
91
+ self.api_key = api_key
93
92
  self.sbom = None
94
93
  self.scan_format = scan_format if scan_format else 'plain'
95
94
  self.flags = flags
96
95
  self.timeout = timeout if timeout > 5 else 180
97
96
  self.retry_limit = retry if retry >= 0 else 5
98
97
  self.ignore_cert_errors = ignore_cert_errors
98
+ self.req_headers = req_headers if req_headers else {}
99
99
  self.headers = {}
100
+
100
101
  if ver_details:
101
102
  self.headers['x-scanoss-client'] = ver_details
102
103
  if self.api_key:
@@ -104,17 +105,24 @@ class ScanossApi(ScanossBase):
104
105
  self.headers['x-api-key'] = self.api_key
105
106
  self.headers['User-Agent'] = f'scanoss-py/{__version__}'
106
107
  self.headers['user-agent'] = f'scanoss-py/{__version__}'
108
+ self.load_generic_headers()
109
+
110
+ self.url = url if url else SCANOSS_SCAN_URL
111
+ self.api_key = api_key if api_key else SCANOSS_API_KEY
112
+ if self.api_key and not url and not os.environ.get('SCANOSS_SCAN_URL'):
113
+ self.url = DEFAULT_URL2 # API key specific and no alternative URL, so use the default premium
114
+
107
115
  if self.trace:
108
116
  logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
109
117
  http_client.HTTPConnection.debuglevel = 1
110
118
  if pac and not proxy: # Setup PAC session if requested (and no proxy has been explicitly set)
111
- self.print_debug(f'Setting up PAC session...')
119
+ self.print_debug('Setting up PAC session...')
112
120
  self.session = PACSession(pac=pac)
113
121
  else:
114
122
  self.session = requests.sessions.Session()
115
123
  self.verify = None
116
124
  if self.ignore_cert_errors:
117
- self.print_debug(f'Ignoring cert errors...')
125
+ self.print_debug('Ignoring cert errors...')
118
126
  urllib3.disable_warnings(InsecureRequestWarning)
119
127
  self.verify = False
120
128
  self.session.verify = False
@@ -261,6 +269,20 @@ class ScanossApi(ScanossBase):
261
269
  self.sbom = sbom
262
270
  return self
263
271
 
272
+ def load_generic_headers(self):
273
+ """
274
+ Adds custom headers from req_headers to the headers collection.
275
+
276
+ If x-api-key is present and no URL is configured (directly or via
277
+ environment), sets URL to the premium endpoint (DEFAULT_URL2).
278
+ """
279
+ if self.req_headers: # Load generic headers
280
+ for key, value in self.req_headers.items():
281
+ if key == 'x-api-key': # Set premium URL if x-api-key header is set
282
+ if not self.url and not os.environ.get('SCANOSS_SCAN_URL'):
283
+ self.url = DEFAULT_URL2 # API key specific and no alternative URL, so use the default premium
284
+ self.api_key = value
285
+ self.headers[key] = value
264
286
 
265
287
  #
266
288
  # End of ScanossApi Class