scanoss 1.20.1__tar.gz → 1.20.3__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.1/src/scanoss.egg-info → scanoss-1.20.3}/PKG-INFO +1 -1
  2. {scanoss-1.20.1 → scanoss-1.20.3}/pyproject.toml +1 -1
  3. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/__init__.py +1 -1
  4. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/cli.py +112 -87
  5. scanoss-1.20.3/src/scanoss/data/build_date.txt +1 -0
  6. {scanoss-1.20.1 → scanoss-1.20.3/src/scanoss.egg-info}/PKG-INFO +1 -1
  7. scanoss-1.20.1/src/scanoss/data/build_date.txt +0 -1
  8. {scanoss-1.20.1 → scanoss-1.20.3}/LICENSE +0 -0
  9. {scanoss-1.20.1 → scanoss-1.20.3}/PACKAGE.md +0 -0
  10. {scanoss-1.20.1 → scanoss-1.20.3}/README.md +0 -0
  11. {scanoss-1.20.1 → scanoss-1.20.3}/setup.cfg +0 -0
  12. {scanoss-1.20.1 → scanoss-1.20.3}/src/protoc_gen_swagger/__init__.py +0 -0
  13. {scanoss-1.20.1 → scanoss-1.20.3}/src/protoc_gen_swagger/options/__init__.py +0 -0
  14. {scanoss-1.20.1 → scanoss-1.20.3}/src/protoc_gen_swagger/options/annotations_pb2.py +0 -0
  15. {scanoss-1.20.1 → scanoss-1.20.3}/src/protoc_gen_swagger/options/annotations_pb2_grpc.py +0 -0
  16. {scanoss-1.20.1 → scanoss-1.20.3}/src/protoc_gen_swagger/options/openapiv2_pb2.py +0 -0
  17. {scanoss-1.20.1 → scanoss-1.20.3}/src/protoc_gen_swagger/options/openapiv2_pb2_grpc.py +0 -0
  18. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/api/__init__.py +0 -0
  19. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/api/common/__init__.py +0 -0
  20. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/api/common/v2/__init__.py +0 -0
  21. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/api/common/v2/scanoss_common_pb2.py +0 -0
  22. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/api/common/v2/scanoss_common_pb2_grpc.py +0 -0
  23. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/api/components/__init__.py +0 -0
  24. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/api/components/v2/__init__.py +0 -0
  25. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/api/components/v2/scanoss_components_pb2.py +0 -0
  26. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/api/components/v2/scanoss_components_pb2_grpc.py +0 -0
  27. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/api/cryptography/v2/scanoss_cryptography_pb2.py +0 -0
  28. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/api/cryptography/v2/scanoss_cryptography_pb2_grpc.py +0 -0
  29. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/api/dependencies/__init__.py +0 -0
  30. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/api/dependencies/v2/__init__.py +0 -0
  31. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/api/dependencies/v2/scanoss_dependencies_pb2.py +0 -0
  32. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/api/dependencies/v2/scanoss_dependencies_pb2_grpc.py +0 -0
  33. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/api/provenance/__init__.py +0 -0
  34. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/api/provenance/v2/__init__.py +0 -0
  35. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/api/provenance/v2/scanoss_provenance_pb2.py +0 -0
  36. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/api/provenance/v2/scanoss_provenance_pb2_grpc.py +0 -0
  37. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/api/scanning/__init__.py +0 -0
  38. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/api/scanning/v2/__init__.py +0 -0
  39. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/api/scanning/v2/scanoss_scanning_pb2.py +0 -0
  40. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/api/scanning/v2/scanoss_scanning_pb2_grpc.py +0 -0
  41. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/api/semgrep/__init__.py +0 -0
  42. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/api/semgrep/v2/__init__.py +0 -0
  43. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/api/semgrep/v2/scanoss_semgrep_pb2.py +0 -0
  44. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/api/semgrep/v2/scanoss_semgrep_pb2_grpc.py +0 -0
  45. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/api/vulnerabilities/__init__.py +0 -0
  46. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/api/vulnerabilities/v2/__init__.py +0 -0
  47. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2.py +0 -0
  48. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2_grpc.py +0 -0
  49. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/components.py +0 -0
  50. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/csvoutput.py +0 -0
  51. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/cyclonedx.py +0 -0
  52. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/data/scanoss-settings-schema.json +0 -0
  53. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/data/spdx-exceptions.json +0 -0
  54. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/data/spdx-licenses.json +0 -0
  55. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/file_filters.py +0 -0
  56. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/filecount.py +0 -0
  57. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/inspection/__init__.py +0 -0
  58. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/inspection/copyleft.py +0 -0
  59. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/inspection/policy_check.py +0 -0
  60. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/inspection/undeclared_component.py +0 -0
  61. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/inspection/utils/license_utils.py +0 -0
  62. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/results.py +0 -0
  63. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/scancodedeps.py +0 -0
  64. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/scanner.py +0 -0
  65. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/scanoss_settings.py +0 -0
  66. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/scanossapi.py +0 -0
  67. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/scanossbase.py +0 -0
  68. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/scanossgrpc.py +0 -0
  69. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/scanpostprocessor.py +0 -0
  70. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/scantype.py +0 -0
  71. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/spdxlite.py +0 -0
  72. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/threadeddependencies.py +0 -0
  73. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/threadedscanning.py +0 -0
  74. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/utils/__init__.py +0 -0
  75. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/utils/file.py +0 -0
  76. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss/winnowing.py +0 -0
  77. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss.egg-info/SOURCES.txt +0 -0
  78. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss.egg-info/dependency_links.txt +0 -0
  79. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss.egg-info/entry_points.txt +0 -0
  80. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss.egg-info/requires.txt +0 -0
  81. {scanoss-1.20.1 → scanoss-1.20.3}/src/scanoss.egg-info/top_level.txt +0 -0
  82. {scanoss-1.20.1 → scanoss-1.20.3}/tests/test_csv_output.py +0 -0
  83. {scanoss-1.20.1 → scanoss-1.20.3}/tests/test_file_filters.py +0 -0
  84. {scanoss-1.20.1 → scanoss-1.20.3}/tests/test_policy_inspect.py +0 -0
  85. {scanoss-1.20.1 → scanoss-1.20.3}/tests/test_scan_post_processor.py +0 -0
  86. {scanoss-1.20.1 → scanoss-1.20.3}/tests/test_spdxlite.py +0 -0
  87. {scanoss-1.20.1 → scanoss-1.20.3}/tests/test_winnowing.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: scanoss
