scanoss 1.16.0__tar.gz → 1.17.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {scanoss-1.16.0/src/scanoss.egg-info → scanoss-1.17.0}/PKG-INFO +1 -1
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/__init__.py +1 -1
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/cli.py +95 -14
- scanoss-1.17.0/src/scanoss/data/build_date.txt +1 -0
- scanoss-1.17.0/src/scanoss/inspection/__init__.py +23 -0
- scanoss-1.17.0/src/scanoss/inspection/copyleft.py +156 -0
- scanoss-1.17.0/src/scanoss/inspection/policy_check.py +341 -0
- scanoss-1.17.0/src/scanoss/inspection/undeclared_component.py +167 -0
- scanoss-1.17.0/src/scanoss/inspection/utils/license_utils.py +115 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/results.py +2 -2
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/scanossbase.py +10 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/spdxlite.py +2 -2
- {scanoss-1.16.0 → scanoss-1.17.0/src/scanoss.egg-info}/PKG-INFO +1 -1
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss.egg-info/SOURCES.txt +6 -1
- scanoss-1.16.0/src/scanoss/data/build_date.txt +0 -1
- {scanoss-1.16.0 → scanoss-1.17.0}/LICENSE +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/PACKAGE.md +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/README.md +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/pyproject.toml +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/setup.cfg +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/protoc_gen_swagger/__init__.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/protoc_gen_swagger/options/__init__.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/protoc_gen_swagger/options/annotations_pb2.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/protoc_gen_swagger/options/annotations_pb2_grpc.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/protoc_gen_swagger/options/openapiv2_pb2.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/protoc_gen_swagger/options/openapiv2_pb2_grpc.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/api/__init__.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/api/common/__init__.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/api/common/v2/__init__.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/api/common/v2/scanoss_common_pb2.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/api/common/v2/scanoss_common_pb2_grpc.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/api/components/__init__.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/api/components/v2/__init__.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/api/components/v2/scanoss_components_pb2.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/api/components/v2/scanoss_components_pb2_grpc.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/api/cryptography/v2/scanoss_cryptography_pb2.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/api/cryptography/v2/scanoss_cryptography_pb2_grpc.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/api/dependencies/__init__.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/api/dependencies/v2/__init__.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/api/dependencies/v2/scanoss_dependencies_pb2.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/api/dependencies/v2/scanoss_dependencies_pb2_grpc.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/api/scanning/__init__.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/api/scanning/v2/__init__.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/api/scanning/v2/scanoss_scanning_pb2.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/api/scanning/v2/scanoss_scanning_pb2_grpc.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/api/semgrep/__init__.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/api/semgrep/v2/__init__.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/api/semgrep/v2/scanoss_semgrep_pb2.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/api/semgrep/v2/scanoss_semgrep_pb2_grpc.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/api/vulnerabilities/__init__.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/api/vulnerabilities/v2/__init__.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2_grpc.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/components.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/csvoutput.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/cyclonedx.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/data/spdx-exceptions.json +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/data/spdx-licenses.json +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/filecount.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/scancodedeps.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/scanner.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/scanoss_settings.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/scanossapi.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/scanossgrpc.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/scanpostprocessor.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/scantype.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/threadeddependencies.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/threadedscanning.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss/winnowing.py +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss.egg-info/dependency_links.txt +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss.egg-info/entry_points.txt +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss.egg-info/requires.txt +0 -0
- {scanoss-1.16.0 → scanoss-1.17.0}/src/scanoss.egg-info/top_level.txt +0 -0
|
@@ -25,15 +25,13 @@ import argparse
|
|
|
25
25
|
import os
|
|
26
26
|
from pathlib import Path
|
|
27
27
|
import sys
|
|
28
|
-
from array import array
|
|
29
|
-
|
|
30
28
|
import pypac
|
|
31
|
-
|
|
29
|
+
from scanoss.inspection.copyleft import Copyleft
|
|
30
|
+
from scanoss.inspection.undeclared_component import UndeclaredComponent
|
|
32
31
|
from .threadeddependencies import SCOPE
|
|
33
|
-
from .scanner import Scanner
|
|
34
32
|
from .scanoss_settings import ScanossSettings
|
|
35
33
|
from .scancodedeps import ScancodeDeps
|
|
36
|
-
from .scanner import
|
|
34
|
+
from .scanner import Scanner
|
|
37
35
|
from .scantype import ScanType
|
|
38
36
|
from .filecount import FileCount
|
|
39
37
|
from .cyclonedx import CycloneDx
|
|
@@ -171,19 +169,19 @@ def setup_args() -> None:
|
|
|
171
169
|
# Component Sub-command: component crypto
|
|
172
170
|
c_crypto = comp_sub.add_parser('crypto', aliases=['cr'],
|
|
173
171
|
description=f'Show Cryptographic algorithms: {__version__}',
|
|
174
|
-
help='
|
|
172
|
+
help='Retrieve cryptographic algorithms for the given components')
|
|
175
173
|
c_crypto.set_defaults(func=comp_crypto)
|
|
176
174
|
|
|
177
175
|
# Component Sub-command: component vulns
|
|
178
176
|
c_vulns = comp_sub.add_parser('vulns', aliases=['vulnerabilities', 'vu'],
|
|
179
177
|
description=f'Show Vulnerability details: {__version__}',
|
|
180
|
-
help='
|
|
178
|
+
help='Retrieve vulnerabilities for the given components')
|
|
181
179
|
c_vulns.set_defaults(func=comp_vulns)
|
|
182
180
|
|
|
183
181
|
# Component Sub-command: component semgrep
|
|
184
182
|
c_semgrep = comp_sub.add_parser('semgrep', aliases=['sp'],
|
|
185
183
|
description=f'Show Semgrep findings: {__version__}',
|
|
186
|
-
help='
|
|
184
|
+
help='Retrieve semgrep issues/findings for the given components')
|
|
187
185
|
c_semgrep.set_defaults(func=comp_semgrep)
|
|
188
186
|
|
|
189
187
|
# Component Sub-command: component search
|
|
@@ -299,6 +297,31 @@ def setup_args() -> None:
|
|
|
299
297
|
)
|
|
300
298
|
p_results.set_defaults(func=results)
|
|
301
299
|
|
|
300
|
+
|
|
301
|
+
# Sub-command: inspect
|
|
302
|
+
p_inspect = subparsers.add_parser('inspect', aliases=['insp', 'ins'],
|
|
303
|
+
description=f'Inspect results: {__version__}',
|
|
304
|
+
help='Inspect results')
|
|
305
|
+
# Sub-parser: inspect
|
|
306
|
+
p_inspect_sub = p_inspect.add_subparsers(title='Inspect Commands', dest='subparsercmd',
|
|
307
|
+
description='Inspect sub-commands', help='Inspect sub-commands')
|
|
308
|
+
# Inspect Sub-command: inspect copyleft
|
|
309
|
+
p_copyleft = p_inspect_sub.add_parser('copyleft', aliases=['cp'],description="Inspect for copyleft licenses", help='Inspect for copyleft licenses')
|
|
310
|
+
p_copyleft.add_argument('--include', help='List of Copyleft licenses to append to the default list. Provide licenses as a comma-separated list.')
|
|
311
|
+
p_copyleft.add_argument('--exclude', help='List of Copyleft licenses to remove from default list. Provide licenses as a comma-separated list.')
|
|
312
|
+
p_copyleft.add_argument('--explicit', help='Explicit list of Copyleft licenses to consider. Provide licenses as a comma-separated list.s')
|
|
313
|
+
p_copyleft.set_defaults(func=inspect_copyleft)
|
|
314
|
+
|
|
315
|
+
# Inspect Sub-command: inspect undeclared
|
|
316
|
+
p_undeclared = p_inspect_sub.add_parser('undeclared', aliases=['un'],description="Inspect for undeclared components", help='Inspect for undeclared components')
|
|
317
|
+
p_undeclared.set_defaults(func=inspect_undeclared)
|
|
318
|
+
|
|
319
|
+
for p in [p_copyleft, p_undeclared]:
|
|
320
|
+
p.add_argument('-i', '--input', nargs='?', help='Path to results file')
|
|
321
|
+
p.add_argument('-f', '--format',required=False ,choices=['json', 'md'], default='json', help='Output format (default: json)')
|
|
322
|
+
p.add_argument('-o', '--output', type=str, help='Save details into a file')
|
|
323
|
+
p.add_argument('-s', '--status', type=str, help='Save summary data into Markdown file')
|
|
324
|
+
|
|
302
325
|
# Global Scan command options
|
|
303
326
|
for p in [p_scan]:
|
|
304
327
|
p.add_argument('--apiurl', type=str,
|
|
@@ -344,7 +367,7 @@ def setup_args() -> None:
|
|
|
344
367
|
|
|
345
368
|
# Help/Trace command options
|
|
346
369
|
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,
|
|
347
|
-
c_versions, c_semgrep, p_results]:
|
|
370
|
+
c_versions, c_semgrep, p_results, p_undeclared, p_copyleft]:
|
|
348
371
|
p.add_argument('--debug', '-d', action='store_true', help='Enable debug messages')
|
|
349
372
|
p.add_argument('--trace', '-t', action='store_true', help='Enable trace messages, including API posts')
|
|
350
373
|
p.add_argument('--quiet', '-q', action='store_true', help='Enable quiet mode')
|
|
@@ -357,9 +380,10 @@ def setup_args() -> None:
|
|
|
357
380
|
parser.print_help() # No sub command subcommand, print general help
|
|
358
381
|
exit(1)
|
|
359
382
|
else:
|
|
360
|
-
if (args.subparser == 'utils' or args.subparser == 'ut' or
|
|
361
|
-
args.subparser == 'component' or args.subparser == 'comp'
|
|
362
|
-
|
|
383
|
+
if ((args.subparser == 'utils' or args.subparser == 'ut' or
|
|
384
|
+
args.subparser == 'component' or args.subparser == 'comp' or
|
|
385
|
+
args.subparser == 'inspect' or args.subparser == 'insp' or args.subparser == 'ins')
|
|
386
|
+
and not args.subparsercmd):
|
|
363
387
|
parser.parse_args([args.subparser, '--help']) # Force utils helps to be displayed
|
|
364
388
|
exit(1)
|
|
365
389
|
args.func(parser, args) # Execute the function associated with the sub-command
|
|
@@ -778,6 +802,64 @@ def convert(parser, args):
|
|
|
778
802
|
if not success:
|
|
779
803
|
exit(1)
|
|
780
804
|
|
|
805
|
+
def inspect_copyleft(parser, args):
|
|
806
|
+
"""
|
|
807
|
+
Run the "inspect" sub-command
|
|
808
|
+
Parameters
|
|
809
|
+
----------
|
|
810
|
+
parser: ArgumentParser
|
|
811
|
+
command line parser object
|
|
812
|
+
args: Namespace
|
|
813
|
+
Parsed arguments
|
|
814
|
+
"""
|
|
815
|
+
if args.input is None:
|
|
816
|
+
print_stderr('Please specify an input file to inspect')
|
|
817
|
+
parser.parse_args([args.subparser, args.subparsercmd, '-h'])
|
|
818
|
+
exit(1)
|
|
819
|
+
output: str = None
|
|
820
|
+
if args.output:
|
|
821
|
+
output = args.output
|
|
822
|
+
open(output, 'w').close()
|
|
823
|
+
|
|
824
|
+
status_output: str = None
|
|
825
|
+
if args.status:
|
|
826
|
+
status_output = args.status
|
|
827
|
+
open(status_output, 'w').close()
|
|
828
|
+
|
|
829
|
+
i_copyleft = Copyleft(debug=args.debug, trace=args.trace, quiet=args.quiet, filepath=args.input,
|
|
830
|
+
format_type=args.format, status=status_output, output=output, include=args.include,
|
|
831
|
+
exclude=args.exclude, explicit=args.explicit)
|
|
832
|
+
status, _ = i_copyleft.run()
|
|
833
|
+
sys.exit(status)
|
|
834
|
+
|
|
835
|
+
def inspect_undeclared(parser, args):
|
|
836
|
+
"""
|
|
837
|
+
Run the "inspect" sub-command
|
|
838
|
+
Parameters
|
|
839
|
+
----------
|
|
840
|
+
parser: ArgumentParser
|
|
841
|
+
command line parser object
|
|
842
|
+
args: Namespace
|
|
843
|
+
Parsed arguments
|
|
844
|
+
"""
|
|
845
|
+
if args.input is None:
|
|
846
|
+
print_stderr('Please specify an input file to inspect')
|
|
847
|
+
parser.parse_args([args.subparser, args.subparsercmd, '-h'])
|
|
848
|
+
exit(1)
|
|
849
|
+
output: str = None
|
|
850
|
+
if args.output:
|
|
851
|
+
output = args.output
|
|
852
|
+
open(output, 'w').close()
|
|
853
|
+
|
|
854
|
+
status_output: str = None
|
|
855
|
+
if args.status:
|
|
856
|
+
status_output = args.status
|
|
857
|
+
open(status_output, 'w').close()
|
|
858
|
+
i_undeclared = UndeclaredComponent(debug=args.debug, trace=args.trace, quiet=args.quiet,
|
|
859
|
+
filepath=args.input, format_type=args.format,
|
|
860
|
+
status=status_output, output=output)
|
|
861
|
+
status, _ = i_undeclared.run()
|
|
862
|
+
sys.exit(status)
|
|
781
863
|
|
|
782
864
|
def utils_certloc(*_):
|
|
783
865
|
"""
|
|
@@ -787,7 +869,6 @@ def utils_certloc(*_):
|
|
|
787
869
|
import certifi
|
|
788
870
|
print(f'CA Cert File: {certifi.where()}')
|
|
789
871
|
|
|
790
|
-
|
|
791
872
|
def utils_cert_download(_, args):
|
|
792
873
|
"""
|
|
793
874
|
Run the "utils cert-download" sub-command
|
|
@@ -820,7 +901,7 @@ def utils_cert_download(_, args):
|
|
|
820
901
|
else:
|
|
821
902
|
cn = cert_components.get('CN')
|
|
822
903
|
if not args.quiet:
|
|
823
|
-
print_stderr(f'
|
|
904
|
+
print_stderr(f'Certificate {index} - CN: {cn}')
|
|
824
905
|
if sys.version_info[0] >= 3:
|
|
825
906
|
print((crypto.dump_certificate(crypto.FILETYPE_PEM, cert).decode('utf-8')).strip(), file=file) # Print the downloaded PEM certificate
|
|
826
907
|
else:
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
date: 20241023122954, utime: 1729686594
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""
|
|
2
|
+
SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
Copyright (c) 2024, 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
|
+
"""
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"""
|
|
2
|
+
SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
Copyright (c) 2024, 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
|
+
"""
|
|
24
|
+
import json
|
|
25
|
+
from typing import Dict, Any
|
|
26
|
+
from scanoss.inspection.policy_check import PolicyCheck, PolicyStatus
|
|
27
|
+
|
|
28
|
+
class Copyleft(PolicyCheck):
|
|
29
|
+
"""
|
|
30
|
+
SCANOSS Copyleft class
|
|
31
|
+
Inspects components for copyleft licenses
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
def __init__(self, debug: bool = False, trace: bool = True, quiet: bool = False, filepath: str = None,
|
|
35
|
+
format_type: str = 'json', status: str = None, output: str = None, include: str = None,
|
|
36
|
+
exclude: str = None, explicit: str = None):
|
|
37
|
+
"""
|
|
38
|
+
Initialize the Copyleft class.
|
|
39
|
+
|
|
40
|
+
:param debug: Enable debug mode
|
|
41
|
+
:param trace: Enable trace mode (default True)
|
|
42
|
+
:param quiet: Enable quiet mode
|
|
43
|
+
:param filepath: Path to the file containing component data
|
|
44
|
+
:param format_type: Output format ('json' or 'md')
|
|
45
|
+
:param status: Path to save the status output
|
|
46
|
+
:param output: Path to save detailed output
|
|
47
|
+
:param include: Licenses to include in the analysis
|
|
48
|
+
:param exclude: Licenses to exclude from the analysis
|
|
49
|
+
:param explicit: Explicitly defined licenses
|
|
50
|
+
"""
|
|
51
|
+
super().__init__(debug, trace, quiet, filepath, format_type, status, output, name='Copyleft Policy')
|
|
52
|
+
self.license_util.init(include, exclude, explicit)
|
|
53
|
+
self.filepath = filepath
|
|
54
|
+
self.format = format
|
|
55
|
+
self.output = output
|
|
56
|
+
self.status = status
|
|
57
|
+
self.include = include
|
|
58
|
+
self.exclude = exclude
|
|
59
|
+
self.explicit = explicit
|
|
60
|
+
|
|
61
|
+
def _json(self, components: list) -> Dict[str, Any]:
|
|
62
|
+
"""
|
|
63
|
+
Format the components with copyleft licenses as JSON.
|
|
64
|
+
|
|
65
|
+
:param components: List of components with copyleft licenses
|
|
66
|
+
:return: Dictionary with formatted JSON details and summary
|
|
67
|
+
"""
|
|
68
|
+
details = {}
|
|
69
|
+
if len(components) > 0:
|
|
70
|
+
details = { 'components': components }
|
|
71
|
+
return {
|
|
72
|
+
'details': json.dumps(details, indent=2),
|
|
73
|
+
'summary': f'{len(components)} component(s) with copyleft licenses were found.'
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
def _markdown(self, components: list) -> Dict[str,Any]:
|
|
77
|
+
"""
|
|
78
|
+
Format the components with copyleft licenses as Markdown.
|
|
79
|
+
|
|
80
|
+
:param components: List of components with copyleft licenses
|
|
81
|
+
:return: Dictionary with formatted Markdown details and summary
|
|
82
|
+
"""
|
|
83
|
+
headers = ['Component', 'Version', 'License', 'URL', 'Copyleft']
|
|
84
|
+
centered_columns = [1, 4]
|
|
85
|
+
rows: [[]]= []
|
|
86
|
+
for component in components:
|
|
87
|
+
for lic in component['licenses']:
|
|
88
|
+
row = [
|
|
89
|
+
component['purl'],
|
|
90
|
+
component['version'],
|
|
91
|
+
lic['spdxid'],
|
|
92
|
+
lic['url'],
|
|
93
|
+
'YES' if lic['copyleft'] else 'NO'
|
|
94
|
+
]
|
|
95
|
+
rows.append(row)
|
|
96
|
+
# End license loop
|
|
97
|
+
# End component loop
|
|
98
|
+
return {
|
|
99
|
+
'details': f'### Copyleft licenses\n{self.generate_table(headers,rows,centered_columns)}',
|
|
100
|
+
'summary' : f'{len(components)} component(s) with copyleft licenses were found.'
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
def _filter_components_with_copyleft_licenses(self, components: list) -> list:
|
|
104
|
+
"""
|
|
105
|
+
Filter the components list to include only those with copyleft licenses.
|
|
106
|
+
|
|
107
|
+
:param components: List of all components
|
|
108
|
+
:return: List of components with copyleft licenses
|
|
109
|
+
"""
|
|
110
|
+
filtered_components = []
|
|
111
|
+
for component in components:
|
|
112
|
+
copyleft_licenses = [lic for lic in component['licenses'] if lic['copyleft']]
|
|
113
|
+
if copyleft_licenses:
|
|
114
|
+
filtered_component = component
|
|
115
|
+
filtered_component['licenses'] = copyleft_licenses
|
|
116
|
+
del filtered_component['status']
|
|
117
|
+
filtered_components.append(filtered_component)
|
|
118
|
+
# End component loop
|
|
119
|
+
self.print_debug(f'Copyleft components: {filtered_components}')
|
|
120
|
+
return filtered_components
|
|
121
|
+
|
|
122
|
+
def run(self):
|
|
123
|
+
"""
|
|
124
|
+
Run the copyleft license inspection process.
|
|
125
|
+
|
|
126
|
+
This method performs the following steps:
|
|
127
|
+
1. Get all components
|
|
128
|
+
2. Filter components with copyleft licenses
|
|
129
|
+
3. Format the results
|
|
130
|
+
4. Save the output to files if required
|
|
131
|
+
|
|
132
|
+
:return: Dictionary containing the inspection results
|
|
133
|
+
"""
|
|
134
|
+
self._debug()
|
|
135
|
+
# Get the components from the results
|
|
136
|
+
components = self._get_components()
|
|
137
|
+
if components is None:
|
|
138
|
+
return PolicyStatus.ERROR.value, {}
|
|
139
|
+
# Get a list of copyleft components if they exist
|
|
140
|
+
copyleft_components = self._filter_components_with_copyleft_licenses(components)
|
|
141
|
+
# Get a formatter for the output results
|
|
142
|
+
formatter = self._get_formatter()
|
|
143
|
+
if formatter is None:
|
|
144
|
+
return PolicyStatus.ERROR.value, {}
|
|
145
|
+
# Format the results
|
|
146
|
+
results = formatter(copyleft_components)
|
|
147
|
+
## Save outputs if required
|
|
148
|
+
self.print_to_file_or_stdout(results['details'], self.output)
|
|
149
|
+
self.print_to_file_or_stderr(results['summary'], self.status)
|
|
150
|
+
# Check to see if we have policy violations
|
|
151
|
+
if len(copyleft_components) <= 0:
|
|
152
|
+
return PolicyStatus.FAIL.value, results
|
|
153
|
+
return PolicyStatus.SUCCESS.value, results
|
|
154
|
+
#
|
|
155
|
+
# End of Copyleft Class
|
|
156
|
+
#
|