scanoss 1.43.0__tar.gz → 1.44.0__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 (125) hide show
  1. {scanoss-1.43.0 → scanoss-1.44.0}/PACKAGE.md +2 -2
  2. {scanoss-1.43.0/src/scanoss.egg-info → scanoss-1.44.0}/PKG-INFO +3 -3
  3. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/__init__.py +1 -1
  4. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/cli.py +12 -1
  5. scanoss-1.44.0/src/scanoss/data/build_date.txt +1 -0
  6. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/scanner.py +16 -0
  7. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/scanossapi.py +44 -13
  8. {scanoss-1.43.0 → scanoss-1.44.0/src/scanoss.egg-info}/PKG-INFO +3 -3
  9. scanoss-1.43.0/src/scanoss/data/build_date.txt +0 -1
  10. {scanoss-1.43.0 → scanoss-1.44.0}/LICENSE +0 -0
  11. {scanoss-1.43.0 → scanoss-1.44.0}/README.md +0 -0
  12. {scanoss-1.43.0 → scanoss-1.44.0}/pyproject.toml +0 -0
  13. {scanoss-1.43.0 → scanoss-1.44.0}/setup.cfg +0 -0
  14. {scanoss-1.43.0 → scanoss-1.44.0}/src/protoc_gen_swagger/__init__.py +0 -0
  15. {scanoss-1.43.0 → scanoss-1.44.0}/src/protoc_gen_swagger/options/__init__.py +0 -0
  16. {scanoss-1.43.0 → scanoss-1.44.0}/src/protoc_gen_swagger/options/annotations_pb2.py +0 -0
  17. {scanoss-1.43.0 → scanoss-1.44.0}/src/protoc_gen_swagger/options/annotations_pb2.pyi +0 -0
  18. {scanoss-1.43.0 → scanoss-1.44.0}/src/protoc_gen_swagger/options/annotations_pb2_grpc.py +0 -0
  19. {scanoss-1.43.0 → scanoss-1.44.0}/src/protoc_gen_swagger/options/openapiv2_pb2.py +0 -0
  20. {scanoss-1.43.0 → scanoss-1.44.0}/src/protoc_gen_swagger/options/openapiv2_pb2.pyi +0 -0
  21. {scanoss-1.43.0 → scanoss-1.44.0}/src/protoc_gen_swagger/options/openapiv2_pb2_grpc.py +0 -0
  22. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/api/__init__.py +0 -0
  23. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/api/common/__init__.py +0 -0
  24. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/api/common/v2/__init__.py +0 -0
  25. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/api/common/v2/scanoss_common_pb2.py +0 -0
  26. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/api/common/v2/scanoss_common_pb2_grpc.py +0 -0
  27. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/api/components/__init__.py +0 -0
  28. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/api/components/v2/__init__.py +0 -0
  29. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/api/components/v2/scanoss_components_pb2.py +0 -0
  30. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/api/components/v2/scanoss_components_pb2_grpc.py +0 -0
  31. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/api/cryptography/v2/scanoss_cryptography_pb2.py +0 -0
  32. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/api/cryptography/v2/scanoss_cryptography_pb2_grpc.py +0 -0
  33. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/api/dependencies/__init__.py +0 -0
  34. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/api/dependencies/v2/__init__.py +0 -0
  35. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/api/dependencies/v2/scanoss_dependencies_pb2.py +0 -0
  36. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/api/dependencies/v2/scanoss_dependencies_pb2_grpc.py +0 -0
  37. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/api/geoprovenance/__init__.py +0 -0
  38. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/api/geoprovenance/v2/__init__.py +0 -0
  39. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/api/geoprovenance/v2/scanoss_geoprovenance_pb2.py +0 -0
  40. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/api/geoprovenance/v2/scanoss_geoprovenance_pb2_grpc.py +0 -0
  41. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/api/licenses/__init__.py +0 -0
  42. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/api/licenses/v2/__init__.py +0 -0
  43. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/api/licenses/v2/scanoss_licenses_pb2.py +0 -0
  44. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/api/licenses/v2/scanoss_licenses_pb2_grpc.py +0 -0
  45. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/api/scanning/__init__.py +0 -0
  46. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/api/scanning/v2/__init__.py +0 -0
  47. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/api/scanning/v2/scanoss_scanning_pb2.py +0 -0
  48. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/api/scanning/v2/scanoss_scanning_pb2_grpc.py +0 -0
  49. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/api/semgrep/__init__.py +0 -0
  50. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/api/semgrep/v2/__init__.py +0 -0
  51. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/api/semgrep/v2/scanoss_semgrep_pb2.py +0 -0
  52. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/api/semgrep/v2/scanoss_semgrep_pb2_grpc.py +0 -0
  53. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/api/vulnerabilities/__init__.py +0 -0
  54. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/api/vulnerabilities/v2/__init__.py +0 -0
  55. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2.py +0 -0
  56. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2_grpc.py +0 -0
  57. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/components.py +0 -0
  58. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/constants.py +0 -0
  59. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/cryptography.py +0 -0
  60. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/csvoutput.py +0 -0
  61. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/cyclonedx.py +0 -0
  62. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/data/osadl-copyleft.json +0 -0
  63. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/data/scanoss-settings-schema.json +0 -0
  64. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/data/spdx-exceptions.json +0 -0
  65. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/data/spdx-licenses.json +0 -0
  66. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/delta.py +0 -0
  67. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/export/__init__.py +0 -0
  68. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/export/dependency_track.py +0 -0
  69. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/file_filters.py +0 -0
  70. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/filecount.py +0 -0
  71. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/gitlabqualityreport.py +0 -0
  72. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/header_filter.py +0 -0
  73. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/inspection/__init__.py +0 -0
  74. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/inspection/policy_check/__init__.py +0 -0
  75. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/inspection/policy_check/dependency_track/__init__.py +0 -0
  76. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/inspection/policy_check/dependency_track/project_violation.py +0 -0
  77. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/inspection/policy_check/policy_check.py +0 -0
  78. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/inspection/policy_check/scanoss/__init__.py +0 -0
  79. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/inspection/policy_check/scanoss/copyleft.py +0 -0
  80. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/inspection/policy_check/scanoss/undeclared_component.py +0 -0
  81. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/inspection/summary/__init__.py +0 -0
  82. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/inspection/summary/component_summary.py +0 -0
  83. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/inspection/summary/license_summary.py +0 -0
  84. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/inspection/summary/match_summary.py +0 -0
  85. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/inspection/utils/file_utils.py +0 -0
  86. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/inspection/utils/license_utils.py +0 -0
  87. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/inspection/utils/markdown_utils.py +0 -0
  88. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/inspection/utils/scan_result_processor.py +0 -0
  89. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/osadl.py +0 -0
  90. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/results.py +0 -0
  91. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/scancodedeps.py +0 -0
  92. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/scanners/__init__.py +0 -0
  93. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/scanners/container_scanner.py +0 -0
  94. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/scanners/folder_hasher.py +0 -0
  95. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/scanners/scanner_config.py +0 -0
  96. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/scanners/scanner_hfh.py +0 -0
  97. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/scanoss_settings.py +0 -0
  98. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/scanossbase.py +0 -0
  99. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/scanossgrpc.py +0 -0
  100. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/scanpostprocessor.py +0 -0
  101. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/scantype.py +0 -0
  102. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/services/dependency_track_service.py +0 -0
  103. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/spdxlite.py +0 -0
  104. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/threadeddependencies.py +0 -0
  105. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/threadedscanning.py +0 -0
  106. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/utils/__init__.py +0 -0
  107. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/utils/abstract_presenter.py +0 -0
  108. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/utils/crc64.py +0 -0
  109. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/utils/file.py +0 -0
  110. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/utils/scanoss_scan_results_utils.py +0 -0
  111. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/utils/simhash.py +0 -0
  112. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss/winnowing.py +0 -0
  113. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss.egg-info/SOURCES.txt +0 -0
  114. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss.egg-info/dependency_links.txt +0 -0
  115. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss.egg-info/entry_points.txt +0 -0
  116. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss.egg-info/requires.txt +0 -0
  117. {scanoss-1.43.0 → scanoss-1.44.0}/src/scanoss.egg-info/top_level.txt +0 -0
  118. {scanoss-1.43.0 → scanoss-1.44.0}/tests/test_csv_output.py +0 -0
  119. {scanoss-1.43.0 → scanoss-1.44.0}/tests/test_file_filters.py +0 -0
  120. {scanoss-1.43.0 → scanoss-1.44.0}/tests/test_headers_filter.py +0 -0
  121. {scanoss-1.43.0 → scanoss-1.44.0}/tests/test_osadl.py +0 -0
  122. {scanoss-1.43.0 → scanoss-1.44.0}/tests/test_policy_inspect.py +0 -0
  123. {scanoss-1.43.0 → scanoss-1.44.0}/tests/test_scan_post_processor.py +0 -0
  124. {scanoss-1.43.0 → scanoss-1.44.0}/tests/test_spdxlite.py +0 -0
  125. {scanoss-1.43.0 → scanoss-1.44.0}/tests/test_winnowing.py +0 -0