3
- Version: 1.20.1
3
+ Version: 1.20.3
4
4
  Summary: Simple Python library to leverage the SCANOSS APIs
5
5
  Home-page: https://scanoss.com
6
6
  Author: SCANOSS
@@ -8,7 +8,7 @@ select = ["E", "F", "I", "PL"]
8
8
  line-length = 120
9
9
  # Assume Python 3.7+
10
10
  target-version = "py37"
11
- exclude = ["tests/*", "test_*.py"]
11
+ exclude = ["tests/*", "test_*.py", "src/scanoss/cli.py"]
12
12
 
13
13
  [tool.ruff.format]
14
14
  quote-style = "single"
@@ -22,4 +22,4 @@ SPDX-License-Identifier: MIT
22
22
  THE SOFTWARE.
23
23
  """
24
24
 
25
- __version__ = '1.20.1'
25
+ __version__ = '1.20.3'
@@ -45,6 +45,11 @@ from .spdxlite import SpdxLite
45
45
  from .threadeddependencies import SCOPE
46
46
  from .utils.file import validate_json_file
47
47
 
48
+ DEFAULT_POST_SIZE = 32
49
+ DEFAULT_TIMEOUT = 180
50
+ MIN_TIMEOUT_VALUE = 5
51
+ DEFAULT_RETRY = 5
52
+ PYTHON3_OR_LATER = 3
48
53
 
49
54
  def print_stderr(*args, **kwargs):
50
55
  """
@@ -53,7 +58,7 @@ def print_stderr(*args, **kwargs):
53
58
  print(*args, file=sys.stderr, **kwargs)
54
59
 
55
60
 
56
- def setup_args() -> None:
61
+ def setup_args() -> None: # noqa: PLR0915
57
62
  """
58
63
  Setup all the command line arguments for processing
59
64
  """
@@ -114,24 +119,26 @@ def setup_args() -> None:
114
119
  '--post-size',
115
120
  '-P',
116
121
  type=int,
117
- default=32,
122
+ default=DEFAULT_POST_SIZE,
118
123
  help='Number of kilobytes to limit the post to while scanning (optional - default 32)',
119
124
  )
120
125
  p_scan.add_argument(
121
126
  '--timeout',
122
127
  '-M',
123
128
  type=int,
124
- default=180,
129
+ default=DEFAULT_TIMEOUT,
125
130
  help='Timeout (in seconds) for API communication (optional - default 180)',
126
131
  )
127
132
  p_scan.add_argument(
128
- '--retry', '-R', type=int, default=5, help='Retry limit for API communication (optional - default 5)'
133
+ '--retry', '-R', type=int, default=DEFAULT_RETRY,
134
+ help='Retry limit for API communication (optional - default 5)'
129
135
  )
130
136
  p_scan.add_argument('--no-wfp-output', action='store_true', help='Skip WFP file generation')
131
137
  p_scan.add_argument('--dependencies', '-D', action='store_true', help='Add Dependency scanning')
132
138
  p_scan.add_argument('--dependencies-only', action='store_true', help='Run Dependency scanning only')
133
139
  p_scan.add_argument(
134
- '--sc-command', type=str, help='Scancode command and path if required (optional - default scancode).'
140
+ '--sc-command', type=str,
141
+ help='Scancode command and path if required (optional - default scancode).'
135
142
  )
