scanoss 1.20.0__py3-none-any.whl → 1.20.2__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 (67) 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 +12 -9
  4. protoc_gen_swagger/options/annotations_pb2_grpc.py +1 -1
  5. protoc_gen_swagger/options/openapiv2_pb2.py +98 -96
  6. protoc_gen_swagger/options/openapiv2_pb2_grpc.py +1 -1
  7. scanoss/__init__.py +18 -18
  8. scanoss/api/__init__.py +17 -17
  9. scanoss/api/common/__init__.py +17 -17
  10. scanoss/api/common/v2/__init__.py +17 -17
  11. scanoss/api/common/v2/scanoss_common_pb2.py +18 -18
  12. scanoss/api/common/v2/scanoss_common_pb2_grpc.py +1 -1
  13. scanoss/api/components/__init__.py +17 -17
  14. scanoss/api/components/v2/__init__.py +17 -17
  15. scanoss/api/components/v2/scanoss_components_pb2.py +48 -38
  16. scanoss/api/components/v2/scanoss_components_pb2_grpc.py +142 -96
  17. scanoss/api/cryptography/v2/scanoss_cryptography_pb2.py +22 -16
  18. scanoss/api/cryptography/v2/scanoss_cryptography_pb2_grpc.py +75 -49
  19. scanoss/api/dependencies/__init__.py +17 -17
  20. scanoss/api/dependencies/v2/__init__.py +17 -17
  21. scanoss/api/dependencies/v2/scanoss_dependencies_pb2.py +30 -24
  22. scanoss/api/dependencies/v2/scanoss_dependencies_pb2_grpc.py +75 -49
  23. scanoss/api/scanning/__init__.py +17 -17
  24. scanoss/api/scanning/v2/__init__.py +17 -17
  25. scanoss/api/scanning/v2/scanoss_scanning_pb2.py +10 -8
  26. scanoss/api/scanning/v2/scanoss_scanning_pb2_grpc.py +40 -32
  27. scanoss/api/semgrep/__init__.py +17 -17
  28. scanoss/api/semgrep/v2/__init__.py +17 -17
  29. scanoss/api/semgrep/v2/scanoss_semgrep_pb2.py +22 -18
  30. scanoss/api/semgrep/v2/scanoss_semgrep_pb2_grpc.py +71 -49
  31. scanoss/api/vulnerabilities/__init__.py +17 -17
  32. scanoss/api/vulnerabilities/v2/__init__.py +17 -17
  33. scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2.py +37 -27
  34. scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2_grpc.py +109 -72
  35. scanoss/cli.py +664 -356
  36. scanoss/components.py +67 -45
  37. scanoss/csvoutput.py +83 -56
  38. scanoss/cyclonedx.py +48 -46
  39. scanoss/data/build_date.txt +1 -1
  40. scanoss/file_filters.py +13 -15
  41. scanoss/filecount.py +43 -36
  42. scanoss/inspection/__init__.py +17 -17
  43. scanoss/inspection/copyleft.py +71 -58
  44. scanoss/inspection/policy_check.py +76 -53
  45. scanoss/inspection/undeclared_component.py +98 -75
  46. scanoss/inspection/utils/license_utils.py +66 -44
  47. scanoss/results.py +51 -60
  48. scanoss/scancodedeps.py +61 -38
  49. scanoss/scanner.py +203 -135
  50. scanoss/scanoss_settings.py +5 -3
  51. scanoss/scanossapi.py +98 -69
  52. scanoss/scanossbase.py +19 -19
  53. scanoss/scanossgrpc.py +73 -51
  54. scanoss/scanpostprocessor.py +9 -6
  55. scanoss/scantype.py +22 -21
  56. scanoss/spdxlite.py +265 -171
  57. scanoss/threadeddependencies.py +91 -61
  58. scanoss/threadedscanning.py +37 -31
  59. scanoss/utils/file.py +4 -4
  60. scanoss/winnowing.py +111 -47
  61. {scanoss-1.20.0.dist-info → scanoss-1.20.2.dist-info}/METADATA +1 -1
  62. scanoss-1.20.2.dist-info/RECORD +74 -0
  63. {scanoss-1.20.0.dist-info → scanoss-1.20.2.dist-info}/WHEEL +1 -1
  64. scanoss-1.20.0.dist-info/RECORD +0 -74
  65. {scanoss-1.20.0.dist-info → scanoss-1.20.2.dist-info}/LICENSE +0 -0
  66. {scanoss-1.20.0.dist-info → scanoss-1.20.2.dist-info}/entry_points.txt +0 -0
  67. {scanoss-1.20.0.dist-info → scanoss-1.20.2.dist-info}/top_level.txt +0 -0
scanoss/cli.py CHANGED
@@ -1,49 +1,55 @@
1
1
  """
2
- SPDX-License-Identifier: MIT
3
-
4
- Copyright (c) 2021, SCANOSS
5
-
6
- Permission is hereby granted, free of charge, to any person obtaining a copy
7
- of this software and associated documentation files (the "Software"), to deal
8
- in the Software without restriction, including without limitation the rights
9
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
- copies of the Software, and to permit persons to whom the Software is
11
- furnished to do so, subject to the following conditions:
12
-
13
- The above copyright notice and this permission notice shall be included in
14
- all copies or substantial portions of the Software.
15
-
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
- THE SOFTWARE.
2
+ SPDX-License-Identifier: MIT
3
+
4
+ Copyright (c) 2021, SCANOSS
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in
14
+ all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ THE SOFTWARE.
23
23
  """
24
+
24
25
  import argparse
25
26
  import os
26
- from pathlib import Path
27
27
  import sys
28
+ from pathlib import Path
29
+
28
30
  import pypac
29
31
 
32
+ from . import __version__
33
+ from .components import Components
34
+ from .csvoutput import CsvOutput
35
+ from .cyclonedx import CycloneDx
36
+ from .filecount import FileCount
30
37
  from .inspection.copyleft import Copyleft
31
38
  from .inspection.undeclared_component import UndeclaredComponent
32
- from .threadeddependencies import SCOPE
33
- from .scanoss_settings import ScanossSettings, ScanossSettingsError
39
+ from .results import Results
34
40
  from .scancodedeps import ScancodeDeps
35
- from .scanner import Scanner
41
+ from .scanner import FAST_WINNOWING, Scanner
42
+ from .scanoss_settings import ScanossSettings, ScanossSettingsError
36
43
  from .scantype import ScanType
37
- from .filecount import FileCount
38
- from .cyclonedx import CycloneDx
39
44
  from .spdxlite import SpdxLite
40
- from .csvoutput import CsvOutput
41
- from .components import Components
42
- from . import __version__
43
- from .scanner import FAST_WINNOWING
44
- from .results import Results
45
+ from .threadeddependencies import SCOPE
45
46
  from .utils.file import validate_json_file
46
47
 
48
+ DEFAULT_POST_SIZE = 32
49
+ DEFAULT_TIMEOUT = 180
50
+ MIN_TIMEOUT_VALUE = 5
51
+ DEFAULT_RETRY = 5
52
+ PYTHON3_OR_LATER = 3
47
53
 
48
54
  def print_stderr(*args, **kwargs):
49
55
  """
@@ -52,163 +58,254 @@ def print_stderr(*args, **kwargs):
52
58
  print(*args, file=sys.stderr, **kwargs)
53
59
 
54
60
 
55
- def setup_args() -> None:
61
+ def setup_args() -> None: # noqa: PLR0915
56
62
  """
57
63
  Setup all the command line arguments for processing