@@ -117,8 +117,8 @@ if __name__ == "__main__":
117
117
  ```
118
118
 
119
119
  ## Scanning URL and API Key
120
- By Default, scanoss uses the API URL endpoint for SCANOSS OSS KB: https://api.osskb.org/scan/direct.
121
- This API does not require an API key.
120
+ By Default, scanoss uses the API base URL for SCANOSS OSS KB: https://api.osskb.org.
121
+ The `/scan/direct` endpoint is automatically appended. This API does not require an API key.
122
122
 
123
123
  These values can be changed from the command line using:
124
124
  ```bash
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: scanoss
3
- Version: 1.43.0
3
+ Version: 1.44.0
4
4
  Summary: Simple Python library to leverage the SCANOSS APIs
5
5
  Home-page: https://scanoss.com
6
6
  Author: SCANOSS
@@ -156,8 +156,8 @@ if __name__ == "__main__":
156
156
  ```
157
157
 
158
158
  ## Scanning URL and API Key
159
- By Default, scanoss uses the API URL endpoint for SCANOSS OSS KB: https://api.osskb.org/scan/direct.
160
- This API does not require an API key.
159
+ By Default, scanoss uses the API base URL for SCANOSS OSS KB: https://api.osskb.org.
160
+ The `/scan/direct` endpoint is automatically appended. This API does not require an API key.
161
161
 
162
162
  These values can be changed from the command line using:
163
163
  ```bash