136
143
  p_scan.add_argument(
137
144
  '--sc-timeout',
@@ -290,7 +297,7 @@ def setup_args() -> None:
290
297
  description=f'Show Provenance findings: {__version__}',
291
298
  help='Retrieve provenance for the given components',
292
299
  )
293
- c_provenance.set_defaults(func=c_provenance)
300
+ c_provenance.set_defaults(func=comp_provenance)
294
301
 
295
302
  # Component Sub-command: component search
296
303
  c_search = comp_sub.add_parser(
@@ -321,7 +328,7 @@ def setup_args() -> None:
321
328
  c_versions.set_defaults(func=comp_versions)
322
329
 
323
330
  # Common purl Component sub-command options
324
- for p in [c_crypto, c_vulns, c_semgrep]:
331
+ for p in [c_crypto, c_vulns, c_semgrep, c_provenance]:
325
332
  p.add_argument('--purl', '-p', type=str, nargs='*', help='Package URL - PURL to process.')
326
333
  p.add_argument('--input', '-i', type=str, help='Input file name')
327
334
  # Common Component sub-command options
@@ -524,7 +531,7 @@ def setup_args() -> None:
524
531
  p.add_argument('--strip-snippet', '-N', type=str, action='append', help='Strip Snippet ID string from WFP.')
525
532
 
526
533
  # Global Scan/GRPC options
527
- for p in [p_scan, c_crypto, c_vulns, c_search, c_versions, c_semgrep]:
534
+ for p in [p_scan, c_crypto, c_vulns, c_search, c_versions, c_semgrep, c_provenance]:
528
535
  p.add_argument(
529
536
  '--key', '-k', type=str, help='SCANOSS API Key token (optional - not required for default OSSKB URL)'
530
537
  )
@@ -550,7 +557,7 @@ def setup_args() -> None:
550
557
  )
551
558
 
552
559
  # Global GRPC options
553
- for p in [p_scan, c_crypto, c_vulns, c_search, c_versions, c_semgrep]:
560
+ for p in [p_scan, c_crypto, c_vulns, c_search, c_versions, c_semgrep, c_provenance]:
554
561
  p.add_argument(
555
562
  '--api2url', type=str, help='SCANOSS gRPC API 2.0 URL (optional - default: https://api.osskb.org)'
556
563
  )
@@ -579,6 +586,7 @@ def setup_args() -> None:
579
586
  p_results,
580
587
  p_undeclared,
581
588
  p_copyleft,
589
+ c_provenance
582
590
  ]:
583
591
  p.add_argument('--debug', '-d', action='store_true', help='Enable debug messages')
584
592
  p.add_argument('--trace', '-t', action='store_true', help='Enable trace messages, including API posts')
@@ -587,21 +595,14 @@ def setup_args() -> None:
587
595
  args = parser.parse_args()
588
596
  if args.version:
589
597
  ver(parser, args)
590
- exit(0)
598
+ sys.exit(0)
591
599
  if not args.subparser:
592
600
  parser.print_help() # No sub command subcommand, print general help
593
- exit(1)
601
+ sys.exit(1)
594
602
  elif (
595
- args.subparser == 'utils'
596
- or args.subparser == 'ut'
597
- or args.subparser == 'component'
598
- or args.subparser == 'comp'
599
- or args.subparser == 'inspect'
600
- or args.subparser == 'insp'
601
- or args.subparser == 'ins'
602
- ) and not args.subparsercmd:
603
+ args.subparser in {'utils', 'ut', 'component', 'comp', 'inspect', 'insp', 'ins'} and not args.subparsercmd):
603
604
  parser.parse_args([args.subparser, '--help']) # Force utils helps to be displayed
604
- exit(1)
605
+ sys.exit(1)
605
606
  args.func(parser, args) # Execute the function associated with the sub-command
606
607
 
607
608
 
@@ -634,7 +635,7 @@ def file_count(parser, args):
634
635
  if not args.scan_dir:
635
636
  print_stderr('Please specify a folder')
636
637
  parser.parse_args([args.subparser, '-h'])
637
- exit(1)
638
+ sys.exit(1)
638
639
  scan_output: str = None
639
640
  if args.output:
640
641
  scan_output = args.output
@@ -649,12 +650,12 @@ def file_count(parser, args):
649
650
  )
650
651
  if not os.path.exists(args.scan_dir):
651
652
  print_stderr(f'Error: Folder specified does not exist: {args.scan_dir}.')
652
- exit(1)
653
+ sys.exit(1)
653
654
  if os.path.isdir(args.scan_dir):
654
655
  counter.count_files(args.scan_dir)
655
656
  else:
656
657
  print_stderr(f'Error: Path specified is not a folder: {args.scan_dir}.')
657
- exit(1)
658
+ sys.exit(1)
658
659
 
659
660
 
660
661
  def wfp(parser, args):