58
64
  """
59
- parser = argparse.ArgumentParser(description=f'SCANOSS Python CLI. Ver: {__version__}, License: MIT, Fast Winnowing: {FAST_WINNOWING}')
65
+ parser = argparse.ArgumentParser(
66
+ description=f'SCANOSS Python CLI. Ver: {__version__}, License: MIT, Fast Winnowing: {FAST_WINNOWING}'
67
+ )
60
68
  parser.add_argument('--version', '-v', action='store_true', help='Display version details')
61
69
 
62
- subparsers = parser.add_subparsers(title='Sub Commands', dest='subparser', description='valid subcommands',
63
- help='sub-command help')
70
+ subparsers = parser.add_subparsers(
71
+ title='Sub Commands', dest='subparser', description='valid subcommands', help='sub-command help'
72
+ )
64
73
  # Sub-command: version
65
- p_ver = subparsers.add_parser('version', aliases=['ver'],
66
- description=f'Version of SCANOSS CLI: {__version__}', help='SCANOSS version')
74
+ p_ver = subparsers.add_parser(
75
+ 'version', aliases=['ver'], description=f'Version of SCANOSS CLI: {__version__}', help='SCANOSS version'
76
+ )
67
77
  p_ver.set_defaults(func=ver)
68
78
 
69
79
  # Sub-command: scan
70
- p_scan = subparsers.add_parser('scan', aliases=['sc'],
71
- description=f'Analyse/scan the given source base: {__version__}',
72
- help='Scan source code')
80
+ p_scan = subparsers.add_parser(
81
+ 'scan',
82
+ aliases=['sc'],
83
+ description=f'Analyse/scan the given source base: {__version__}',
84
+ help='Scan source code',
85
+ )
73
86
  p_scan.set_defaults(func=scan)
74
87
  p_scan.add_argument('scan_dir', metavar='FILE/DIR', type=str, nargs='?', help='A file or folder to scan')
75
- p_scan.add_argument('--wfp', '-w', type=str,
76
- help='Scan a WFP File instead of a folder (optional)')
77
- p_scan.add_argument('--dep', '-p', type=str,
78
- help='Use a dependency file instead of a folder (optional)')
79
- p_scan.add_argument('--stdin', '-s', metavar='STDIN-FILENAME', type=str,
80
- help='Scan the file contents supplied via STDIN (optional)')
81
- p_scan.add_argument('--files', '-e', type=str, nargs="*", help='List of files to scan.')
88
+ p_scan.add_argument('--wfp', '-w', type=str, help='Scan a WFP File instead of a folder (optional)')
89
+ p_scan.add_argument('--dep', '-p', type=str, help='Use a dependency file instead of a folder (optional)')
90
+ p_scan.add_argument(
91
+ '--stdin', '-s', metavar='STDIN-FILENAME', type=str, help='Scan the file contents supplied via STDIN (optional)'
92
+ )
93
+ p_scan.add_argument('--files', '-e', type=str, nargs='*', help='List of files to scan.')
82
94
  p_scan.add_argument('--identify', '-i', type=str, help='Scan and identify components in SBOM file')
83
- p_scan.add_argument('--ignore', '-n', type=str, help='Ignore components specified in the SBOM file')
84
- p_scan.add_argument('--output', '-o', type=str, help='Output result file name (optional - default stdout).')
85
- p_scan.add_argument('--format', '-f', type=str, choices=['plain', 'cyclonedx', 'spdxlite', 'csv'],
86
- help='Result output format (optional - default: plain)')
87
- p_scan.add_argument('--threads', '-T', type=int, default=5,
88
- help='Number of threads to use while scanning (optional - default 5)')
89
- p_scan.add_argument('--flags', '-F', type=int,
90
- help='Scanning engine flags (1: disable snippet matching, 2 enable snippet ids, '
91
- '4: disable dependencies, 8: disable licenses, 16: disable copyrights,'
92
- '32: disable vulnerabilities, 64: disable quality, 128: disable cryptography,'
93
- '256: disable best match only, 512: hide identified files, '
94
- '1024: enable download_url, 2048: enable GitHub full path, '
95
- '4096: disable extended server stats)')
96
- p_scan.add_argument('--post-size', '-P', type=int, default=32,
97
- help='Number of kilobytes to limit the post to while scanning (optional - default 32)')
98
- p_scan.add_argument('--timeout', '-M', type=int, default=180,
99
- help='Timeout (in seconds) for API communication (optional - default 180)')
100
- p_scan.add_argument('--retry', '-R', type=int, default=5,
101
- help='Retry limit for API communication (optional - default 5)')
95
+ p_scan.add_argument('--ignore', '-n', type=str, help='Ignore components specified in the SBOM file')
96
+ p_scan.add_argument('--output', '-o', type=str, help='Output result file name (optional - default stdout).')
97
+ p_scan.add_argument(
98
+ '--format',
99
+ '-f',
100
+ type=str,
101
+ choices=['plain', 'cyclonedx', 'spdxlite', 'csv'],
102
+ help='Result output format (optional - default: plain)',
103
+ )
104
+ p_scan.add_argument(
105
+ '--threads', '-T', type=int, default=5, help='Number of threads to use while scanning (optional - default 5)'
106
+ )
107
+ p_scan.add_argument(
108
+ '--flags',
109
+ '-F',
110
+ type=int,
111
+ help='Scanning engine flags (1: disable snippet matching, 2 enable snippet ids, '
112
+ '4: disable dependencies, 8: disable licenses, 16: disable copyrights,'
113
+ '32: disable vulnerabilities, 64: disable quality, 128: disable cryptography,'
114
+ '256: disable best match only, 512: hide identified files, '
115
+ '1024: enable download_url, 2048: enable GitHub full path, '
116
+ '4096: disable extended server stats)',
117
+ )
118
+ p_scan.add_argument(
119
+ '--post-size',
120
+ '-P',
121
+ type=int,
122
+ default=DEFAULT_POST_SIZE,
123
+ help='Number of kilobytes to limit the post to while scanning (optional - default 32)',
124
+ )
125
+ p_scan.add_argument(
126
+ '--timeout',
127
+ '-M',
128
+ type=int,
129
+ default=DEFAULT_TIMEOUT,
130
+ help='Timeout (in seconds) for API communication (optional - default 180)',
131
+ )
132
+ p_scan.add_argument(
133
+ '--retry', '-R', type=int, default=DEFAULT_RETRY,
134
+ help='Retry limit for API communication (optional - default 5)'
135
+ )
102
136
  p_scan.add_argument('--no-wfp-output', action='store_true', help='Skip WFP file generation')
103
137
  p_scan.add_argument('--dependencies', '-D', action='store_true', help='Add Dependency scanning')
104
138
  p_scan.add_argument('--dependencies-only', action='store_true', help='Run Dependency scanning only')
105
- p_scan.add_argument('--sc-command', type=str,
106
- help='Scancode command and path if required (optional - default scancode).')
107
- p_scan.add_argument('--sc-timeout', type=int, default=600,
108
- help='Timeout (in seconds) for scancode to complete (optional - default 600)')
109
- p_scan.add_argument('--dep-scope', '-ds', type=SCOPE, help='Filter dependencies by scope - default all (options: dev/prod)')
110
- p_scan.add_argument('--dep-scope-inc', '-dsi', type=str,help='Include dependencies with declared scopes')
139
+ p_scan.add_argument(
140
+ '--sc-command', type=str,
141
+ help='Scancode command and path if required (optional - default scancode).'
142
+ )
143
+ p_scan.add_argument(
144
+ '--sc-timeout',
145
+ type=int,
146
+ default=600,
147
+ help='Timeout (in seconds) for scancode to complete (optional - default 600)',
148
+ )
149
+ p_scan.add_argument(
150
+ '--dep-scope', '-ds', type=SCOPE, help='Filter dependencies by scope - default all (options: dev/prod)'
151
+ )
152
+ p_scan.add_argument('--dep-scope-inc', '-dsi', type=str, help='Include dependencies with declared scopes')
111
153
  p_scan.add_argument('--dep-scope-exc', '-dse', type=str, help='Exclude dependencies with declared scopes')
112
154
  p_scan.add_argument(
113
- '--settings', '-st',
155
+ '--settings',
156
+ '-st',
114
157
  type=str,
115
158
  help='Settings file to use for scanning (optional - default scanoss.json)',
116
159
  )
117
160
  p_scan.add_argument(
118
- '--skip-settings-file', '-stf', action='store_true',
161
+ '--skip-settings-file',
162
+ '-stf',
163
+ action='store_true',
119
164
  help='Skip default settings file (scanoss.json) if it exists',
120
165
  )
121
166
 
122
167
  # Sub-command: fingerprint
123
- p_wfp = subparsers.add_parser('fingerprint', aliases=['fp', 'wfp'],
124
- description=f'Fingerprint the given source base: {__version__}',
125
- help='Fingerprint source code')
168
+ p_wfp = subparsers.add_parser(
169
+ 'fingerprint',
170
+ aliases=['fp', 'wfp'],
171
+ description=f'Fingerprint the given source base: {__version__}',
172
+ help='Fingerprint source code',
173
+ )
126
174
  p_wfp.set_defaults(func=wfp)
127
- p_wfp.add_argument('scan_dir', metavar='FILE/DIR', type=str, nargs='?',
128
- help='A file or folder to scan')
129
- p_wfp.add_argument('--stdin', '-s', metavar='STDIN-FILENAME', type=str,
130
- help='Fingerprint the file contents supplied via STDIN (optional)')
175
+ p_wfp.add_argument('scan_dir', metavar='FILE/DIR', type=str, nargs='?', help='A file or folder to scan')
176
+ p_wfp.add_argument(
177
+ '--stdin',
178
+ '-s',
179
+ metavar='STDIN-FILENAME',
180
+ type=str,
181
+ help='Fingerprint the file contents supplied via STDIN (optional)',
182
+ )
131
183
  p_wfp.add_argument('--output', '-o', type=str, help='Output result file name (optional - default stdout).')
132
184
  p_wfp.add_argument(
133
- '--settings', '-st',
185
+ '--settings',
186
+ '-st',
134
187
  type=str,
135
188
  help='Settings file to use for fingerprinting (optional - default scanoss.json)',
136
189
  )
137
190
  p_wfp.add_argument(
138
- '--skip-settings-file', '-stf', action='store_true',
191
+ '--skip-settings-file',
192
+ '-stf',
193
+ action='store_true',
139
194
  help='Skip default settings file (scanoss.json) if it exists',
140
195
  )
141
196
 
142
197
  # Sub-command: dependency
143
- p_dep = subparsers.add_parser('dependencies', aliases=['dp', 'dep'],
144
- description=f'Produce dependency file summary: {__version__}',
145
- help='Scan source code for dependencies, but do not decorate them')
198
+ p_dep = subparsers.add_parser(
199
+ 'dependencies',
200
+ aliases=['dp', 'dep'],
201
+ description=f'Produce dependency file summary: {__version__}',
202
+ help='Scan source code for dependencies, but do not decorate them',
203
+ )
146
204
  p_dep.set_defaults(func=dependency)
147
205
  p_dep.add_argument('scan_dir', metavar='FILE/DIR', type=str, nargs='?', help='A file or folder to scan')
148
206
  p_dep.add_argument('--output', '-o', type=str, help='Output result file name (optional - default stdout).')
149
- p_dep.add_argument('--sc-command', type=str,
150
- help='Scancode command and path if required (optional - default scancode).')
151
- p_dep.add_argument('--sc-timeout', type=int, default=600,
152
- help='Timeout (in seconds) for scancode to complete (optional - default 600)')
207
+ p_dep.add_argument(
208
+ '--sc-command', type=str, help='Scancode command and path if required (optional - default scancode).'
209
+ )
210
+ p_dep.add_argument(
211
+ '--sc-timeout',
212
+ type=int,
213
+ default=600,
214
+ help='Timeout (in seconds) for scancode to complete (optional - default 600)',
215
+ )
153
216
 
154
217
  # Sub-command: file_count
155
- p_fc = subparsers.add_parser('file_count', aliases=['fc'],
156
- description=f'Produce a file type count summary: {__version__}',
157
- help='Search the source tree and produce a file type summary')
218
+ p_fc = subparsers.add_parser(
219
+ 'file_count',
220
+ aliases=['fc'],
221
+ description=f'Produce a file type count summary: {__version__}',
222
+ help='Search the source tree and produce a file type summary',
223
+ )
158
224
  p_fc.set_defaults(func=file_count)
159
225
  p_fc.add_argument('scan_dir', metavar='DIR', type=str, nargs='?', help='A folder to search')
160
226
  p_fc.add_argument('--output', '-o', type=str, help='Output result file name (optional - default stdout).')
161
227
  p_fc.add_argument('--all-hidden', action='store_true', help='Scan all hidden files/folders')
162
228
 
163
229
  # Sub-command: convert
164
- p_cnv = subparsers.add_parser('convert', aliases=['cv', 'cnv', 'cvrt'],
165
- description=f'Convert results files between formats: {__version__}',
166
- help='Convert file format')
230
+ p_cnv = subparsers.add_parser(
231
+ 'convert',
232
+ aliases=['cv', 'cnv', 'cvrt'],
233
+ description=f'Convert results files between formats: {__version__}',
234
+ help='Convert file format',
235
+ )
167
236
  p_cnv.set_defaults(func=convert)
168
237
  p_cnv.add_argument('--input', '-i', type=str, required=True, help='Input file name')
169
238
  p_cnv.add_argument('--output', '-o', type=str, help='Output result file name (optional - default stdout).')
170
- p_cnv.add_argument('--format', '-f', type=str, choices=['cyclonedx', 'spdxlite', 'csv'], default='spdxlite',
171
- help='Output format (optional - default: spdxlite)')
172
- p_cnv.add_argument('--input-format', type=str, choices=['plain'], default='plain',
173
- help='Input format (optional - default: plain)')
239
+ p_cnv.add_argument(
240
+ '--format',
241
+ '-f',
242
+ type=str,
243
+ choices=['cyclonedx', 'spdxlite', 'csv'],
244
+ default='spdxlite',
245
+ help='Output format (optional - default: spdxlite)',
246
+ )
247
+ p_cnv.add_argument(
248
+ '--input-format', type=str, choices=['plain'], default='plain', help='Input format (optional - default: plain)'
249
+ )
174
250
 
175
251
  # Sub-command: component
176
- p_comp = subparsers.add_parser('component', aliases=['comp'],
177
- description=f'SCANOSS Component commands: {__version__}',
178
- help='Component support commands')
252
+ p_comp = subparsers.add_parser(
253
+ 'component',
254
+ aliases=['comp'],
255
+ description=f'SCANOSS Component commands: {__version__}',
256
+ help='Component support commands',
257
+ )
179
258
 
180
- comp_sub = p_comp.add_subparsers(title='Component Commands', dest='subparsercmd', description='component sub-commands',
181
- help='component sub-commands')
259
+ comp_sub = p_comp.add_subparsers(
260
+ title='Component Commands',
261
+ dest='subparsercmd',
262
+ description='component sub-commands',
263
+ help='component sub-commands',
264
+ )
182
265
 
183
266
  # Component Sub-command: component crypto
184
- c_crypto = comp_sub.add_parser('crypto', aliases=['cr'],
185
- description=f'Show Cryptographic algorithms: {__version__}',
186
- help='Retrieve cryptographic algorithms for the given components')
267
+ c_crypto = comp_sub.add_parser(
268
+ 'crypto',
269
+ aliases=['cr'],
270
+ description=f'Show Cryptographic algorithms: {__version__}',
271
+ help='Retrieve cryptographic algorithms for the given components',
272
+ )
187
273
  c_crypto.set_defaults(func=comp_crypto)
188
274
 
189
275
  # Component Sub-command: component vulns
190
- c_vulns = comp_sub.add_parser('vulns', aliases=['vulnerabilities', 'vu'],
191
- description=f'Show Vulnerability details: {__version__}',
192
- help='Retrieve vulnerabilities for the given components')
276
+ c_vulns = comp_sub.add_parser(
277
+ 'vulns',
278
+ aliases=['vulnerabilities', 'vu'],
279
+ description=f'Show Vulnerability details: {__version__}',
280
+ help='Retrieve vulnerabilities for the given components',
281
+ )
193
282
  c_vulns.set_defaults(func=comp_vulns)
194
283
 
195
284
  # Component Sub-command: component semgrep
196
- c_semgrep = comp_sub.add_parser('semgrep', aliases=['sp'],
197
- description=f'Show Semgrep findings: {__version__}',
198
- help='Retrieve semgrep issues/findings for the given components')
285
+ c_semgrep = comp_sub.add_parser(
286
+ 'semgrep',
287
+ aliases=['sp'],
288
+ description=f'Show Semgrep findings: {__version__}',
289
+ help='Retrieve semgrep issues/findings for the given components',
290
+ )
199
291
  c_semgrep.set_defaults(func=comp_semgrep)
200
292
 
201
293
  # Component Sub-command: component provenance
202
- c_provenance = comp_sub.add_parser('provenance', aliases=['prov', 'prv'],
203
- description=f'Show Provenance findings: {__version__}',
204
- help='Retrieve provenance for the given components')
294
+ c_provenance = comp_sub.add_parser(
295
+ 'provenance',
296
+ aliases=['prov', 'prv'],
297
+ description=f'Show Provenance findings: {__version__}',
298
+ help='Retrieve provenance for the given components',
299
+ )
205
300
  c_provenance.set_defaults(func=comp_provenance)
206
301
 
207
-
208
302
  # Component Sub-command: component search
209
- c_search = comp_sub.add_parser('search', aliases=['sc'],
210
- description=f'Search component details: {__version__}',
211
- help='Search for a KB component')
303
+ c_search = comp_sub.add_parser(
304
+ 'search',
305
+ aliases=['sc'],
306
+ description=f'Search component details: {__version__}',
307
+ help='Search for a KB component',
308
+ )
212
309
  c_search.add_argument('--input', '-i', type=str, help='Input file name')
213
310
  c_search.add_argument('--search', '-s', type=str, help='Generic component search')
214
311
  c_search.add_argument('--vendor', '-v', type=str, help='Generic component search')
@@ -219,9 +316,12 @@ def setup_args() -> None:
219
316
  c_search.set_defaults(func=comp_search)
220
317
 
221
318
  # Component Sub-command: component versions
222
- c_versions = comp_sub.add_parser('versions', aliases=['vs'],
223
- description=f'Get component version details: {__version__}',
224
- help='Search for component versions')
319
+ c_versions = comp_sub.add_parser(
320
+ 'versions',
321
+ aliases=['vs'],
322
+ description=f'Get component version details: {__version__}',
323
+ help='Search for component versions',
324
+ )
225
325
  c_versions.add_argument('--input', '-i', type=str, help='Input file name')
226
326
  c_versions.add_argument('--purl', '-p', type=str, help='Generic component search')
227
327
  c_versions.add_argument('--limit', '-l', type=int, help='Generic component search')
@@ -229,58 +329,87 @@ def setup_args() -> None:
229
329
 
230
330
  # Common purl Component sub-command options
231
331
  for p in [c_crypto, c_vulns, c_semgrep, c_provenance]:
232
- p.add_argument('--purl', '-p', type=str, nargs="*", help='Package URL - PURL to process.')
332
+ p.add_argument('--purl', '-p', type=str, nargs='*', help='Package URL - PURL to process.')
233
333
  p.add_argument('--input', '-i', type=str, help='Input file name')
234
334
  # Common Component sub-command options
235
335
  for p in [c_crypto, c_vulns, c_search, c_versions, c_semgrep, c_provenance]:
236
336
  p.add_argument('--output', '-o', type=str, help='Output result file name (optional - default stdout).')
237
- p.add_argument('--timeout', '-M', type=int, default=600,
238
- help='Timeout (in seconds) for API communication (optional - default 600)')
337
+ p.add_argument(
338
+ '--timeout',
339
+ '-M',
340
+ type=int,
341
+ default=600,
342
+ help='Timeout (in seconds) for API communication (optional - default 600)',
343
+ )
239
344
 
240
345
  # Sub-command: utils
241
- p_util = subparsers.add_parser('utils', aliases=['ut'],
242
- description=f'SCANOSS Utility commands: {__version__}',
243
- help='General utility support commands')
346
+ p_util = subparsers.add_parser(
347
+ 'utils',
348
+ aliases=['ut'],
349
+ description=f'SCANOSS Utility commands: {__version__}',
350
+ help='General utility support commands',
351
+ )
244
352
 
245
- utils_sub = p_util.add_subparsers(title='Utils Commands', dest='subparsercmd', description='utils sub-commands',
246
- help='utils sub-commands')
353
+ utils_sub = p_util.add_subparsers(
354
+ title='Utils Commands', dest='subparsercmd', description='utils sub-commands', help='utils sub-commands'
355
+ )
247
356
 
248
357
  # Utils Sub-command: utils fast
249
- p_f_f = utils_sub.add_parser('fast',
250
- description=f'Is fast winnowing enabled: {__version__}', help='SCANOSS fast winnowing')
358
+ p_f_f = utils_sub.add_parser(
359
+ 'fast', description=f'Is fast winnowing enabled: {__version__}', help='SCANOSS fast winnowing'
360
+ )
251
361
  p_f_f.set_defaults(func=fast)
252
362
 
253
363
  # Utils Sub-command: utils certloc
254
- p_c_loc = utils_sub.add_parser('certloc', aliases=['cl'],
255
- description=f'Show location of Python CA Certs: {__version__}',
256
- help='Display the location of Python CA Certs')
364
+ p_c_loc = utils_sub.add_parser(
365
+ 'certloc',
366
+ aliases=['cl'],
367
+ description=f'Show location of Python CA Certs: {__version__}',
368
+ help='Display the location of Python CA Certs',
369
+ )
257
370
  p_c_loc.set_defaults(func=utils_certloc)
258
371
 
259
372
  # Utils Sub-command: utils cert-download
260
- p_c_dwnld = utils_sub.add_parser('cert-download', aliases=['cdl', 'cert-dl'],
261
- description=f'Download Server SSL Cert: {__version__}',
262
- help='Download the specified server\'s SSL PEM certificate')
373
+ p_c_dwnld = utils_sub.add_parser(
374
+ 'cert-download',
375
+ aliases=['cdl', 'cert-dl'],
376
+ description=f'Download Server SSL Cert: {__version__}',
377
+ help="Download the specified server's SSL PEM certificate",
378
+ )
263
379
  p_c_dwnld.set_defaults(func=utils_cert_download)
264
380
  p_c_dwnld.add_argument('--hostname', '-n', required=True, type=str, help='Server hostname to download cert from.')
265
- p_c_dwnld.add_argument('--port', '-p', required=False, type=int, default=443,
266
- help='Server port number (default: 443).')
381
+ p_c_dwnld.add_argument(
382
+ '--port', '-p', required=False, type=int, default=443, help='Server port number (default: 443).'
383
+ )
267
384
  p_c_dwnld.add_argument('--output', '-o', type=str, help='Output result file name (optional - default stdout).')
268
385
 
269
386
  # Utils Sub-command: utils pac-proxy
270
- p_p_proxy = utils_sub.add_parser('pac-proxy', aliases=['pac'],
271
- description=f'Determine Proxy from PAC: {__version__}',
272
- help='Use Proxy Auto-Config to determine proxy configuration')
387
+ p_p_proxy = utils_sub.add_parser(
388
+ 'pac-proxy',
389
+ aliases=['pac'],
390
+ description=f'Determine Proxy from PAC: {__version__}',
391
+ help='Use Proxy Auto-Config to determine proxy configuration',
392
+ )
273
393
  p_p_proxy.set_defaults(func=utils_pac_proxy)
274
- p_p_proxy.add_argument('--pac', required=False, type=str, default="auto",
275
- help='Proxy auto configuration. Specify a file, http url or "auto" to try to discover it.'
276
- )
277
- p_p_proxy.add_argument('--url', required=False, type=str, default="https://api.osskb.org",
278
- help='URL to test (default: https://api.osskb.org).')
394
+ p_p_proxy.add_argument(
395
+ '--pac',
396
+ required=False,
397
+ type=str,
398
+ default='auto',
399
+ help='Proxy auto configuration. Specify a file, http url or "auto" to try to discover it.',
400
+ )
401
+ p_p_proxy.add_argument(
402
+ '--url',
403
+ required=False,
404
+ type=str,
405
+ default='https://api.osskb.org',
406
+ help='URL to test (default: https://api.osskb.org).',
407
+ )
279
408
 
280
409
  p_results = subparsers.add_parser(
281
410
  'results',
282
411
  aliases=['res'],
283
- description=f"SCANOSS Results commands: {__version__}",
412
+ description=f'SCANOSS Results commands: {__version__}',
284
413
  help='Process scan results',
285
414
  )
286
415
  p_results.add_argument(
@@ -318,37 +447,66 @@ def setup_args() -> None:
318
447
  )
319
448
  p_results.set_defaults(func=results)
320
449
 
321
-
322
450
  # Sub-command: inspect
323
- p_inspect = subparsers.add_parser('inspect', aliases=['insp', 'ins'],
324
- description=f'Inspect results: {__version__}',
325
- help='Inspect results')
451
+ p_inspect = subparsers.add_parser(
452
+ 'inspect', aliases=['insp', 'ins'], description=f'Inspect results: {__version__}', help='Inspect results'
453
+ )
326
454
  # Sub-parser: inspect
327
- p_inspect_sub = p_inspect.add_subparsers(title='Inspect Commands', dest='subparsercmd',
328
- description='Inspect sub-commands', help='Inspect sub-commands')
455
+ p_inspect_sub = p_inspect.add_subparsers(
456
+ title='Inspect Commands', dest='subparsercmd', description='Inspect sub-commands', help='Inspect sub-commands'
457
+ )
329
458
  # Inspect Sub-command: inspect copyleft
330
- p_copyleft = p_inspect_sub.add_parser('copyleft', aliases=['cp'],description="Inspect for copyleft licenses", help='Inspect for copyleft licenses')
331
- p_copyleft.add_argument('--include', help='List of Copyleft licenses to append to the default list. Provide licenses as a comma-separated list.')
332
- p_copyleft.add_argument('--exclude', help='List of Copyleft licenses to remove from default list. Provide licenses as a comma-separated list.')
333
- p_copyleft.add_argument('--explicit', help='Explicit list of Copyleft licenses to consider. Provide licenses as a comma-separated list.s')
459
+ p_copyleft = p_inspect_sub.add_parser(
460
+ 'copyleft', aliases=['cp'], description='Inspect for copyleft licenses', help='Inspect for copyleft licenses'
461
+ )
462
+ p_copyleft.add_argument(
463
+ '--include',
464
+ help='List of Copyleft licenses to append to the default list. Provide licenses as a comma-separated list.',
465
+ )
466
+ p_copyleft.add_argument(
467
+ '--exclude',
468
+ help='List of Copyleft licenses to remove from default list. Provide licenses as a comma-separated list.',
469
+ )
470
+ p_copyleft.add_argument(
471
+ '--explicit',
472
+ help='Explicit list of Copyleft licenses to consider. Provide licenses as a comma-separated list.s',
473
+ )
334
474
  p_copyleft.set_defaults(func=inspect_copyleft)
335
475
 
336
476
  # Inspect Sub-command: inspect undeclared
337
- p_undeclared = p_inspect_sub.add_parser('undeclared', aliases=['un'],description="Inspect for undeclared components", help='Inspect for undeclared components')
338
- p_undeclared.add_argument('--sbom-format',required=False ,choices=['legacy', 'settings'],
339
- default="settings",help='Sbom format for status output')
477
+ p_undeclared = p_inspect_sub.add_parser(
478
+ 'undeclared',
479
+ aliases=['un'],
480
+ description='Inspect for undeclared components',
481
+ help='Inspect for undeclared components',
482
+ )
483
+ p_undeclared.add_argument(
484
+ '--sbom-format',
485
+ required=False,
486
+ choices=['legacy', 'settings'],
487
+ default='settings',
488
+ help='Sbom format for status output',
489
+ )
340
490
  p_undeclared.set_defaults(func=inspect_undeclared)
341
491
 
342
492
  for p in [p_copyleft, p_undeclared]:
343
493
  p.add_argument('-i', '--input', nargs='?', help='Path to results file')
344
- p.add_argument('-f', '--format',required=False ,choices=['json', 'md', 'jira_md'], default='json', help='Output format (default: json)')
494
+ p.add_argument(
495
+ '-f',
496
+ '--format',
497
+ required=False,
498
+ choices=['json', 'md', 'jira_md'],
499
+ default='json',
500
+ help='Output format (default: json)',
501
+ )
345
502
  p.add_argument('-o', '--output', type=str, help='Save details into a file')
346
503
  p.add_argument('-s', '--status', type=str, help='Save summary data into Markdown file')
347
504
 
348
505
  # Global Scan command options
349
506
  for p in [p_scan]:
350
- p.add_argument('--apiurl', type=str,
351
- help='SCANOSS API URL (optional - default: https://api.osskb.org/scan/direct)')
507
+ p.add_argument(
508
+ '--apiurl', type=str, help='SCANOSS API URL (optional - default: https://api.osskb.org/scan/direct)'
509
+ )
352
510
  p.add_argument('--ignore-cert-errors', action='store_true', help='Ignore certificate errors')
353
511
 
354
512
  # Global Scan/Fingerprint filter options
@@ -361,36 +519,75 @@ def setup_args() -> None:
361
519
  p.add_argument('--skip-snippets', '-S', action='store_true', help='Skip the generation of snippets')
362
520
  p.add_argument('--skip-extension', '-E', type=str, action='append', help='File Extension to skip.')
363
521
  p.add_argument('--skip-folder', '-O', type=str, action='append', help='Folder to skip.')
364
- p.add_argument('--skip-size', '-Z', type=int, default=0,
365
- help='Minimum file size to consider for fingerprinting (optional - default 0 bytes [unlimited])')
522
+ p.add_argument(
523
+ '--skip-size',
524
+ '-Z',
525
+ type=int,
526
+ default=0,
527
+ help='Minimum file size to consider for fingerprinting (optional - default 0 bytes [unlimited])',
528
+ )
366
529
  p.add_argument('--skip-md5', '-5', type=str, action='append', help='Skip files matching MD5.')
367
530
  p.add_argument('--strip-hpsm', '-G', type=str, action='append', help='Strip HPSM string from WFP.')
368
531
  p.add_argument('--strip-snippet', '-N', type=str, action='append', help='Strip Snippet ID string from WFP.')
369
532
 
370
533
  # Global Scan/GRPC options
371
534
  for p in [p_scan, c_crypto, c_vulns, c_search, c_versions, c_semgrep, c_provenance]:
372
- p.add_argument('--key', '-k', type=str,
373
- help='SCANOSS API Key token (optional - not required for default OSSKB URL)')
374
- p.add_argument('--proxy', type=str, help='Proxy URL to use for connections (optional). '
375
- 'Can also use the environment variable "HTTPS_PROXY=<ip>:<port>" '
376
- 'and "grcp_proxy=<ip>:<port>" for gRPC')
377
- p.add_argument('--pac', type=str, help='Proxy auto configuration (optional). '
378
- 'Specify a file, http url or "auto" to try to discover it.')
379
- p.add_argument('--ca-cert', type=str, help='Alternative certificate PEM file (optional). '
380
- 'Can also use the environment variable '
381
- '"REQUESTS_CA_BUNDLE=/path/to/cacert.pem" and '
382
- '"GRPC_DEFAULT_SSL_ROOTS_FILE_PATH=/path/to/cacert.pem" for gRPC')
535
+ p.add_argument(
536
+ '--key', '-k', type=str, help='SCANOSS API Key token (optional - not required for default OSSKB URL)'
537
+ )
538
+ p.add_argument(
539
+ '--proxy',
540
+ type=str,
541
+ help='Proxy URL to use for connections (optional). '
542
+ 'Can also use the environment variable "HTTPS_PROXY=<ip>:<port>" '
543
+ 'and "grcp_proxy=<ip>:<port>" for gRPC',
544
+ )
545
+ p.add_argument(
546
+ '--pac',
547
+ type=str,
548
+ help='Proxy auto configuration (optional). Specify a file, http url or "auto" to try to discover it.',
549
+ )
550
+ p.add_argument(
551
+ '--ca-cert',
552
+ type=str,
553
+ help='Alternative certificate PEM file (optional). '
554
+ 'Can also use the environment variable '
555
+ '"REQUESTS_CA_BUNDLE=/path/to/cacert.pem" and '
556
+ '"GRPC_DEFAULT_SSL_ROOTS_FILE_PATH=/path/to/cacert.pem" for gRPC',
557
+ )
383
558
 
384
559
  # Global GRPC options
385
560
  for p in [p_scan, c_crypto, c_vulns, c_search, c_versions, c_semgrep, c_provenance]:
386
- p.add_argument('--api2url', type=str,
387
- help='SCANOSS gRPC API 2.0 URL (optional - default: https://api.osskb.org)')
388
- p.add_argument('--grpc-proxy', type=str, help='GRPC Proxy URL to use for connections (optional). '
389
- 'Can also use the environment variable "grcp_proxy=<ip>:<port>"')
561
+ p.add_argument(
562
+ '--api2url', type=str, help='SCANOSS gRPC API 2.0 URL (optional - default: https://api.osskb.org)'
563
+ )
564
+ p.add_argument(
565
+ '--grpc-proxy',
566
+ type=str,
567
+ help='GRPC Proxy URL to use for connections (optional). '
568
+ 'Can also use the environment variable "grcp_proxy=<ip>:<port>"',
569
+ )
390
570
 
391
571
  # Help/Trace command options
392
- for p in [p_scan, p_wfp, p_dep, p_fc, p_cnv, p_c_loc, p_c_dwnld, p_p_proxy, c_crypto, c_vulns, c_search,
393
- c_versions, c_semgrep, p_results, p_undeclared, p_copyleft, c_provenance]:
572
+ for p in [
573
+ p_scan,
574
+ p_wfp,
575
+ p_dep,
576
+ p_fc,
577
+ p_cnv,
578
+ p_c_loc,
579
+ p_c_dwnld,
580
+ p_p_proxy,
581
+ c_crypto,
582
+ c_vulns,
583
+ c_search,
584
+ c_versions,
585
+ c_semgrep,
586
+ p_results,
587
+ p_undeclared,
588
+ p_copyleft,
589
+ c_provenance
590
+ ]:
394
591
  p.add_argument('--debug', '-d', action='store_true', help='Enable debug messages')
395
592
  p.add_argument('--trace', '-t', action='store_true', help='Enable trace messages, including API posts')
396
593
  p.add_argument('--quiet', '-q', action='store_true', help='Enable quiet mode')
@@ -398,17 +595,14 @@ def setup_args() -> None:
398
595
  args = parser.parse_args()
399
596
  if args.version:
400
597
  ver(parser, args)
401
- exit(0)
598
+ sys.sys.exit(0)
402
599
  if not args.subparser:
403
600
  parser.print_help() # No sub command subcommand, print general help
404
- exit(1)
405
- else:
406
- if ((args.subparser == 'utils' or args.subparser == 'ut' or
407
- args.subparser == 'component' or args.subparser == 'comp' or
408
- args.subparser == 'inspect' or args.subparser == 'insp' or args.subparser == 'ins')
409
- and not args.subparsercmd):
410
- parser.parse_args([args.subparser, '--help']) # Force utils helps to be displayed
411
- exit(1)
601
+ sys.exit(1)
602
+ elif (
603
+ args.subparser in {'utils', 'ut', 'component', 'comp', 'inspect', 'insp', 'ins'} and not args.subparsercmd):
604
+ parser.parse_args([args.subparser, '--help']) # Force utils helps to be displayed
605
+ sys.exit(1)
412
606
  args.func(parser, args) # Execute the function associated with the sub-command
413
607
 
414
608
 
@@ -441,23 +635,27 @@ def file_count(parser, args):
441
635
  if not args.scan_dir:
442
636
  print_stderr('Please specify a folder')
443
637
  parser.parse_args([args.subparser, '-h'])
444
- exit(1)
638
+ sys.exit(1)
445
639
  scan_output: str = None
446
640
  if args.output:
447
641
  scan_output = args.output
448
642
  open(scan_output, 'w').close()
449
643
 
450
- counter = FileCount(debug=args.debug, quiet=args.quiet, trace=args.trace, scan_output=scan_output,
451
- hidden_files_folders=args.all_hidden
452
- )
644
+ counter = FileCount(
645
+ debug=args.debug,
646
+ quiet=args.quiet,
647
+ trace=args.trace,
648
+ scan_output=scan_output,
649
+ hidden_files_folders=args.all_hidden,
650
+ )
453
651
  if not os.path.exists(args.scan_dir):
454
652
  print_stderr(f'Error: Folder specified does not exist: {args.scan_dir}.')
455
- exit(1)
653
+ sys.exit(1)
456
654
  if os.path.isdir(args.scan_dir):
457
655
  counter.count_files(args.scan_dir)
458
656
  else:
459
657
  print_stderr(f'Error: Path specified is not a folder: {args.scan_dir}.')
460
- exit(1)
658
+ sys.exit(1)
461
659
 
462
660
 
463
661
  def wfp(parser, args):
@@ -473,9 +671,9 @@ def wfp(parser, args):
473
671
  if not args.scan_dir and not args.stdin:
474
672
  print_stderr('Please specify a file/folder or STDIN (--stdin)')
475
673
  parser.parse_args([args.subparser, '-h'])
476
- exit(1)
674
+ sys.exit(1)
477
675
  if args.strip_hpsm and not args.hpsm and not args.quiet:
478
- print_stderr(f'Warning: --strip-hpsm option supplied without enabling HPSM (--hpsm). Ignoring.')
676
+ print_stderr('Warning: --strip-hpsm option supplied without enabling HPSM (--hpsm). Ignoring.')
479
677
  scan_output: str = None
480
678
  if args.output:
481
679
  scan_output = args.output
@@ -489,33 +687,44 @@ def wfp(parser, args):
489
687
  scan_settings.load_json_file(args.settings)
490
688
  except ScanossSettingsError as e:
491
689
  print_stderr(f'Error: {e}')
492
- exit(1)
690
+ sys.exit(1)
493
691
 
494
692
  scan_options = 0 if args.skip_snippets else ScanType.SCAN_SNIPPETS.value # Skip snippet generation or not
495
- scanner = Scanner(debug=args.debug, trace=args.trace, quiet=args.quiet, obfuscate=args.obfuscate,
496
- scan_options=scan_options, all_extensions=args.all_extensions,
497
- all_folders=args.all_folders, hidden_files_folders=args.all_hidden, hpsm=args.hpsm,
498
- skip_size=args.skip_size, skip_extensions=args.skip_extension, skip_folders=args.skip_folder,
499
- skip_md5_ids=args.skip_md5, strip_hpsm_ids=args.strip_hpsm, strip_snippet_ids=args.strip_snippet,
500
- scan_settings=scan_settings
501
- )
693
+ scanner = Scanner(
694
+ debug=args.debug,
695
+ trace=args.trace,
696
+ quiet=args.quiet,
697
+ obfuscate=args.obfuscate,
698
+ scan_options=scan_options,
699
+ all_extensions=args.all_extensions,
700
+ all_folders=args.all_folders,
701
+ hidden_files_folders=args.all_hidden,
702
+ hpsm=args.hpsm,
703
+ skip_size=args.skip_size,
704
+ skip_extensions=args.skip_extension,
705
+ skip_folders=args.skip_folder,
706
+ skip_md5_ids=args.skip_md5,
707
+ strip_hpsm_ids=args.strip_hpsm,
708
+ strip_snippet_ids=args.strip_snippet,
709
+ scan_settings=scan_settings,
710
+ )
502
711
  if args.stdin:
503
712
  contents = sys.stdin.buffer.read()
504
713
  scanner.wfp_contents(args.stdin, contents, scan_output)
505
714
  elif args.scan_dir:
506
715
  if not os.path.exists(args.scan_dir):
507
716
  print_stderr(f'Error: File or folder specified does not exist: {args.scan_dir}.')
508
- exit(1)
717
+ sys.exit(1)
509
718
  if os.path.isdir(args.scan_dir):
510
719
  scanner.wfp_folder(args.scan_dir, scan_output)
511
720
  elif os.path.isfile(args.scan_dir):
512
721
  scanner.wfp_file(args.scan_dir, scan_output)
513
722
  else:
514
723
  print_stderr(f'Error: Path specified is neither a file or a folder: {args.scan_dir}.')
515
- exit(1)
724
+ sys.exit(1)
516
725
  else:
517
726
  print_stderr('No action found to process')
518
- exit(1)
727
+ sys.exit(1)
519
728
 
520
729
 
521
730
  def get_scan_options(args):
@@ -539,18 +748,18 @@ def get_scan_options(args):
539
748
 
540
749
  if args.debug:
541
750
  if ScanType.SCAN_FILES.value & scan_options:
542
- print_stderr(f'Scan Files')
751
+ print_stderr('Scan Files')
543
752
  if ScanType.SCAN_SNIPPETS.value & scan_options:
544
- print_stderr(f'Scan Snippets')
753
+ print_stderr('Scan Snippets')
545
754
  if ScanType.SCAN_DEPENDENCIES.value & scan_options:
546
- print_stderr(f'Scan Dependencies')
755
+ print_stderr('Scan Dependencies')
547
756
  if scan_options <= 0:
548
757
  print_stderr(f'Error: No valid scan options configured: {scan_options}')
549
- exit(1)
758
+ sys.exit(1)
550
759
  return scan_options
551
760
 
552
761
 
553
- def scan(parser, args):
762
+ def scan(parser, args): # noqa: PLR0912, PLR0915
554
763
  """