@@ -22,4 +22,4 @@ SPDX-License-Identifier: MIT
22
22
  THE SOFTWARE.
23
23
  """
24
24
 
25
- __version__ = '1.43.0'
25
+ __version__ = '1.44.0'
@@ -186,6 +186,14 @@ def setup_args() -> None: # noqa: PLR0912, PLR0915
186
186
  )
187
187
  p_scan.add_argument('--dep-scope-inc', '-dsi', type=str, help='Include dependencies with declared scopes')
188
188
  p_scan.add_argument('--dep-scope-exc', '-dse', type=str, help='Exclude dependencies with declared scopes')
189
+ p_scan.add_argument(
190
+ '--no-wfp-output', action='store_true',
191
+ help='DEPRECATED: Scans no longer generate scanner_output.wfp. Use "fingerprint -o" to create WFP files.'
192
+ )
193
+ p_scan.add_argument(
194
+ '--wfp-output', type=str, metavar='FILE',
195
+ help='Save fingerprints to specified file during scan'
196
+ )
189
197
 
190
198
  # Sub-command: fingerprint
191
199
  p_wfp = subparsers.add_parser(
@@ -1072,7 +1080,7 @@ def setup_args() -> None: # noqa: PLR0912, PLR0915
1072
1080
  # Global Scan command options
1073
1081
  for p in [p_scan, p_cs]:
1074
1082
  p.add_argument(
1075
- '--apiurl', type=str, help='SCANOSS API URL (optional - default: https://api.osskb.org/scan/direct)'
1083
+ '--apiurl', type=str, help='SCANOSS API base URL (optional - default: https://api.osskb.org)'
1076
1084
  )
1077
1085
 
1078
1086
  # Global Scan/Fingerprint filter options
@@ -1470,6 +1478,8 @@ def scan(parser, args): # noqa: PLR0912, PLR0915
1470
1478
  )
1471
1479
  parser.parse_args([args.subparser, '-h'])
1472
1480
  sys.exit(1)
1481
+ if args.no_wfp_output:
1482
+ print_stderr('Warning: --no-wfp-output is deprecated and has no effect. It will be removed in a future version')
1473
1483
  if args.pac and args.proxy:
1474
1484
  print_stderr('Please specify one of --proxy or --pac, not both')
1475
1485
  parser.parse_args([args.subparser, '-h'])
@@ -1595,6 +1605,7 @@ def scan(parser, args): # noqa: PLR0912, PLR0915
1595
1605
  use_grpc=args.grpc,
1596
1606
  skip_headers=args.skip_headers,
1597
1607
  skip_headers_limit=args.skip_headers_limit,
1608
+ wfp_output=args.wfp_output,
1598
1609
  )
1599
1610
  if args.wfp:
1600
1611
  if not scanner.is_file_or_snippet_scan():
@@ -0,0 +1 @@
1
+ date: 20260122124532, utime: 1769085932
@@ -108,6 +108,7 @@ class Scanner(ScanossBase):
108
108
  use_grpc: bool = False,
109
109
  skip_headers: bool = False,
110
110
  skip_headers_limit: int = 0,
111
+ wfp_output: str = None,
111
112
  ):
112
113
  """