@@ -670,7 +671,7 @@ def wfp(parser, args):
670
671
  if not args.scan_dir and not args.stdin:
671
672
  print_stderr('Please specify a file/folder or STDIN (--stdin)')
672
673
  parser.parse_args([args.subparser, '-h'])
673
- exit(1)
674
+ sys.exit(1)
674
675
  if args.strip_hpsm and not args.hpsm and not args.quiet:
675
676
  print_stderr('Warning: --strip-hpsm option supplied without enabling HPSM (--hpsm). Ignoring.')
676
677
  scan_output: str = None
@@ -686,7 +687,7 @@ def wfp(parser, args):
686
687
  scan_settings.load_json_file(args.settings)
687
688
  except ScanossSettingsError as e:
688
689
  print_stderr(f'Error: {e}')
689
- exit(1)
690
+ sys.exit(1)
690
691
 
691
692
  scan_options = 0 if args.skip_snippets else ScanType.SCAN_SNIPPETS.value # Skip snippet generation or not
692
693
  scanner = Scanner(
@@ -713,17 +714,17 @@ def wfp(parser, args):
713
714
  elif args.scan_dir:
714
715
  if not os.path.exists(args.scan_dir):
715
716
  print_stderr(f'Error: File or folder specified does not exist: {args.scan_dir}.')
716
- exit(1)
717
+ sys.exit(1)
717
718
  if os.path.isdir(args.scan_dir):
718
719
  scanner.wfp_folder(args.scan_dir, scan_output)
719
720
  elif os.path.isfile(args.scan_dir):
720
721
  scanner.wfp_file(args.scan_dir, scan_output)
721
722
  else:
722
723
  print_stderr(f'Error: Path specified is neither a file or a folder: {args.scan_dir}.')
723
- exit(1)
724
+ sys.exit(1)
724
725
  else:
725
726
  print_stderr('No action found to process')
726
- exit(1)
727
+ sys.exit(1)
727
728
 
728
729
 
729
730
  def get_scan_options(args):
@@ -754,11 +755,11 @@ def get_scan_options(args):
754
755
  print_stderr('Scan Dependencies')
755
756
  if scan_options <= 0:
756
757
  print_stderr(f'Error: No valid scan options configured: {scan_options}')
757
- exit(1)
758
+ sys.exit(1)
758
759
  return scan_options
759
760
 
760
761
 
761
- def scan(parser, args):
762
+ def scan(parser, args): # noqa: PLR0912, PLR0915
762
763
  """
763
764
  Run the "scan" sub-command
764
765
  Parameters
@@ -773,17 +774,17 @@ def scan(parser, args):
773
774
  'Please specify a file/folder, files (--files), fingerprint (--wfp), dependency (--dep), or STDIN (--stdin)'
774
775
  )
775
776
  parser.parse_args([args.subparser, '-h'])
776
- exit(1)
777
+ sys.exit(1)
777
778
  if args.pac and args.proxy:
778
779
  print_stderr('Please specify one of --proxy or --pac, not both')
779
780
  parser.parse_args([args.subparser, '-h'])
780
- exit(1)
781
+ sys.exit(1)
781
782
  if args.identify and args.settings:
782
783
  print_stderr('ERROR: Cannot specify both --identify and --settings options.')
783
- exit(1)
784
+ sys.exit(1)
784
785
  if args.settings and args.skip_settings_file:
785
786
  print_stderr('ERROR: Cannot specify both --settings and --skip-file-settings options.')
786
- exit(1)
787
+ sys.exit(1)
787
788
  # Figure out which settings (if any) to load before processing
788
789
  scan_settings = None
789
790
  if not args.skip_settings_file:
@@ -803,15 +804,15 @@ def scan(parser, args):
803
804
  )
804
805
  except ScanossSettingsError as e:
805
806
  print_stderr(f'Error: {e}')
806
- exit(1)
807
+ sys.exit(1)
807
808
  if args.dep:
808
809
  if not os.path.exists(args.dep) or not os.path.isfile(args.dep):
809
810
  print_stderr(f'Specified --dep file does not exist or is not a file: {args.dep}')
810
- exit(1)
811
+ sys.exit(1)
811
812
  result = validate_json_file(args.dep)
812
813
  if not result.is_valid:
813
814
  print_stderr(f'Error: Dependency file is not valid: {result.error}')
814
- exit(1)
815
+ sys.exit(1)
815
816
  if args.strip_hpsm and not args.hpsm and not args.quiet:
816
817
  print_stderr('Warning: --strip-hpsm option supplied without enabling HPSM (--hpsm). Ignoring.')
817
818
 
@@ -832,11 +833,11 @@ def scan(parser, args):
832
833
  print_stderr('Scanning all hidden files/folders...')
833
834
  if args.skip_snippets:
834
835
  print_stderr('Skipping snippets...')
835
- if args.post_size != 32:
836
+ if args.post_size != DEFAULT_POST_SIZE:
836
837
  print_stderr(f'Changing scanning POST size to: {args.post_size}k...')
837
- if args.timeout != 180:
838
+ if args.timeout != DEFAULT_TIMEOUT:
838
839
  print_stderr(f'Changing scanning POST timeout to: {args.timeout}...')
839
- if args.retry != 5:
840
+ if args.retry != DEFAULT_RETRY:
840
841
  print_stderr(f'Changing scanning POST retry to: {args.retry}...')
841
842
  if args.obfuscate:
842
843
  print_stderr('Obfuscating file fingerprints...')
@@ -853,7 +854,7 @@ def scan(parser, args):
853
854
  if flags:
854
855
  print_stderr(f'Using flags {flags}...')
855
856
  elif not args.quiet:
856
- if args.timeout < 5:
857
+ if args.timeout < MIN_TIMEOUT_VALUE:
857
858
  print_stderr(f'POST timeout (--timeout) too small: {args.timeout}. Reverting to default.')
858
859
  if args.retry < 0:
859
860
  print_stderr(f'POST retry (--retry) too small: {args.retry}. Reverting to default.')
@@ -863,7 +864,7 @@ def scan(parser, args):
863
864
  args.no_wfp_output = True
864
865
  if args.ca_cert and not os.path.exists(args.ca_cert):
865
866
  print_stderr(f'Error: Certificate file does not exist: {args.ca_cert}.')
866
- exit(1)
867
+ sys.exit(1)
867
868
  pac_file = get_pac_file(args.pac)
868
869
  scan_options = get_scan_options(args) # Figure out what scanning options we have
869
870
 
@@ -906,22 +907,22 @@ def scan(parser, args):
906
907
  if args.wfp:
907
908
  if not scanner.is_file_or_snippet_scan():
908
909
  print_stderr(f'Error: Cannot specify WFP scanning if file/snippet options are disabled ({scan_options})')
909
- exit(1)
910
+ sys.exit(1)
910
911
  if scanner.is_dependency_scan() and not args.dep:
911
912
  print_stderr('Error: Cannot specify WFP & Dependency scanning without a dependency file (--dep)')
912
- exit(1)
913
+ sys.exit(1)
913
914
  scanner.scan_wfp_with_options(args.wfp, args.dep)
914
915
  elif args.stdin:
915
916
  contents = sys.stdin.buffer.read()
916
917
  if not scanner.scan_contents(args.stdin, contents):
917
- exit(1)
918
+ sys.exit(1)
918
919
  elif args.files:
919
920
  if not scanner.scan_files_with_options(args.files, args.dep, scanner.winnowing.file_map):
920
- exit(1)
921
+ sys.exit(1)
921
922
  elif args.scan_dir:
922
923
  if not os.path.exists(args.scan_dir):
923
924
  print_stderr(f'Error: File or folder specified does not exist: {args.scan_dir}.')
924
- exit(1)
925
+ sys.exit(1)
925
926
  if os.path.isdir(args.scan_dir):
926
927
  if not scanner.scan_folder_with_options(
927
928
  args.scan_dir,
@@ -931,7 +932,7 @@ def scan(parser, args):
931
932
  args.dep_scope_inc,
932
933
  args.dep_scope_exc,
933
934
  ):
934
- exit(1)
935
+ sys.exit(1)
935
936
  elif os.path.isfile(args.scan_dir):
936
937
  if not scanner.scan_file_with_options(
937
938
  args.scan_dir,
@@ -941,23 +942,24 @@ def scan(parser, args):
941
942
  args.dep_scope_inc,
942
943
  args.dep_scope_exc,
943
944
  ):
944
- exit(1)
945
+ sys.exit(1)
945
946
  else:
946
947
  print_stderr(f'Error: Path specified is neither a file or a folder: {args.scan_dir}.')
947
- exit(1)
948
+ sys.exit(1)
948
949
  elif args.dep:
949
950
  if not args.dependencies_only:
950
951
  print_stderr(
951
- 'Error: No file or folder specified to scan. Please add --dependencies-only to decorate dependency file only.'
952
+ 'Error: No file or folder specified to scan.'
953
+ ' Please add --dependencies-only to decorate dependency file only.'
952
954
  )
953
- exit(1)
955
+ sys.exit(1)
954
956
  if not scanner.scan_folder_with_options(
955
957
  '.', args.dep, scanner.winnowing.file_map, args.dep_scope, args.dep_scope_inc, args.dep_scope_exc
956
958
  ):
957
- exit(1)
959
+ sys.exit(1)
958
960
  else:
959
961
  print_stderr('No action found to process')
960
- exit(1)
962
+ sys.exit(1)
961
963
 
962
964
 
963
965
  def dependency(parser, args):
@@ -973,10 +975,10 @@ def dependency(parser, args):
973
975
  if not args.scan_dir:
974
976
  print_stderr('Please specify a file/folder')
975
977
  parser.parse_args([args.subparser, '-h'])
976
- exit(1)
978
+ sys.exit(1)
977
979
  if not os.path.exists(args.scan_dir):
978
980
  print_stderr(f'Error: File or folder specified does not exist: {args.scan_dir}.')
979
- exit(1)
981
+ sys.exit(1)
980
982
  scan_output: str = None
981
983
  if args.output:
982
984
  scan_output = args.output
@@ -986,7 +988,7 @@ def dependency(parser, args):
986
988
  debug=args.debug, quiet=args.quiet, trace=args.trace, sc_command=args.sc_command, timeout=args.sc_timeout
987
989
  )
988
990
  if not sc_deps.get_dependencies(what_to_scan=args.scan_dir, result_output=scan_output):
989
- exit(1)
991
+ sys.exit(1)
990
992
 
991
993
 
992
994
  def convert(parser, args):
@@ -1002,7 +1004,7 @@ def convert(parser, args):
1002
1004
  if not args.input:
1003
1005
  print_stderr('Please specify an input file to convert')
1004
1006
  parser.parse_args([args.subparser, '-h'])
1005
- exit(1)
1007
+ sys.exit(1)
1006
1008
  success = False
1007
1009
  if args.format == 'cyclonedx':
1008
1010
  if not args.quiet:
@@ -1022,7 +1024,7 @@ def convert(parser, args):
1022
1024
  else:
1023
1025
  print_stderr(f'ERROR: Unknown output format (--format): {args.format}')
1024
1026
  if not success:
1025
- exit(1)
1027
+ sys.exit(1)
1026
1028
 
1027
1029
 
1028
1030
  def inspect_copyleft(parser, args):
@@ -1038,7 +1040,7 @@ def inspect_copyleft(parser, args):
1038
1040
  if args.input is None:
1039
1041
  print_stderr('Please specify an input file to inspect')
1040
1042
  parser.parse_args([args.subparser, args.subparsercmd, '-h'])
1041
- exit(1)
1043
+ sys.exit(1)
1042
1044
  output: str = None
1043
1045
  if args.output:
1044
1046
  output = args.output
@@ -1078,7 +1080,7 @@ def inspect_undeclared(parser, args):
1078
1080
  if args.input is None:
1079
1081
  print_stderr('Please specify an input file to inspect')
1080
1082
  parser.parse_args([args.subparser, args.subparsercmd, '-h'])
1081
- exit(1)
1083
+ sys.exit(1)
1082
1084
  output: str = None
1083
1085
  if args.output:
1084
1086
  output = args.output
@@ -1112,7 +1114,7 @@ def utils_certloc(*_):
1112
1114
  print(f'CA Cert File: {certifi.where()}')
1113
1115
 
1114
1116
 
1115
- def utils_cert_download(_, args):
1117
+ def utils_cert_download(_, args): # pylint: disable=PLR0912 # noqa: PLR0912
1116
1118
  """
1117
1119
  Run the "utils cert-download" sub-command
1118
1120
  :param _: ignore/unused
@@ -1139,13 +1141,13 @@ def utils_cert_download(_, args):
1139
1141
  certs = conn.get_peer_cert_chain()
1140
1142
  for index, cert in enumerate(certs):
1141
1143
  cert_components = dict(cert.get_subject().get_components())
1142
- if sys.version_info[0] >= 3:
1144
+ if sys.version_info[0] >= PYTHON3_OR_LATER:
1143
1145
  cn = cert_components.get(b'CN')
1144
1146
  else:
1145
1147
  cn = cert_components.get('CN')
1146
1148
  if not args.quiet:
1147
1149
  print_stderr(f'Certificate {index} - CN: {cn}')
1148
- if sys.version_info[0] >= 3:
1150
+ if sys.version_info[0] >= PYTHON3_OR_LATER:
1149
1151
  print(
1150
1152
  (crypto.dump_certificate(crypto.FILETYPE_PEM, cert).decode('utf-8')).strip(), file=file
1151
1153
  ) # Print the downloaded PEM certificate
@@ -1155,7 +1157,7 @@ def utils_cert_download(_, args):
1155
1157
  print_stderr(f'ERROR: Exception ({e.__class__.__name__}) Downloading certificate from {hostname}:{port} - {e}.')
1156
1158
  if args.debug:
1157
1159
  traceback.print_exc()
1158
- exit(1)
1160
+ sys.exit(1)
1159
1161
  else:
1160
1162
  if args.output:
1161
1163
  if args.debug:
@@ -1173,11 +1175,11 @@ def utils_pac_proxy(_, args):
1173
1175
 
1174
1176
  if not args.pac:
1175
1177
  print_stderr('Error: No pac file option specified.')
1176
- exit(1)
1178
+ sys.exit(1)
1177
1179
  pac_file = get_pac_file(args.pac)
1178
1180
  if pac_file is None:
1179
1181
  print_stderr(f'No proxy configuration for: {args.pac}')
1180
- exit(1)
1182
+ sys.exit(1)
1181
1183
  resolver = ProxyResolver(pac_file)
1182
1184
  proxies = resolver.get_proxy_for_requests(args.url)
1183
1185
  print(f'Proxies: {proxies}\n')
@@ -1197,14 +1199,14 @@ def get_pac_file(pac: str):
1197
1199
  pac_local = pac.strip('file://')
1198
1200
  if not os.path.exists(pac_local):
1199
1201
  print_stderr(f'Error: PAC file does not exist: {pac_local}.')
1200
- exit(1)
1202
+ sys.exit(1)
1201
1203
  with open(pac_local) as pf:
1202
1204
  pac_file = pypac.get_pac(js=pf.read())
1203
1205
  elif pac.startswith('http'):
1204
1206
  pac_file = pypac.get_pac(url=pac)
1205
1207
  else:
1206
1208
  print_stderr(f'Error: Unknown PAC file option: {pac}. Should be one of "auto", "file://", "https://"')
1207
- exit(1)
1209
+ sys.exit(1)
1208
1210
  return pac_file
1209
1211
 
1210
1212
 
@@ -1221,10 +1223,10 @@ def comp_crypto(parser, args):
1221
1223
  if (not args.purl and not args.input) or (args.purl and args.input):
1222
1224
  print_stderr('Please specify an input file or purl to decorate (--purl or --input)')
1223
1225
  parser.parse_args([args.subparser, args.subparsercmd, '-h'])
1224
- exit(1)
1226
+ sys.exit(1)
1225
1227
  if args.ca_cert and not os.path.exists(args.ca_cert):
1226
1228
  print_stderr(f'Error: Certificate file does not exist: {args.ca_cert}.')
1227
- exit(1)
1229
+ sys.exit(1)
1228
1230
  pac_file = get_pac_file(args.pac)
1229
1231
  comps = Components(
1230
1232
  debug=args.debug,
@@ -1239,7 +1241,7 @@ def comp_crypto(parser, args):
1239
1241
  timeout=args.timeout,
1240
1242
  )
1241
1243
  if not comps.get_crypto_details(args.input, args.purl, args.output):
1242
- exit(1)
1244
+ sys.exit(1)
1243
1245
 
1244
1246
 
1245
1247
  def comp_vulns(parser, args):
@@ -1255,10 +1257,10 @@ def comp_vulns(parser, args):
1255
1257
  if (not args.purl and not args.input) or (args.purl and args.input):
1256
1258
  print_stderr('Please specify an input file or purl to decorate (--purl or --input)')
1257
1259
  parser.parse_args([args.subparser, args.subparsercmd, '-h'])
1258
- exit(1)
1260
+ sys.exit(1)
1259
1261
  if args.ca_cert and not os.path.exists(args.ca_cert):
1260
1262
  print_stderr(f'Error: Certificate file does not exist: {args.ca_cert}.')
1261
- exit(1)
1263
+ sys.exit(1)
1262
1264
  pac_file = get_pac_file(args.pac)
1263
1265
  comps = Components(
1264
1266
  debug=args.debug,
@@ -1273,7 +1275,7 @@ def comp_vulns(parser, args):
1273
1275
  timeout=args.timeout,
1274
1276
  )
1275
1277
  if not comps.get_vulnerabilities(args.input, args.purl, args.output):
1276
- exit(1)
1278
+ sys.exit(1)
1277
1279
 
1278
1280
 
1279
1281
  def comp_semgrep(parser, args):
@@ -1289,10 +1291,10 @@ def comp_semgrep(parser, args):
1289
1291
  if (not args.purl and not args.input) or (args.purl and args.input):
1290
1292
  print_stderr('Please specify an input file or purl to decorate (--purl or --input)')
1291
1293
  parser.parse_args([args.subparser, args.subparsercmd, '-h'])
1292
- exit(1)
1294
+ sys.exit(1)
1293
1295
  if args.ca_cert and not os.path.exists(args.ca_cert):
1294
1296
  print_stderr(f'Error: Certificate file does not exist: {args.ca_cert}.')
1295
- exit(1)
1297
+ sys.exit(1)
1296
1298
  pac_file = get_pac_file(args.pac)
1297
1299
  comps = Components(
1298
1300
  debug=args.debug,
@@ -1307,7 +1309,7 @@ def comp_semgrep(parser, args):
1307
1309
  timeout=args.timeout,
1308
1310
  )
1309
1311
  if not comps.get_semgrep_details(args.input, args.purl, args.output):
1310
- exit(1)
1312
+ sys.exit(1)
1311
1313
 
1312
1314
 
1313
1315
  def comp_search(parser, args):
@@ -1325,11 +1327,11 @@ def comp_search(parser, args):
1325
1327
  ):