555
764
  Run the "scan" sub-command
556
765
  Parameters
@@ -565,39 +774,45 @@ def scan(parser, args):
565
774
  'Please specify a file/folder, files (--files), fingerprint (--wfp), dependency (--dep), or STDIN (--stdin)'
566
775
  )
567
776
  parser.parse_args([args.subparser, '-h'])
568
- exit(1)
777
+ sys.exit(1)
569
778
  if args.pac and args.proxy:
570
779
  print_stderr('Please specify one of --proxy or --pac, not both')
571
780
  parser.parse_args([args.subparser, '-h'])
572
- exit(1)
781
+ sys.exit(1)
573
782
  if args.identify and args.settings:
574
783
  print_stderr('ERROR: Cannot specify both --identify and --settings options.')
575
- exit(1)
784
+ sys.exit(1)
576
785
  if args.settings and args.skip_settings_file:
577
786
  print_stderr('ERROR: Cannot specify both --settings and --skip-file-settings options.')
578
- exit(1)
787
+ sys.exit(1)
579
788
  # Figure out which settings (if any) to load before processing
580
789
  scan_settings = None
581
790
  if not args.skip_settings_file:
582
791
  scan_settings = ScanossSettings(debug=args.debug, trace=args.trace, quiet=args.quiet)
583
792
  try:
584
793
  if args.identify:
585
- scan_settings.load_json_file(args.identify, args.scan_dir).set_file_type('legacy').set_scan_type('identify')
794
+ scan_settings.load_json_file(args.identify, args.scan_dir).set_file_type('legacy').set_scan_type(
795
+ 'identify'
796
+ )
586
797
  elif args.ignore:
587
- scan_settings.load_json_file(args.ignore, args.scan_dir).set_file_type('legacy').set_scan_type('blacklist')
798
+ scan_settings.load_json_file(args.ignore, args.scan_dir).set_file_type('legacy').set_scan_type(
799
+ 'blacklist'
800
+ )
588
801
  else:
589
- scan_settings.load_json_file(args.settings, args.scan_dir).set_file_type('new').set_scan_type('identify')
802
+ scan_settings.load_json_file(args.settings, args.scan_dir).set_file_type('new').set_scan_type(
803
+ 'identify'
804
+ )
590
805
  except ScanossSettingsError as e:
591
806
  print_stderr(f'Error: {e}')
592
- exit(1)
807
+ sys.exit(1)
593
808
  if args.dep:
594
809
  if not os.path.exists(args.dep) or not os.path.isfile(args.dep):
595
810
  print_stderr(f'Specified --dep file does not exist or is not a file: {args.dep}')