113
114
  Initialise scanning class, including Winnowing, ScanossApi, ThreadedScanning
@@ -119,6 +120,7 @@ class Scanner(ScanossBase):
119
120
  skip_extensions = []
120
121
  self.scan_output = scan_output
121
122
  self.output_format = output_format
123
+ self.wfp_output = wfp_output
122
124
  self.isatty = sys.stderr.isatty()
123
125
  self.all_extensions = all_extensions
124
126
  self.all_folders = all_folders
@@ -373,6 +375,7 @@ class Scanner(ScanossBase):
373
375
  file_count = 0 # count all files fingerprinted
374
376
  wfp_file_count = 0 # count number of files in each queue post
375
377
  scan_started = False
378
+ wfp_list = [] if self.wfp_output else None # Collect WFPs if output file is specified
376
379
 
377
380
  to_scan_files = file_filters.get_filtered_files_from_folder(scan_dir)
378
381
  for to_scan_file in to_scan_files:
@@ -387,6 +390,8 @@ class Scanner(ScanossBase):
387
390
  if wfp is None or wfp == '':
388
391
  self.print_debug(f'No WFP returned for {to_scan_file}. Skipping.')
389
392
  continue
393
+ if wfp_list is not None:
394
+ wfp_list.append(wfp)
390
395
  file_count += 1
391
396
  if self.threaded_scan:
392
397
  wfp_size = len(wfp.encode('utf-8'))
@@ -420,6 +425,10 @@ class Scanner(ScanossBase):
420
425
  self.threaded_scan.queue_add(scan_block) # Make sure all files have been submitted
421
426
 
422
427
  if file_count > 0:
428
+ if wfp_list is not None:
429
+ self.print_debug(f'Writing fingerprints to {self.wfp_output}')
430
+ with open(self.wfp_output, 'w') as f:
431
+ f.write(''.join(wfp_list))
423
432
  if self.threaded_scan:
424
433
  success = self.__run_scan_threaded(scan_started, file_count)
425
434
  else:
@@ -633,6 +642,7 @@ class Scanner(ScanossBase):
633
642
  file_count = 0 # count all files fingerprinted
634
643
  wfp_file_count = 0 # count number of files in each queue post
635
644
  scan_started = False
645
+ wfp_list = [] if self.wfp_output else None # Collect WFPs if output file is specified
636
646
 