1326
1328
  print_stderr('Please specify an input file or search terms (--input or --search, or --vendor or --comp.)')
1327
1329
  parser.parse_args([args.subparser, args.subparsercmd, '-h'])
1328
- exit(1)
1330
+ sys.exit(1)
1329
1331
 
1330
1332
  if args.ca_cert and not os.path.exists(args.ca_cert):
1331
1333
  print_stderr(f'Error: Certificate file does not exist: {args.ca_cert}.')
1332
- exit(1)
1334
+ sys.exit(1)
1333
1335
  pac_file = get_pac_file(args.pac)
1334
1336
  comps = Components(
1335
1337
  debug=args.debug,
@@ -1353,7 +1355,7 @@ def comp_search(parser, args):
1353
1355
  limit=args.limit,
1354
1356
  offset=args.offset,
1355
1357
  ):
1356
- exit(1)
1358
+ sys.exit(1)
1357
1359
 
1358
1360
 
1359
1361
  def comp_versions(parser, args):
@@ -1369,11 +1371,11 @@ def comp_versions(parser, args):
1369
1371
  if (not args.input and not args.purl) or (args.input and args.purl):
1370
1372
  print_stderr('Please specify an input file or search terms (--input or --purl.)')
1371
1373
  parser.parse_args([args.subparser, args.subparsercmd, '-h'])