596
- exit(1)
811
+ sys.exit(1)
597
812
  result = validate_json_file(args.dep)
598
813
  if not result.is_valid:
599
814
  print_stderr(f'Error: Dependency file is not valid: {result.error}')
600
- exit(1)
815
+ sys.exit(1)
601
816
  if args.strip_hpsm and not args.hpsm and not args.quiet:
602
817
  print_stderr('Warning: --strip-hpsm option supplied without enabling HPSM (--hpsm). Ignoring.')
603
818
 
@@ -611,21 +826,21 @@ def scan(parser, args):
611
826
  if args.skip_settings_file:
612
827
  print_stderr('Skipping Settings file...')
613
828
  if args.all_extensions:
614
- print_stderr("Scanning all file extensions/types...")
829
+ print_stderr('Scanning all file extensions/types...')
615
830
  if args.all_folders:
616
- print_stderr("Scanning all folders...")
831
+ print_stderr('Scanning all folders...')
617
832
  if args.all_hidden:
618
- print_stderr("Scanning all hidden files/folders...")
833
+ print_stderr('Scanning all hidden files/folders...')
619
834
  if args.skip_snippets:
620
- print_stderr("Skipping snippets...")
621
- if args.post_size != 32:
835
+ print_stderr('Skipping snippets...')
836
+ if args.post_size != DEFAULT_POST_SIZE:
622
837
  print_stderr(f'Changing scanning POST size to: {args.post_size}k...')
623
- if args.timeout != 180:
838
+ if args.timeout != DEFAULT_TIMEOUT:
624
839
  print_stderr(f'Changing scanning POST timeout to: {args.timeout}...')
625
- if args.retry != 5:
840
+ if args.retry != DEFAULT_RETRY:
626
841
  print_stderr(f'Changing scanning POST retry to: {args.retry}...')
627
842
  if args.obfuscate:
628
- print_stderr("Obfuscating file fingerprints...")
843
+ print_stderr('Obfuscating file fingerprints...')
629
844
  if args.proxy:
630
845
  print_stderr(f'Using Proxy {args.proxy}...')
631
846
  if args.grpc_proxy:
@@ -635,11 +850,11 @@ def scan(parser, args):
635
850
  if args.ca_cert:
636
851
  print_stderr(f'Using Certificate {args.ca_cert}...')
637
852
  if args.hpsm:
638
- print_stderr("Setting HPSM mode...")
853
+ print_stderr('Setting HPSM mode...')
639
854
  if flags:
640
855
  print_stderr(f'Using flags {flags}...')
641
856
  elif not args.quiet:
642
- if args.timeout < 5:
857
+ if args.timeout < MIN_TIMEOUT_VALUE:
643
858
  print_stderr(f'POST timeout (--timeout) too small: {args.timeout}. Reverting to default.')
644
859
  if args.retry < 0:
645
860
  print_stderr(f'POST retry (--retry) too small: {args.retry}. Reverting to default.')
@@ -649,13 +864,16 @@ def scan(parser, args):
649
864
  args.no_wfp_output = True
650
865
  if args.ca_cert and not os.path.exists(args.ca_cert):
651
866
  print_stderr(f'Error: Certificate file does not exist: {args.ca_cert}.')
652
- exit(1)
867
+ sys.exit(1)
653
868
  pac_file = get_pac_file(args.pac)
654
869
  scan_options = get_scan_options(args) # Figure out what scanning options we have
655
870
 
656
871
  scanner = Scanner(
657
- debug=args.debug, trace=args.trace, quiet=args.quiet,
658
- api_key=args.key, url=args.apiurl,
872
+ debug=args.debug,
873
+ trace=args.trace,
874
+ quiet=args.quiet,
875
+ api_key=args.key,
876
+ url=args.apiurl,
659
877
  scan_output=scan_output,
660
878
  output_format=output_format,
661
879
  flags=flags,
@@ -689,47 +907,59 @@ def scan(parser, args):
689
907
  if args.wfp:
690
908
  if not scanner.is_file_or_snippet_scan():
691
909
  print_stderr(f'Error: Cannot specify WFP scanning if file/snippet options are disabled ({scan_options})')
692
- exit(1)
910
+ sys.exit(1)
693
911
  if scanner.is_dependency_scan() and not args.dep:
694
- print_stderr(f'Error: Cannot specify WFP & Dependency scanning without a dependency file (--dep)')
695
- exit(1)
912
+ print_stderr('Error: Cannot specify WFP & Dependency scanning without a dependency file (--dep)')
913
+ sys.exit(1)
696
914
  scanner.scan_wfp_with_options(args.wfp, args.dep)
697
915
  elif args.stdin:
698
916
  contents = sys.stdin.buffer.read()
699
917
  if not scanner.scan_contents(args.stdin, contents):
700
- exit(1)
918
+ sys.exit(1)
701
919
  elif args.files:
702
- if not scanner.scan_files_with_options(
703
- args.files, args.dep, scanner.winnowing.file_map
704
- ):
705
- exit(1)
920
+ if not scanner.scan_files_with_options(args.files, args.dep, scanner.winnowing.file_map):
921
+ sys.exit(1)
706
922
  elif args.scan_dir:
707
923
  if not os.path.exists(args.scan_dir):
708
924
  print_stderr(f'Error: File or folder specified does not exist: {args.scan_dir}.')
709
- exit(1)
925
+ sys.exit(1)
710
926
  if os.path.isdir(args.scan_dir):
711
- if not scanner.scan_folder_with_options(args.scan_dir, args.dep, scanner.winnowing.file_map,
712
- args.dep_scope, args.dep_scope_inc, args.dep_scope_exc):
713
- exit(1)
927
+ if not scanner.scan_folder_with_options(
928
+ args.scan_dir,
929
+ args.dep,
930
+ scanner.winnowing.file_map,
931
+ args.dep_scope,
932
+ args.dep_scope_inc,
933
+ args.dep_scope_exc,
934
+ ):
935
+ sys.exit(1)
714
936
  elif os.path.isfile(args.scan_dir):
715
- if not scanner.scan_file_with_options(args.scan_dir, args.dep, scanner.winnowing.file_map,
716
- args.dep_scope, args.dep_scope_inc, args.dep_scope_exc):
717
- exit(1)
937
+ if not scanner.scan_file_with_options(
938
+ args.scan_dir,
939
+ args.dep,
940
+ scanner.winnowing.file_map,
941
+ args.dep_scope,
942
+ args.dep_scope_inc,
943
+ args.dep_scope_exc,
944
+ ):
945
+ sys.exit(1)
718
946
  else:
719
947
  print_stderr(f'Error: Path specified is neither a file or a folder: {args.scan_dir}.')
720
- exit(1)
948
+ sys.exit(1)
721
949
  elif args.dep:
722
950
  if not args.dependencies_only:
723
951
  print_stderr(
724
- f'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.'
725
954
  )
726
- exit(1)
727
- if not scanner.scan_folder_with_options(".", args.dep, scanner.winnowing.file_map,args.dep_scope,
728
- args.dep_scope_inc, args.dep_scope_exc):
729
- exit(1)
955
+ sys.exit(1)
956
+ if not scanner.scan_folder_with_options(
957
+ '.', args.dep, scanner.winnowing.file_map, args.dep_scope, args.dep_scope_inc, args.dep_scope_exc
958
+ ):
959
+ sys.exit(1)
730
960
  else:
731
961
  print_stderr('No action found to process')
732
- exit(1)
962
+ sys.exit(1)
733
963
 
734
964
 
735
965
  def dependency(parser, args):
@@ -745,20 +975,20 @@ def dependency(parser, args):
745
975
  if not args.scan_dir:
746
976
  print_stderr('Please specify a file/folder')
747
977
  parser.parse_args([args.subparser, '-h'])
748
- exit(1)
978
+ sys.exit(1)
749
979
  if not os.path.exists(args.scan_dir):
750
980
  print_stderr(f'Error: File or folder specified does not exist: {args.scan_dir}.')
751
- exit(1)
981
+ sys.exit(1)
752
982
  scan_output: str = None
753
983
  if args.output:
754
984
  scan_output = args.output
755
985
  open(scan_output, 'w').close()
756
986
 
757
- sc_deps = ScancodeDeps(debug=args.debug, quiet=args.quiet, trace=args.trace, sc_command=args.sc_command,
758
- timeout=args.sc_timeout
759
- )
987
+ sc_deps = ScancodeDeps(
988
+ debug=args.debug, quiet=args.quiet, trace=args.trace, sc_command=args.sc_command, timeout=args.sc_timeout
989
+ )
760
990
  if not sc_deps.get_dependencies(what_to_scan=args.scan_dir, result_output=scan_output):
761
- exit(1)
991
+ sys.exit(1)
762
992
 
763
993
 
764
994
  def convert(parser, args):
@@ -774,27 +1004,28 @@ def convert(parser, args):
774
1004
  if not args.input:
775
1005
  print_stderr('Please specify an input file to convert')
776
1006
  parser.parse_args([args.subparser, '-h'])
777
- exit(1)
1007
+ sys.exit(1)
778
1008
  success = False
779
1009
  if args.format == 'cyclonedx':
780
1010
  if not args.quiet:
781
- print_stderr(f'Producing CycloneDX report...')
1011
+ print_stderr('Producing CycloneDX report...')
782
1012
  cdx = CycloneDx(debug=args.debug, output_file=args.output)
783
1013
  success = cdx.produce_from_file(args.input)
784
1014
  elif args.format == 'spdxlite':
785
1015
  if not args.quiet:
786
- print_stderr(f'Producing SPDX Lite report...')
1016
+ print_stderr('Producing SPDX Lite report...')
787
1017
  spdxlite = SpdxLite(debug=args.debug, output_file=args.output)
788
1018
  success = spdxlite.produce_from_file(args.input)
789
1019
  elif args.format == 'csv':
790
1020
  if not args.quiet:
791
- print_stderr(f'Producing CSV report...')
1021
+ print_stderr('Producing CSV report...')
792
1022
  csvo = CsvOutput(debug=args.debug, output_file=args.output)
793
1023
  success = csvo.produce_from_file(args.input)
794
1024
  else:
795
1025
  print_stderr(f'ERROR: Unknown output format (--format): {args.format}')
796
1026
  if not success:
797
- exit(1)
1027
+ sys.exit(1)
1028
+
798
1029
 
799
1030
  def inspect_copyleft(parser, args):
800
1031
  """
@@ -809,7 +1040,7 @@ def inspect_copyleft(parser, args):
809
1040
  if args.input is None:
810
1041
  print_stderr('Please specify an input file to inspect')
811
1042
  parser.parse_args([args.subparser, args.subparsercmd, '-h'])
812
- exit(1)
1043
+ sys.exit(1)
813
1044
  output: str = None
814
1045
  if args.output:
815
1046
  output = args.output
@@ -820,11 +1051,21 @@ def inspect_copyleft(parser, args):
820
1051
  status_output = args.status
821
1052
  open(status_output, 'w').close()
822
1053
 
823
- i_copyleft = Copyleft(debug=args.debug, trace=args.trace, quiet=args.quiet, filepath=args.input,
824
- format_type=args.format, status=status_output, output=output, include=args.include,
825
- exclude=args.exclude, explicit=args.explicit)
1054
+ i_copyleft = Copyleft(
1055
+ debug=args.debug,
1056
+ trace=args.trace,
1057
+ quiet=args.quiet,
1058
+ filepath=args.input,
1059
+ format_type=args.format,
1060
+ status=status_output,
1061
+ output=output,
1062
+ include=args.include,
1063
+ exclude=args.exclude,
1064
+ explicit=args.explicit,
1065
+ )
826
1066
  status, _ = i_copyleft.run()
827
- sys.exit(status)
1067
+ sys.sys.exit(status)
1068
+
828
1069
 
829
1070
  def inspect_undeclared(parser, args):
830
1071
  """
@@ -839,7 +1080,7 @@ def inspect_undeclared(parser, args):
839
1080
  if args.input is None:
840
1081
  print_stderr('Please specify an input file to inspect')
841
1082
  parser.parse_args([args.subparser, args.subparsercmd, '-h'])
842
- exit(1)
1083
+ sys.exit(1)
843
1084
  output: str = None
844
1085
  if args.output:
845
1086
  output = args.output
@@ -849,11 +1090,19 @@ def inspect_undeclared(parser, args):
849
1090
  if args.status:
850
1091
  status_output = args.status
851
1092
  open(status_output, 'w').close()
852
- i_undeclared = UndeclaredComponent(debug=args.debug, trace=args.trace, quiet=args.quiet,
853
- filepath=args.input, format_type=args.format,
854
- status=status_output, output=output, sbom_format=args.sbom_format)
1093
+ i_undeclared = UndeclaredComponent(
1094
+ debug=args.debug,
1095
+ trace=args.trace,
1096
+ quiet=args.quiet,
1097
+ filepath=args.input,
1098
+ format_type=args.format,
1099
+ status=status_output,
1100
+ output=output,
1101
+ sbom_format=args.sbom_format,
1102
+ )
855
1103
  status, _ = i_undeclared.run()
856
- sys.exit(status)
1104
+ sys.sys.exit(status)
1105
+
857
1106
 
858
1107
  def utils_certloc(*_):
859
1108
  """
@@ -861,9 +1110,11 @@ def utils_certloc(*_):
861
1110
  :param _: ignored/unused
862
1111
  """
863
1112
  import certifi
1113
+
864
1114
  print(f'CA Cert File: {certifi.where()}')
865
1115
 
866
- def utils_cert_download(_, args):
1116
+
1117
+ def utils_cert_download(_, args): # pylint: disable=PLR0912 # noqa: PLR0912
867
1118
  """
868
1119
  Run the "utils cert-download" sub-command
869
1120
  :param _: ignore/unused
@@ -890,21 +1141,23 @@ def utils_cert_download(_, args):
890
1141
  certs = conn.get_peer_cert_chain()
891
1142
  for index, cert in enumerate(certs):
892
1143
  cert_components = dict(cert.get_subject().get_components())
893
- if sys.version_info[0] >= 3:
1144
+ if sys.version_info[0] >= PYTHON3_OR_LATER:
894
1145
  cn = cert_components.get(b'CN')
895
1146
  else:
896
1147
  cn = cert_components.get('CN')
897
1148
  if not args.quiet:
898
1149
  print_stderr(f'Certificate {index} - CN: {cn}')
899
- if sys.version_info[0] >= 3:
900
- print((crypto.dump_certificate(crypto.FILETYPE_PEM, cert).decode('utf-8')).strip(), file=file) # Print the downloaded PEM certificate
1150
+ if sys.version_info[0] >= PYTHON3_OR_LATER:
1151
+ print(
1152
+ (crypto.dump_certificate(crypto.FILETYPE_PEM, cert).decode('utf-8')).strip(), file=file
1153
+ ) # Print the downloaded PEM certificate
901
1154
  else:
902
1155
  print((crypto.dump_certificate(crypto.FILETYPE_PEM, cert)).strip(), file=file)
903
1156
  except SSL.Error as e:
904
1157
  print_stderr(f'ERROR: Exception ({e.__class__.__name__}) Downloading certificate from {hostname}:{port} - {e}.')
905
1158
  if args.debug:
906
1159
  traceback.print_exc()
907
- exit(1)
1160
+ sys.exit(1)
908
1161
  else:
909
1162
  if args.output:
910
1163
  if args.debug:
@@ -919,13 +1172,14 @@ def utils_pac_proxy(_, args):
919
1172
  :param args: Parsed arguments
920
1173
  """
921
1174
  from pypac.resolver import ProxyResolver
1175
+
922
1176
  if not args.pac:
923
- print_stderr(f'Error: No pac file option specified.')
924
- exit(1)
1177
+ print_stderr('Error: No pac file option specified.')
1178
+ sys.exit(1)
925
1179
  pac_file = get_pac_file(args.pac)
926
1180
  if pac_file is None:
927
1181
  print_stderr(f'No proxy configuration for: {args.pac}')
928
- exit(1)
1182
+ sys.exit(1)
929
1183
  resolver = ProxyResolver(pac_file)
930
1184
  proxies = resolver.get_proxy_for_requests(args.url)
931
1185
  print(f'Proxies: {proxies}\n')
@@ -945,14 +1199,14 @@ def get_pac_file(pac: str):
945
1199
  pac_local = pac.strip('file://')
946
1200
  if not os.path.exists(pac_local):
947
1201
  print_stderr(f'Error: PAC file does not exist: {pac_local}.')
948
- exit(1)
1202
+ sys.exit(1)
949
1203
  with open(pac_local) as pf:
950
1204
  pac_file = pypac.get_pac(js=pf.read())
951
1205
  elif pac.startswith('http'):
952
1206
  pac_file = pypac.get_pac(url=pac)
953
1207
  else:
954
1208
  print_stderr(f'Error: Unknown PAC file option: {pac}. Should be one of "auto", "file://", "https://"')
955
- exit(1)
1209
+ sys.exit(1)
956
1210
  return pac_file
957
1211
 
958
1212
 
@@ -969,16 +1223,25 @@ def comp_crypto(parser, args):
969
1223
  if (not args.purl and not args.input) or (args.purl and args.input):
970
1224
  print_stderr('Please specify an input file or purl to decorate (--purl or --input)')
971
1225
  parser.parse_args([args.subparser, args.subparsercmd, '-h'])
972
- exit(1)
1226
+ sys.exit(1)
973
1227
  if args.ca_cert and not os.path.exists(args.ca_cert):
974
1228
  print_stderr(f'Error: Certificate file does not exist: {args.ca_cert}.')
975
- exit(1)
1229
+ sys.exit(1)
976
1230
  pac_file = get_pac_file(args.pac)
977
- comps = Components(debug=args.debug, trace=args.trace, quiet=args.quiet, grpc_url=args.api2url, api_key=args.key,
978
- ca_cert=args.ca_cert, proxy=args.proxy, grpc_proxy=args.grpc_proxy, pac=pac_file,
979
- timeout=args.timeout)
1231
+ comps = Components(
1232
+ debug=args.debug,
1233
+ trace=args.trace,
1234
+ quiet=args.quiet,
1235
+ grpc_url=args.api2url,
1236
+ api_key=args.key,
1237
+ ca_cert=args.ca_cert,
1238
+ proxy=args.proxy,
1239
+ grpc_proxy=args.grpc_proxy,
1240
+ pac=pac_file,
1241
+ timeout=args.timeout,
1242
+ )
980
1243
  if not comps.get_crypto_details(args.input, args.purl, args.output):
981
- exit(1)
1244
+ sys.exit(1)
982
1245
 
983
1246
 
984
1247
  def comp_vulns(parser, args):
@@ -994,16 +1257,26 @@ def comp_vulns(parser, args):
994
1257
  if (not args.purl and not args.input) or (args.purl and args.input):
995
1258
  print_stderr('Please specify an input file or purl to decorate (--purl or --input)')
996
1259
  parser.parse_args([args.subparser, args.subparsercmd, '-h'])
997
- exit(1)
1260
+ sys.exit(1)
998
1261
  if args.ca_cert and not os.path.exists(args.ca_cert):
999
1262
  print_stderr(f'Error: Certificate file does not exist: {args.ca_cert}.')
1000
- exit(1)
1263
+ sys.exit(1)
1001
1264
  pac_file = get_pac_file(args.pac)
1002
- comps = Components(debug=args.debug, trace=args.trace, quiet=args.quiet, grpc_url=args.api2url, api_key=args.key,
1003
- ca_cert=args.ca_cert, proxy=args.proxy, grpc_proxy=args.grpc_proxy, pac=pac_file,
1004
- timeout=args.timeout)
1265
+ comps = Components(
1266
+ debug=args.debug,
1267
+ trace=args.trace,
1268
+ quiet=args.quiet,
1269
+ grpc_url=args.api2url,
1270
+ api_key=args.key,
1271
+ ca_cert=args.ca_cert,
1272
+ proxy=args.proxy,
1273
+ grpc_proxy=args.grpc_proxy,
1274
+ pac=pac_file,
1275
+ timeout=args.timeout,
1276
+ )
1005
1277
  if not comps.get_vulnerabilities(args.input, args.purl, args.output):
1006
- exit(1)
1278
+ sys.exit(1)
1279
+
1007
1280
 
1008
1281
  def comp_semgrep(parser, args):
1009
1282
  """
@@ -1018,20 +1291,30 @@ def comp_semgrep(parser, args):
1018
1291
  if (not args.purl and not args.input) or (args.purl and args.input):
1019
1292
  print_stderr('Please specify an input file or purl to decorate (--purl or --input)')
1020
1293
  parser.parse_args([args.subparser, args.subparsercmd, '-h'])
1021
- exit(1)
1294
+ sys.exit(1)
1022
1295
  if args.ca_cert and not os.path.exists(args.ca_cert):
1023
1296
  print_stderr(f'Error: Certificate file does not exist: {args.ca_cert}.')
1024
- exit(1)
1297
+ sys.exit(1)
1025
1298
  pac_file = get_pac_file(args.pac)
1026
- comps = Components(debug=args.debug, trace=args.trace, quiet=args.quiet, grpc_url=args.api2url, api_key=args.key,
1027
- ca_cert=args.ca_cert, proxy=args.proxy, grpc_proxy=args.grpc_proxy, pac=pac_file,
1028
- timeout=args.timeout)
1299
+ comps = Components(
1300
+ debug=args.debug,
1301
+ trace=args.trace,
1302
+ quiet=args.quiet,
1303
+ grpc_url=args.api2url,
1304
+ api_key=args.key,
1305
+ ca_cert=args.ca_cert,
1306
+ proxy=args.proxy,
1307
+ grpc_proxy=args.grpc_proxy,
1308
+ pac=pac_file,
1309
+ timeout=args.timeout,
1310
+ )
1029
1311
  if not comps.get_semgrep_details(args.input, args.purl, args.output):
1030
- exit(1)
1312
+ sys.exit(1)
1031
1313
 
1032
- def comp_provenance(parser, args):
1314
+
1315
+ def comp_search(parser, args):
1033
1316
  """
1034
- Run the "component provenance" sub-command
1317
+ Run the "component search" sub-command
1035
1318
  Parameters
1036
1319
  ----------
1037
1320
  parser: ArgumentParser
@@ -1039,23 +1322,45 @@ def comp_provenance(parser, args):
1039
1322
  args: Namespace
1040
1323
  Parsed arguments
1041
1324
  """
1042
- if (not args.purl and not args.input) or (args.purl and args.input):
1043
- print_stderr('Please specify an input file or purl to decorate (--purl or --input)')
1325
+ if (not args.input and not args.search and not args.vendor and not args.comp) or (
1326
+ args.input and (args.search or args.vendor or args.comp)
1327
+ ):
1328
+ print_stderr('Please specify an input file or search terms (--input or --search, or --vendor or --comp.)')
1044
1329
  parser.parse_args([args.subparser, args.subparsercmd, '-h'])
1045
- exit(1)
1330
+ sys.exit(1)
1331
+
1046
1332
  if args.ca_cert and not os.path.exists(args.ca_cert):
1047
1333
  print_stderr(f'Error: Certificate file does not exist: {args.ca_cert}.')
1048
- exit(1)
1334
+ sys.exit(1)
1049
1335
  pac_file = get_pac_file(args.pac)
1050
- comps = Components(debug=args.debug, trace=args.trace, quiet=args.quiet, grpc_url=args.api2url, api_key=args.key,
1051
- ca_cert=args.ca_cert, proxy=args.proxy, grpc_proxy=args.grpc_proxy, pac=pac_file,
1052
- timeout=args.timeout)
1053
- if not comps.get_provenance_details(args.input, args.purl, args.output):
1054
- exit(1)
1336
+ comps = Components(
1337
+ debug=args.debug,
1338
+ trace=args.trace,
1339
+ quiet=args.quiet,
1340
+ grpc_url=args.api2url,
1341
+ api_key=args.key,
1342
+ ca_cert=args.ca_cert,
1343
+ proxy=args.proxy,
1344
+ grpc_proxy=args.grpc_proxy,
1345
+ pac=pac_file,
1346
+ timeout=args.timeout,
1347
+ )
1348
+ if not comps.search_components(
1349
+ args.output,
1350
+ json_file=args.input,
1351
+ search=args.search,
1352
+ vendor=args.vendor,
1353
+ comp=args.comp,
1354
+ package=args.package,
1355
+ limit=args.limit,
1356
+ offset=args.offset,
1357
+ ):
1358
+ sys.exit(1)
1055
1359
 
1056
- def comp_search(parser, args):
1360
+
1361
+ def comp_versions(parser, args):
1057
1362
  """
1058
- Run the "component search" sub-command
1363
+ Run the "component versions" sub-command
1059
1364
  Parameters
1060
1365
  ----------
1061
1366
  parser: ArgumentParser
@@ -1063,28 +1368,33 @@ def comp_search(parser, args):
1063
1368
  args: Namespace
1064
1369
  Parsed arguments
1065
1370
  """
1066
- if ((not args.input and not args.search and not args.vendor and not args.comp) or
1067
- (args.input and (args.search or args.vendor or args.comp))):
1068
- print_stderr('Please specify an input file or search terms (--input or --search, or --vendor or --comp.)')
1371
+ if (not args.input and not args.purl) or (args.input and args.purl):
1372
+ print_stderr('Please specify an input file or search terms (--input or --purl.)')
1069
1373
  parser.parse_args([args.subparser, args.subparsercmd, '-h'])
1070
- exit(1)
1374
+ sys.exit(1)
1071
1375
 
1072
1376
  if args.ca_cert and not os.path.exists(args.ca_cert):
1073
1377
  print_stderr(f'Error: Certificate file does not exist: {args.ca_cert}.')
1074
- exit(1)
1378
+ sys.exit(1)
1075
1379
  pac_file = get_pac_file(args.pac)
1076
- comps = Components(debug=args.debug, trace=args.trace, quiet=args.quiet, grpc_url=args.api2url, api_key=args.key,
1077
- ca_cert=args.ca_cert, proxy=args.proxy, grpc_proxy=args.grpc_proxy, pac=pac_file,
1078
- timeout=args.timeout)
1079
- if not comps.search_components(args.output, json_file=args.input,
1080
- search=args.search, vendor=args.vendor, comp=args.comp, package=args.package,
1081
- limit=args.limit, offset=args.offset):
1082
- exit(1)
1083
-
1380
+ comps = Components(
1381
+ debug=args.debug,
1382
+ trace=args.trace,
1383
+ quiet=args.quiet,
1384
+ grpc_url=args.api2url,
1385
+ api_key=args.key,
1386
+ ca_cert=args.ca_cert,
1387
+ proxy=args.proxy,
1388
+ grpc_proxy=args.grpc_proxy,
1389
+ pac=pac_file,
1390
+ timeout=args.timeout,
1391
+ )
1392
+ if not comps.get_component_versions(args.output, json_file=args.input, purl=args.purl, limit=args.limit):
1393
+ sys.exit(1)
1084
1394
 
1085
- def comp_versions(parser, args):
1395
+ def comp_provenance(parser, args):
1086
1396
  """
1087
- Run the "component versions" sub-command
1397
+ Run the "component semgrep" sub-command
1088
1398
  Parameters
1089
1399
  ----------
1090
1400
  parser: ArgumentParser
@@ -1092,21 +1402,19 @@ def comp_versions(parser, args):
1092
1402
  args: Namespace
1093
1403
  Parsed arguments
1094
1404
  """
1095
- if (not args.input and not args.purl) or (args.input and args.purl):
1096
- print_stderr('Please specify an input file or search terms (--input or --purl.)')
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)')
1097
1407
  parser.parse_args([args.subparser, args.subparsercmd, '-h'])
1098
- exit(1)
1099
-
1408
+ sys.exit(1)
1100
1409
  if args.ca_cert and not os.path.exists(args.ca_cert):
1101
1410
  print_stderr(f'Error: Certificate file does not exist: {args.ca_cert}.')
1102
- exit(1)
1411
+ sys.exit(1)
1103
1412
  pac_file = get_pac_file(args.pac)
1104
1413
  comps = Components(debug=args.debug, trace=args.trace, quiet=args.quiet, grpc_url=args.api2url, api_key=args.key,
1105
1414
  ca_cert=args.ca_cert, proxy=args.proxy, grpc_proxy=args.grpc_proxy, pac=pac_file,
1106
1415
  timeout=args.timeout)
1107
- if not comps.get_component_versions(args.output, json_file=args.input, purl=args.purl, limit=args.limit):
1108
- exit(1)
1109
-
1416
+ if not comps.get_provenance_details(args.input, args.purl, args.output):
1417
+ sys.exit(1)
1110
1418
 
1111
1419
  def results(parser, args):
1112
1420
  """
@@ -1120,14 +1428,14 @@ def results(parser, args):
1120
1428
  """
1121
1429
  if not args.filepath:
1122
1430
  print_stderr('ERROR: Please specify a file containing the results')
1123
- parser.parse_args([args.subparser, "-h"])
1124
- exit(1)
1431
+ parser.parse_args([args.subparser, '-h'])
1432
+ sys.exit(1)
1125
1433
 
1126
1434
  file_path = Path(args.filepath).resolve()
1127
1435
 
1128
1436
  if not file_path.is_file():
1129
- print_stderr(f"The specified file {args.filepath} does not exist")
1130
- exit(1)
1437
+ print_stderr(f'The specified file {args.filepath} does not exist')
1438
+ sys.exit(1)
1131
1439
 
1132
1440
  results = Results(
1133
1441
  debug=args.debug,
@@ -1143,7 +1451,7 @@ def results(parser, args):
1143
1451
  if args.has_pending:
1144
1452
  results.get_pending_identifications().present()
1145
1453
  if results.has_results():
1146
- exit(1)
1454
+ sys.exit(1)
1147
1455
  else:
1148
1456
  results.apply_filters().present()
1149
1457
 
@@ -1155,5 +1463,5 @@ def main():
1155
1463
  setup_args()
1156
1464
 
1157
1465
 
1158
- if __name__ == "__main__":
1466
+ if __name__ == '__main__':
1159
1467
  main()