637
647
  to_scan_files = file_filters.get_filtered_files_from_files(files)
638
648
  for file in to_scan_files:
@@ -646,6 +656,8 @@ class Scanner(ScanossBase):
646
656
  if wfp is None or wfp == '':
647
657
  self.print_debug(f'No WFP returned for {file}. Skipping.')
648
658
  continue
659
+ if wfp_list is not None:
660
+ wfp_list.append(wfp)
649
661
  file_count += 1
650
662
  if self.threaded_scan:
651
663
  wfp_size = len(wfp.encode('utf-8'))
@@ -680,6 +692,10 @@ class Scanner(ScanossBase):
680
692
  self.threaded_scan.queue_add(scan_block) # Make sure all files have been submitted
681
693
 
682
694
  if file_count > 0:
695
+ if wfp_list is not None:
696
+ self.print_debug(f'Writing fingerprints to {self.wfp_output}')
697
+ with open(self.wfp_output, 'w') as f:
698
+ f.write(''.join(wfp_list))
683
699
  if self.threaded_scan:
684
700
  success = self.__run_scan_threaded(scan_started, file_count)
685
701
  else:
@@ -29,6 +29,7 @@ import sys
29
29
  import time
30
30
  import uuid
31
31
  from json.decoder import JSONDecodeError
32
+ from urllib.parse import urlparse, urlunparse
32
33
 
33
34
  import requests
34
35
  import urllib3
@@ -40,8 +41,9 @@ from . import __version__
40
41
  from .constants import DEFAULT_TIMEOUT, MIN_TIMEOUT
41
42
  from .scanossbase import ScanossBase
42
43
 
43
- DEFAULT_URL = 'https://api.osskb.org/scan/direct' # default free service URL
44
- DEFAULT_URL2 = 'https://api.scanoss.com/scan/direct' # default premium service URL
44
+ DEFAULT_URL = 'https://api.osskb.org' # default free service base URL
45
+ DEFAULT_URL2 = 'https://api.scanoss.com' # default premium service base URL
46
+ SCAN_ENDPOINT = '/scan/direct' # scan endpoint path
45
47
  SCANOSS_SCAN_URL = os.environ.get('SCANOSS_SCAN_URL') if os.environ.get('SCANOSS_SCAN_URL') else DEFAULT_URL
46
48
  SCANOSS_API_KEY = os.environ.get('SCANOSS_API_KEY') if os.environ.get('SCANOSS_API_KEY') else ''
47
49
 
@@ -52,6 +54,33 @@ class ScanossApi(ScanossBase):
52
54
  Currently support posting scan requests to the SCANOSS streaming API