1372
- exit(1)
1374
+ sys.exit(1)
1373
1375
 
1374
1376
  if args.ca_cert and not os.path.exists(args.ca_cert):
1375
1377
  print_stderr(f'Error: Certificate file does not exist: {args.ca_cert}.')
1376
- exit(1)
1378
+ sys.exit(1)
1377
1379
  pac_file = get_pac_file(args.pac)
1378
1380
  comps = Components(
1379
1381
  debug=args.debug,
@@ -1388,8 +1390,31 @@ def comp_versions(parser, args):
1388
1390
  timeout=args.timeout,
1389
1391
  )
1390
1392
  if not comps.get_component_versions(args.output, json_file=args.input, purl=args.purl, limit=args.limit):
1391
- exit(1)
1393
+ sys.exit(1)
1392
1394
 
1395
+ def comp_provenance(parser, args):
1396
+ """
1397
+ Run the "component semgrep" sub-command
1398
+ Parameters
1399
+ ----------
1400
+ parser: ArgumentParser
1401
+ command line parser object
1402
+ args: Namespace
1403
+ Parsed arguments
1404
+ """
1405
+ if (not args.purl and not args.input) or (args.purl and args.input):
1406
+ print_stderr('Please specify an input file or purl to decorate (--purl or --input)')
1407
+ parser.parse_args([args.subparser, args.subparsercmd, '-h'])
1408
+ sys.exit(1)
1409
+ if args.ca_cert and not os.path.exists(args.ca_cert):
1410
+ print_stderr(f'Error: Certificate file does not exist: {args.ca_cert}.')
1411
+ sys.exit(1)
1412
+ pac_file = get_pac_file(args.pac)
1413
+ comps = Components(debug=args.debug, trace=args.trace, quiet=args.quiet, grpc_url=args.api2url, api_key=args.key,
1414
+ ca_cert=args.ca_cert, proxy=args.proxy, grpc_proxy=args.grpc_proxy, pac=pac_file,
1415
+ timeout=args.timeout)
1416
+ if not comps.get_provenance_details(args.input, args.purl, args.output):
1417
+ sys.exit(1)
1393
1418
 
1394
1419
  def results(parser, args):
1395
1420
  """
@@ -1404,13 +1429,13 @@ def results(parser, args):
1404
1429
  if not args.filepath:
1405
1430
  print_stderr('ERROR: Please specify a file containing the results')
1406
1431
  parser.parse_args([args.subparser, '-h'])
1407
- exit(1)
1432
+ sys.exit(1)
1408
1433
 
1409
1434
  file_path = Path(args.filepath).resolve()
1410
1435
 
1411
1436
  if not file_path.is_file():
1412
1437
  print_stderr(f'The specified file {args.filepath} does not exist')
1413
- exit(1)
1438
+ sys.exit(1)
1414
1439
 
1415
1440
  results = Results(
1416
1441
  debug=args.debug,
@@ -1426,7 +1451,7 @@ def results(parser, args):
1426
1451
  if args.has_pending:
1427
1452
  results.get_pending_identifications().present()
1428
1453
  if results.has_results():
1429
- exit(1)
1454
+ sys.exit(1)
1430
1455
  else:
1431
1456
  results.apply_filters().present()
1432
1457
 
@@ -0,0 +1 @@
1
+ date: 20250303125404, utime: 1741006444
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: scanoss
3
- Version: 1.20.1
3
+ Version: 1.20.3
4
4
  Summary: Simple Python library to leverage the SCANOSS APIs
5
5
  Home-page: https://scanoss.com
6
6
  Author: SCANOSS
@@ -1 +0,0 @@
1
- date: 20250219134430, utime: 1739972670
File without changes
File without changes
File without changes
File without changes