53
55
  """
54
56
 
57
+ def normalize_api_url(self, url: str) -> str:
58
+ """
59
+ Normalize API URL to ensure it's a base URL with the scan endpoint appended.
60
+
61
+ If the URL contains a path component (e.g., /scan/direct), a warning is emitted
62
+ and the path is stripped to use only the base URL.
63
+
64
+ :param url: Input URL (can be base URL or full endpoint URL)
65
+ :return: Normalized URL with /scan/direct endpoint
66
+ """
67
+ if not url:
68
+ return url
69
+
70
+ url = url.strip()
71
+ parsed = urlparse(url)
72
+
73
+ if parsed.path and parsed.path != '/':
74
+ self.print_stderr(
75
+ f"Warning: URL '{url}' contains path '{parsed.path}'. "
76
+ f"Using base URL only: '{parsed.scheme}://{parsed.netloc}'"
77
+ )
78
+ base_url = urlunparse((parsed.scheme, parsed.netloc, '', '', '', ''))
79
+ else:
80
+ base_url = url.rstrip('/')
81
+
82
+ return f'{base_url}{SCAN_ENDPOINT}'
83
+
55
84
  def __init__( # noqa: PLR0912, PLR0913, PLR0915
56
85
  self,
57
86
  scan_format: str = None,
@@ -74,7 +103,7 @@ class ScanossApi(ScanossBase):
74
103
  Initialise the SCANOSS API
75
104
  :param scan_format: Scan format (default plain)
76
105
  :param flags: Scanning flags (default None)
77
- :param url: API URL (default https://api.osskb.org/scan/direct)
106
+ :param url: API base URL (default https://api.osskb.org). The /scan/direct endpoint is automatically appended.
78
107
  :param api_key: API Key (default None)
79
108
  :param debug: Enable debug (default False)
80
109
  :param trace: Enable trace (default False)
@@ -95,11 +124,11 @@ class ScanossApi(ScanossBase):
95
124
  self.ignore_cert_errors = ignore_cert_errors
96
125
  self.req_headers = req_headers if req_headers else {}
97
126
  self.headers = {}
98
- # Set the correct URL/API key combination
99
- self.url = url if url else SCANOSS_SCAN_URL
127
+ base_url = url if url else SCANOSS_SCAN_URL
100
128
  self.api_key = api_key if api_key else SCANOSS_API_KEY
101
129
  if self.api_key and not url and not os.environ.get('SCANOSS_SCAN_URL'):
102
- self.url = DEFAULT_URL2 # API key specific and no alternative URL, so use the default premium
130
+ base_url = DEFAULT_URL2
131
+ self.url = self.normalize_api_url(base_url)
103
132
  if ver_details:
104
133
  self.headers['x-scanoss-client'] = ver_details
105
134
  if self.api_key:
@@ -113,7 +142,7 @@ class ScanossApi(ScanossBase):
113
142
  if self.trace:
114
143
  logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
115
144
  http_client.HTTPConnection.debuglevel = 1
116
- if pac and not proxy: # Setup PAC session if requested (and no proxy has been explicitly set)
145
+ if pac and not proxy:
117
146
  self.print_debug('Setting up PAC session...')
118
147
  self.session = PACSession(pac=pac)
119
148
  else:
@@ -269,19 +298,21 @@ class ScanossApi(ScanossBase):
269
298
 
270
299
  def load_generic_headers(self, url):
271
300
  """
272
- Adds custom headers from req_headers to the headers collection.
301
+ Adds custom headers from req_headers to the headers collection.
273
302
 
274
- If x-api-key is present and no URL is configured (directly or via
275
- environment), sets URL to the premium endpoint (DEFAULT_URL2).
276
- """
303
+ If x-api-key is present and no URL is configured (directly or via
304
+ environment), sets URL to the premium endpoint (DEFAULT_URL2).
305
+ """
277
306
  if self.req_headers: # Load generic headers
278
307
  for key, value in self.req_headers.items():
279
- if key == 'x-api-key': # Set premium URL if x-api-key header is set
308
+ if key == 'x-api-key': # Set premium URL if x-api-key header is set
280
309
  if not url and not os.environ.get('SCANOSS_SCAN_URL'):
281
- self.url = DEFAULT_URL2 # API key specific and no alternative URL, so use the default premium
310
+ # API key specific and no alternative URL, so use the default premium
311
+ self.url = self.normalize_api_url(DEFAULT_URL2)
282
312
  self.api_key = value
283
313
  self.headers[key] = value
284
314
 
315
+
285
316
  #
286
317
  # End of ScanossApi Class
287
318
  #
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: scanoss
3
- Version: 1.43.0
3
+ Version: 1.44.0
4
4
  Summary: Simple Python library to leverage the SCANOSS APIs
5
5
  Home-page: https://scanoss.com
6
6
  Author: SCANOSS
@@ -156,8 +156,8 @@ if __name__ == "__main__":
156
156
  ```
157
157
 
158
158
  ## Scanning URL and API Key
159
- By Default, scanoss uses the API URL endpoint for SCANOSS OSS KB: https://api.osskb.org/scan/direct.
160
- This API does not require an API key.
159
+ By Default, scanoss uses the API base URL for SCANOSS OSS KB: https://api.osskb.org.
160
+ The `/scan/direct` endpoint is automatically appended. This API does not require an API key.
161
161
 
162
162
  These values can be changed from the command line using:
163
163
  ```bash
@@ -1 +0,0 @@
1
- date: 20260105093002, utime: 1767605402
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes