scanoss 1.22.0__py3-none-any.whl → 1.24.0__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.
@@ -0,0 +1,274 @@
1
+ import json
2
+ from dataclasses import dataclass
3
+ from typing import Dict, List, Optional
4
+
5
+ from scanoss.scanossbase import ScanossBase
6
+ from scanoss.scanossgrpc import ScanossGrpc
7
+ from scanoss.utils.abstract_presenter import AbstractPresenter
8
+ from scanoss.utils.file import validate_json_file
9
+
10
+
11
+ class ScanossCryptographyError(Exception):
12
+ pass
13
+
14
+
15
+ MIN_SPLIT_PARTS = 2
16
+
17
+
18
+ @dataclass
19
+ class CryptographyConfig:
20
+ purl: List[str]
21
+ input_file: Optional[str] = None
22
+ output_file: Optional[str] = None
23
+ header: Optional[str] = None
24
+ debug: bool = False
25
+ trace: bool = False
26
+ quiet: bool = False
27
+ with_range: bool = False
28
+
29
+ def __post_init__(self):
30
+ """
31
+ Validate that the configuration is valid.
32
+ """
33
+ if self.purl:
34
+ if self.with_range:
35
+ for purl in self.purl:
36
+ parts = purl.split('@')
37
+ if not (len(parts) >= MIN_SPLIT_PARTS and parts[1]):
38
+ raise ScanossCryptographyError(
39
+ f'Invalid PURL format: "{purl}".' f'It must include a version (e.g., pkg:type/name@version)'
40
+ )
41
+ if self.input_file:
42
+ input_file_validation = validate_json_file(self.input_file)
43
+ if not input_file_validation.is_valid:
44
+ raise ScanossCryptographyError(
45
+ f'There was a problem with the purl input file. {input_file_validation.error}'
46
+ )
47
+ if (
48
+ not isinstance(input_file_validation.data, dict)
49
+ or 'purls' not in input_file_validation.data
50
+ or not isinstance(input_file_validation.data['purls'], list)
51
+ or not all(isinstance(p, dict) and 'purl' in p for p in input_file_validation.data['purls'])
52
+ ):
53
+ raise ScanossCryptographyError('The supplied input file is not in the correct PurlRequest format.')
54
+ purls = input_file_validation.data['purls']
55
+ purls_with_requirement = []
56
+ if self.with_range:
57
+ if any('requirement' not in p for p in purls):
58
+ raise ScanossCryptographyError(
59
+ f'One or more PURLs in "{self.input_file}" are missing the "requirement" field.'
60
+ )
61
+ else:
62
+ for purl in purls:
63
+ purls_with_requirement.append(f'{purl["purl"]}@{purl["requirement"]}')
64
+ else:
65
+ purls_with_requirement = purls
66
+ self.purl = purls_with_requirement
67
+
68
+
69
+ def create_cryptography_config_from_args(args) -> CryptographyConfig:
70
+ return CryptographyConfig(
71
+ debug=getattr(args, 'debug', False),
72
+ trace=getattr(args, 'trace', False),
73
+ quiet=getattr(args, 'quiet', False),
74
+ with_range=getattr(args, 'with_range', False),
75
+ purl=getattr(args, 'purl', []),
76
+ input_file=getattr(args, 'input', None),
77
+ output_file=getattr(args, 'output', None),
78
+ header=getattr(args, 'header', None),
79
+ )
80
+
81
+
82
+ class Cryptography:
83
+ """
84
+ Cryptography Class
85
+
86
+ This class is used to decorate purls with cryptography information.
87
+ """
88
+
89
+ def __init__(
90
+ self,
91
+ config: CryptographyConfig,
92
+ client: ScanossGrpc,
93
+ ):
94
+ """
95
+ Initialize the Cryptography.
96
+
97
+ Args:
98
+ config (CryptographyConfig): Configuration parameters for the cryptography.
99
+ client (ScanossGrpc): gRPC client for communicating with the scanning service.
100
+ """
101
+ self.base = ScanossBase(
102
+ debug=config.debug,
103
+ trace=config.trace,
104
+ quiet=config.quiet,
105
+ )
106
+ self.presenter = CryptographyPresenter(
107
+ self,
108
+ debug=config.debug,
109
+ trace=config.trace,
110
+ quiet=config.quiet,
111
+ )
112
+
113
+ self.client = client
114
+ self.config = config
115
+ self.purls_request = self._build_purls_request()
116
+ self.results = None
117
+
118
+ def get_algorithms(self) -> Optional[Dict]:
119
+ """
120
+ Get the cryptographic algorithms for the provided purl or input file.
121
+
122
+ Returns:
123
+ Optional[Dict]: The folder hash response from the gRPC client, or None if an error occurs.
124
+ """
125
+
126
+ if not self.purls_request:
127
+ raise ScanossCryptographyError('No PURLs supplied. Provide --purl or --input.')
128
+ self.base.print_stderr(
129
+ f'Getting cryptographic algorithms for {", ".join([p["purl"] for p in self.purls_request["purls"]])}'
130
+ )
131
+ if self.config.with_range:
132
+ response = self.client.get_crypto_algorithms_in_range_for_purl(self.purls_request)
133
+ else:
134
+ response = self.client.get_crypto_algorithms_for_purl(self.purls_request)
135
+ if response:
136
+ self.results = response
137
+
138
+ return self.results
139
+
140
+ def get_encryption_hints(self) -> Optional[Dict]:
141
+ """
142
+ Get the encryption hints for the provided purl or input file.
143
+
144
+ Returns:
145
+ Optional[Dict]: The encryption hints response from the gRPC client, or None if an error occurs.
146
+ """
147
+
148
+ if not self.purls_request:
149
+ raise ScanossCryptographyError('No PURLs supplied. Provide --purl or --input.')
150
+ self.base.print_stderr(
151
+ f'Getting encryption hints '
152
+ f'{"in range" if self.config.with_range else ""} '
153
+ f'for {", ".join([p["purl"] for p in self.purls_request["purls"]])}'
154
+ )
155
+ if self.config.with_range:
156
+ response = self.client.get_encryption_hints_in_range_for_purl(self.purls_request)
157
+ else:
158
+ response = self.client.get_encryption_hints_for_purl(self.purls_request)
159
+ if response:
160
+ self.results = response
161
+
162
+ return self.results
163
+
164
+ def get_versions_in_range(self) -> Optional[Dict]:
165
+ """
166
+ Given a list of PURLS and version ranges, get a list of versions that do/do not contain cryptographic algorithms
167
+
168
+ Returns:
169
+ Optional[Dict]: The versions in range response from the gRPC client, or None if an error occurs.
170
+ """
171
+
172
+ if not self.purls_request:
173
+ raise ScanossCryptographyError('No PURLs supplied. Provide --purl or --input.')
174
+
175
+ self.base.print_stderr(
176
+ f'Getting versions in range for {", ".join([p["purl"] for p in self.purls_request["purls"]])}'
177
+ )
178
+
179
+ response = self.client.get_versions_in_range_for_purl(self.purls_request)
180
+ if response:
181
+ self.results = response
182
+
183
+ return self.results
184
+
185
+ def _build_purls_request(
186
+ self,
187
+ ) -> Optional[dict]:
188
+ """
189
+ Load the specified purls from a JSON file or a list of PURLs and return a dictionary
190
+
191
+ Args:
192
+ json_file (Optional[str], optional): The JSON file containing the PURLs. Defaults to None.
193
+ purls (Optional[List[str]], optional): The list of PURLs. Defaults to None.
194
+
195
+ Returns:
196
+ Optional[dict]: The dictionary containing the PURLs
197
+ """
198
+ return {
199
+ 'purls': [
200
+ {
201
+ 'purl': p,
202
+ 'requirement': self._extract_version_from_purl(p),
203
+ }
204
+ for p in self.config.purl
205
+ ]
206
+ }
207
+
208
+ def _extract_version_from_purl(self, purl: str) -> str:
209
+ """
210
+ Extract version from purl
211
+
212
+ Args:
213
+ purl (str): The purl string to extract the version from
214
+
215
+ Returns:
216
+ str: The extracted version
217
+
218
+ Raises:
219
+ ScanossCryptographyError: If the purl is not in the correct format
220
+ """
221
+ try:
222
+ return purl.split('@')[-1]
223
+ except IndexError:
224
+ raise ScanossCryptographyError(f'Invalid purl format: {purl}')
225
+
226
+ def present(
227
+ self,
228
+ output_format: Optional[str] = None,
229
+ output_file: Optional[str] = None,
230
+ ):
231
+ """Present the results in the selected format"""
232
+ self.presenter.present(output_format=output_format, output_file=output_file)
233
+
234
+
235
+ class CryptographyPresenter(AbstractPresenter):
236
+ """
237
+ Cryptography presenter class
238
+ Handles the presentation of the cryptography results
239
+ """
240
+
241
+ def __init__(self, cryptography: Cryptography, **kwargs):
242
+ super().__init__(**kwargs)
243
+ self.cryptography = cryptography
244
+
245
+ def _format_json_output(self) -> str:
246
+ """
247
+ Format the scan output data into a JSON object
248
+
249
+ Returns:
250
+ str: The formatted JSON string
251
+ """
252
+ return json.dumps(self.cryptography.results, indent=2)
253
+
254
+ def _format_plain_output(self) -> str:
255
+ """
256
+ Format the scan output data into a plain text string
257
+ """
258
+ return (
259
+ json.dumps(self.cryptography.results, indent=2)
260
+ if isinstance(self.cryptography.results, dict)
261
+ else str(self.cryptography.results)
262
+ )
263
+
264
+ def _format_cyclonedx_output(self) -> str:
265
+ raise NotImplementedError('CycloneDX output is not implemented')
266
+
267
+ def _format_spdxlite_output(self) -> str:
268
+ raise NotImplementedError('SPDXlite output is not implemented')
269
+
270
+ def _format_csv_output(self) -> str:
271
+ raise NotImplementedError('CSV output is not implemented')
272
+
273
+ def _format_raw_output(self) -> str:
274
+ raise NotImplementedError('Raw output is not implemented')
@@ -1 +1 @@
1
- date: 20250423153708, utime: 1745422628
1
+ date: 20250528081438, utime: 1748420078
@@ -117,7 +117,8 @@ class ScannerHFH:
117
117
 
118
118
  try:
119
119
  response = self.client.folder_hash_scan(hfh_request)
120
- self.scan_results = response
120
+ if response:
121
+ self.scan_results = response
121
122
  finally:
122
123
  stop_spinner = True
123
124
  spinner_thread.join()
scanoss/scanossgrpc.py CHANGED
@@ -36,7 +36,6 @@ from google.protobuf.json_format import MessageToDict, ParseDict
36
36
  from pypac.parser import PACFile
37
37
  from pypac.resolver import ProxyResolver
38
38
 
39
- from scanoss.api.provenance.v2.scanoss_provenance_pb2_grpc import ProvenanceStub
40
39
  from scanoss.api.scanning.v2.scanoss_scanning_pb2_grpc import ScanningStub
41
40
  from scanoss.constants import DEFAULT_TIMEOUT
42
41
 
@@ -55,11 +54,11 @@ from .api.components.v2.scanoss_components_pb2 import (
55
54
  CompVersionResponse,
56
55
  )
57
56
  from .api.components.v2.scanoss_components_pb2_grpc import ComponentsStub
58
- from .api.cryptography.v2.scanoss_cryptography_pb2 import AlgorithmResponse
59
57
  from .api.cryptography.v2.scanoss_cryptography_pb2_grpc import CryptographyStub
60
58
  from .api.dependencies.v2.scanoss_dependencies_pb2 import DependencyRequest
61
59
  from .api.dependencies.v2.scanoss_dependencies_pb2_grpc import DependenciesStub
62
- from .api.provenance.v2.scanoss_provenance_pb2 import ProvenanceResponse
60
+ from .api.geoprovenance.v2.scanoss_geoprovenance_pb2 import ContributorResponse
61
+ from .api.geoprovenance.v2.scanoss_geoprovenance_pb2_grpc import GeoProvenanceStub
63
62
  from .api.scanning.v2.scanoss_scanning_pb2 import HFHRequest
64
63
  from .api.semgrep.v2.scanoss_semgrep_pb2 import SemgrepResponse
65
64
  from .api.semgrep.v2.scanoss_semgrep_pb2_grpc import SemgrepStub
@@ -169,7 +168,7 @@ class ScanossGrpc(ScanossBase):
169
168
  self.dependencies_stub = DependenciesStub(grpc.insecure_channel(self.url))
170
169
  self.semgrep_stub = SemgrepStub(grpc.insecure_channel(self.url))
171
170
  self.vuln_stub = VulnerabilitiesStub(grpc.insecure_channel(self.url))
172
- self.provenance_stub = ProvenanceStub(grpc.insecure_channel(self.url))
171
+ self.provenance_stub = GeoProvenanceStub(grpc.insecure_channel(self.url))
173
172
  self.scanning_stub = ScanningStub(grpc.insecure_channel(self.url))
174
173
  else:
175
174
  if ca_cert is not None:
@@ -181,7 +180,7 @@ class ScanossGrpc(ScanossBase):
181
180
  self.dependencies_stub = DependenciesStub(grpc.secure_channel(self.url, credentials))
182
181
  self.semgrep_stub = SemgrepStub(grpc.secure_channel(self.url, credentials))
183
182
  self.vuln_stub = VulnerabilitiesStub(grpc.secure_channel(self.url, credentials))
184
- self.provenance_stub = ProvenanceStub(grpc.secure_channel(self.url, credentials))
183
+ self.provenance_stub = GeoProvenanceStub(grpc.secure_channel(self.url, credentials))
185
184
  self.scanning_stub = ScanningStub(grpc.secure_channel(self.url, credentials))
186
185
 
187
186
  @classmethod
@@ -312,36 +311,6 @@ class ScanossGrpc(ScanossBase):
312
311
  merged_response['status'] = response['status']
313
312
  return merged_response
314
313
 
315
- def get_crypto_json(self, purls: dict) -> dict:
316
- """
317
- Client function to call the rpc for Cryptography GetAlgorithms
318
- :param purls: Message to send to the service
319
- :return: Server response or None
320
- """
321
- if not purls:
322
- self.print_stderr('ERROR: No message supplied to send to gRPC service.')
323
- return None
324
- request_id = str(uuid.uuid4())
325
- resp: AlgorithmResponse
326
- try:
327
- request = ParseDict(purls, PurlRequest()) # Parse the JSON/Dict into the purl request object
328
- metadata = self.metadata[:]
329
- metadata.append(('x-request-id', request_id)) # Set a Request ID
330
- self.print_debug(f'Sending crypto data for decoration (rqId: {request_id})...')
331
- resp = self.crypto_stub.GetAlgorithms(request, metadata=metadata, timeout=self.timeout)
332
- except Exception as e:
333
- self.print_stderr(
334
- f'ERROR: {e.__class__.__name__} Problem encountered sending gRPC message (rqId: {request_id}): {e}'
335
- )
336
- else:
337
- if resp:
338
- if not self._check_status_response(resp.status, request_id):
339
- return None
340
- resp_dict = MessageToDict(resp, preserving_proto_field_name=True) # Convert gRPC response to a dict
341
- del resp_dict['status']
342
- return resp_dict
343
- return None
344
-
345
314
  def get_vulnerabilities_json(self, purls: dict) -> dict:
346
315
  """
347
316
  Client function to call the rpc for Vulnerability GetVulnerabilities
@@ -462,7 +431,7 @@ class ScanossGrpc(ScanossBase):
462
431
  return resp_dict
463
432
  return None
464
433
 
465
- def folder_hash_scan(self, request: Dict) -> Dict:
434
+ def folder_hash_scan(self, request: Dict) -> Optional[Dict]:
466
435
  """
467
436
  Client function to call the rpc for Folder Hashing Scan
468
437
 
@@ -470,7 +439,7 @@ class ScanossGrpc(ScanossBase):
470
439
  request (Dict): Folder Hash Request
471
440
 
472
441
  Returns:
473
- Dict: Folder Hash Response
442
+ Optional[Dict]: Folder Hash Response, or None if the request was not succesfull
474
443
  """
475
444
  return self._call_rpc(
476
445
  self.scanning_stub.FolderHashScan,
@@ -479,7 +448,7 @@ class ScanossGrpc(ScanossBase):
479
448
  'Sending folder hash scan data (rqId: {rqId})...',
480
449
  )
481
450
 
482
- def _call_rpc(self, rpc_method, request_input, request_type, debug_msg: Optional[str] = None) -> dict:
451
+ def _call_rpc(self, rpc_method, request_input, request_type, debug_msg: Optional[str] = None) -> Optional[Dict]:
483
452
  """
484
453
  Call a gRPC method and return the response as a dictionary
485
454
 
@@ -490,9 +459,8 @@ class ScanossGrpc(ScanossBase):
490
459
  debug_msg (str, optional): Debug message template that can include {rqId} placeholder.
491
460
 
492
461
  Returns:
493
- dict: The parsed gRPC response as a dictionary, or None if an error occurred.
462
+ dict: The parsed gRPC response as a dictionary, or None if something went wrong
494
463
  """
495
-
496
464
  request_id = str(uuid.uuid4())
497
465
 
498
466
  if isinstance(request_input, dict):
@@ -503,7 +471,6 @@ class ScanossGrpc(ScanossBase):
503
471
  metadata = self.metadata[:] + [('x-request-id', request_id)]
504
472
 
505
473
  self.print_debug(debug_msg.format(rqId=request_id))
506
-
507
474
  try:
508
475
  resp = rpc_method(request_obj, metadata=metadata, timeout=self.timeout)
509
476
  except grpc.RpcError as e:
@@ -512,10 +479,9 @@ class ScanossGrpc(ScanossBase):
512
479
  )
513
480
 
514
481
  if resp and not self._check_status_response(resp.status, request_id):
515
- raise ScanossGrpcError(f'Unsuccessful status response (rqId: {request_id}).')
482
+ return None
516
483
 
517
484
  resp_dict = MessageToDict(resp, preserving_proto_field_name=True)
518
- resp_dict.pop('status', None)
519
485
  return resp_dict
520
486
 
521
487
  def _check_status_response(self, status_response: StatusResponse, request_id: str = None) -> bool:
@@ -574,13 +540,13 @@ class ScanossGrpc(ScanossBase):
574
540
  self.print_stderr('ERROR: No message supplied to send to gRPC service.')
575
541
  return None
576
542
  request_id = str(uuid.uuid4())
577
- resp: ProvenanceResponse
543
+ resp: ContributorResponse
578
544
  try:
579
545
  request = ParseDict(purls, PurlRequest()) # Parse the JSON/Dict into the purl request object
580
546
  metadata = self.metadata[:]
581
547
  metadata.append(('x-request-id', request_id)) # Set a Request ID
582
548
  self.print_debug(f'Sending data for provenance decoration (rqId: {request_id})...')
583
- resp = self.provenance_stub.GetComponentProvenance(request, metadata=metadata, timeout=self.timeout)
549
+ resp = self.provenance_stub.GetComponentContributors(request, metadata=metadata, timeout=self.timeout)
584
550
  except Exception as e:
585
551
  self.print_stderr(
586
552
  f'ERROR: {e.__class__.__name__} Problem encountered sending gRPC message (rqId: {request_id}): {e}'
@@ -593,6 +559,108 @@ class ScanossGrpc(ScanossBase):
593
559
  return resp_dict
594
560
  return None
595
561
 
562
+ def get_provenance_origin(self, request: Dict) -> Optional[Dict]:
563
+ """
564
+ Client function to call the rpc for GetComponentOrigin
565
+
566
+ Args:
567
+ request (Dict): GetComponentOrigin Request
568
+
569
+ Returns:
570
+ Optional[Dict]: OriginResponse, or None if the request was not successfull
571
+ """
572
+ return self._call_rpc(
573
+ self.provenance_stub.GetComponentOrigin,
574
+ request,
575
+ PurlRequest,
576
+ 'Sending data for provenance origin decoration (rqId: {rqId})...',
577
+ )
578
+
579
+ def get_crypto_algorithms_for_purl(self, request: Dict) -> Optional[Dict]:
580
+ """
581
+ Client function to call the rpc for GetAlgorithms for a list of purls
582
+
583
+ Args:
584
+ request (Dict): PurlRequest
585
+
586
+ Returns:
587
+ Optional[Dict]: AlgorithmResponse, or None if the request was not successfull
588
+ """
589
+ return self._call_rpc(
590
+ self.crypto_stub.GetAlgorithms,
591
+ request,
592
+ PurlRequest,
593
+ 'Sending data for cryptographic algorithms decoration (rqId: {rqId})...',
594
+ )
595
+
596
+ def get_crypto_algorithms_in_range_for_purl(self, request: Dict) -> Optional[Dict]:
597
+ """
598
+ Client function to call the rpc for GetAlgorithmsInRange for a list of purls
599
+
600
+ Args:
601
+ request (Dict): PurlRequest
602
+
603
+ Returns:
604
+ Optional[Dict]: AlgorithmsInRangeResponse, or None if the request was not successfull
605
+ """
606
+ return self._call_rpc(
607
+ self.crypto_stub.GetAlgorithmsInRange,
608
+ request,
609
+ PurlRequest,
610
+ 'Sending data for cryptographic algorithms in range decoration (rqId: {rqId})...',
611
+ )
612
+
613
+ def get_encryption_hints_for_purl(self, request: Dict) -> Optional[Dict]:
614
+ """
615
+ Client function to call the rpc for GetEncryptionHints for a list of purls
616
+
617
+ Args:
618
+ request (Dict): PurlRequest
619
+
620
+ Returns:
621
+ Optional[Dict]: HintsResponse, or None if the request was not successfull
622
+ """
623
+ return self._call_rpc(
624
+ self.crypto_stub.GetEncryptionHints,
625
+ request,
626
+ PurlRequest,
627
+ 'Sending data for encryption hints decoration (rqId: {rqId})...',
628
+ )
629
+
630
+ def get_encryption_hints_in_range_for_purl(self, request: Dict) -> Optional[Dict]:
631
+ """
632
+ Client function to call the rpc for GetHintsInRange for a list of purls
633
+
634
+ Args:
635
+ request (Dict): PurlRequest
636
+
637
+ Returns:
638
+ Optional[Dict]: HintsInRangeResponse, or None if the request was not successfull
639
+ """
640
+ return self._call_rpc(
641
+ self.crypto_stub.GetHintsInRange,
642
+ request,
643
+ PurlRequest,
644
+ 'Sending data for encryption hints in range decoration (rqId: {rqId})...',
645
+ )
646
+
647
+ def get_versions_in_range_for_purl(self, request: Dict) -> Optional[Dict]:
648
+ """
649
+ Client function to call the rpc for GetVersionsInRange for a list of purls
650
+
651
+ Args:
652
+ request (Dict): PurlRequest
653
+
654
+ Returns:
655
+ Optional[Dict]: VersionsInRangeResponse, or None if the request was not successfull
656
+ """
657
+ return self._call_rpc(
658
+ self.crypto_stub.GetVersionsInRange,
659
+ request,
660
+ PurlRequest,
661
+ 'Sending data for cryptographic versions in range decoration (rqId: {rqId})...',
662
+ )
663
+
596
664
  def load_generic_headers(self):
597
665
  """
598
666
  Adds custom headers from req_headers to metadata.
@@ -623,10 +691,11 @@ class GrpcConfig:
623
691
  quiet: Optional[bool] = False
624
692
  ver_details: Optional[str] = None
625
693
  ca_cert: Optional[str] = None
626
- pac: Optional[PACFile] = None
627
694
  timeout: Optional[int] = DEFAULT_TIMEOUT
628
695
  proxy: Optional[str] = None
629
696
  grpc_proxy: Optional[str] = None
697
+ pac: Optional[PACFile] = None
698
+ req_headers: Optional[dict] = None
630
699
 
631
700
 
632
701
  def create_grpc_config_from_args(args) -> GrpcConfig:
@@ -638,7 +707,6 @@ def create_grpc_config_from_args(args) -> GrpcConfig:
638
707
  quiet=getattr(args, 'quiet', False),
639
708
  ver_details=getattr(args, 'ver_details', None),
640
709
  ca_cert=getattr(args, 'ca_cert', None),
641
- pac=getattr(args, 'pac', None),
642
710
  timeout=getattr(args, 'timeout', DEFAULT_TIMEOUT),
643
711
  proxy=getattr(args, 'proxy', None),
644
712
  grpc_proxy=getattr(args, 'grpc_proxy', None),
scanoss/utils/file.py CHANGED
@@ -49,8 +49,8 @@ def validate_json_file(json_file_path: str) -> JsonValidation:
49
49
  json_file_path (str): The JSON file to validate
50
50
 
51
51
  Returns:
52
- Tuple[bool, str]: A tuple containing a boolean indicating if the file is valid and a message
53
- """
52
+ JsonValidation: A JsonValidation object containing a boolean indicating if the file is valid, the data, error, and error code
53
+ """ # noqa: E501
54
54
  if not json_file_path:
55
55
  return JsonValidation(is_valid=False, error='No JSON file specified')
56
56
  if not os.path.isfile(json_file_path):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: scanoss
3
- Version: 1.22.0
3
+ Version: 1.24.0
4
4
  Summary: Simple Python library to leverage the SCANOSS APIs
5
5
  Home-page: https://scanoss.com
6
6
  Author: SCANOSS
@@ -4,10 +4,11 @@ protoc_gen_swagger/options/annotations_pb2.py,sha256=b25EDD6gssUWnFby9gxgcpLIROT
4
4
  protoc_gen_swagger/options/annotations_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
5
5
  protoc_gen_swagger/options/openapiv2_pb2.py,sha256=vYElGp8E1vGHszvWqX97zNG9GFJ7u2QcdK9ouq0XdyI,14939
6
6
  protoc_gen_swagger/options/openapiv2_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
7
- scanoss/__init__.py,sha256=N6D9URr6AdSmpvYx7VJ2j8mViBMjK2aGLjn-kekJ2Sg,1146
8
- scanoss/cli.py,sha256=StXsVdi4ti2cY7Y_KvpE7IHDNNoWkiOys10UnXJl770,63497
9
- scanoss/components.py,sha256=pXzF892dDKRagVi2LM3FsQ0U6rciQ-7-5HCDMvfMKhU,14078
10
- scanoss/constants.py,sha256=9cJxbaXMP4GUIMVn0O1eEyT7Qfq4Jl6BWgZsYQqxQ20,293
7
+ scanoss/__init__.py,sha256=eyFaTBLEaia158sB-9Qg2uEmdiJFZKEB4ow7f4e5wVw,1146
8
+ scanoss/cli.py,sha256=SAB0xuHjEEw20YtYAPSZwrQaVf4JUsm8NRcVArMzd4U,69099
9
+ scanoss/components.py,sha256=b0R9DdKuXqyQiw5nZZwjQ6NJXBr1U9gyx1RI2FP9ozA,14511
10
+ scanoss/constants.py,sha256=FWCZG8gQputKwV7XwvW1GuwDXL4wDLQyVRGdwygg578,320
11
+ scanoss/cryptography.py,sha256=Q39MOCscP-OFvrnPXaPOMFFkc8OKnf3mC3SgZYEtCog,9407
11
12
  scanoss/csvoutput.py,sha256=qNKRwcChSkgIwLm00kZiVX6iHVQUF4Apl-sMbzJ5Taw,10192
12
13
  scanoss/cyclonedx.py,sha256=UktDuqZUbXSggdt864Pg8ziTD7sdEQtLxfYL7vd_ZCE,12756
13
14
  scanoss/file_filters.py,sha256=_1Ehb_rLnHw_-6N5Zhh4Es2lz6rlx0LozGPn-u52cok,20338
@@ -18,7 +19,7 @@ scanoss/scanner.py,sha256=ZL8I8KtVyXgUMcl7Ccbip_Q1IlU9WTgI-mFtSpF1JWw,45223
18
19
  scanoss/scanoss_settings.py,sha256=393JnWLsEZhvMg5tPUGgxmqnBKp8AcLxYsDRbLP7aV4,10650
19
20
  scanoss/scanossapi.py,sha256=v4D9i9Impa82Enw-5hZ7KLlscDIpaILNbGOMj3MJXqs,13067
20
21
  scanoss/scanossbase.py,sha256=Dkpwxa8NH8XN1iRl03NM_Mkvby0JQ4qfvCiiUrJ5ul0,3163
21
- scanoss/scanossgrpc.py,sha256=BZ6-JXmOigm0agvWp_rIoM1vkNN1K3yhcrjiNx6EO28,28075
22
+ scanoss/scanossgrpc.py,sha256=B0rl676-B-ZxqXRp7blXnqbAGPC5rqLAQHG28NoC32E,30004
22
23
  scanoss/scanpostprocessor.py,sha256=-JsThlxrU70r92GHykTMERnicdd-6jmwNsE4PH0MN2o,11063
23
24
  scanoss/scantype.py,sha256=gFmyVmKQpHWogN2iCmMj032e_sZo4T92xS3_EH5B3Tc,1310
24
25
  scanoss/spdxlite.py,sha256=MQqFgQhIO-yrbRwEAQS77HmRgP5GDxff-2JYLVoceA0,28946
@@ -40,10 +41,10 @@ scanoss/api/dependencies/__init__.py,sha256=hx-P78xbDsh6WQIigewkJ7Y7y1fqc_eYnyHC
40
41
  scanoss/api/dependencies/v2/__init__.py,sha256=hx-P78xbDsh6WQIigewkJ7Y7y1fqc_eYnyHC5IZTKmo,1122
41
42
  scanoss/api/dependencies/v2/scanoss_dependencies_pb2.py,sha256=4zG2dIiQnNcicg84WcJPPBqLK5QaOKQjkz49hXRTRkw,6501
42
43
  scanoss/api/dependencies/v2/scanoss_dependencies_pb2_grpc.py,sha256=8KjaWuOT5rygIMe2oWTmyZND3Ugt7K3g94K7a1Mbwcs,6875
43
- scanoss/api/provenance/__init__.py,sha256=KlDD87JmyZP-10T-fuJo0_v2zt1gxWfTgs70wjky9xg,1139
44
- scanoss/api/provenance/v2/__init__.py,sha256=KlDD87JmyZP-10T-fuJo0_v2zt1gxWfTgs70wjky9xg,1139
45
- scanoss/api/provenance/v2/scanoss_provenance_pb2.py,sha256=ItIz2iyDpmNgurKQAtcG4_IoF9snv9Z2H6X7Uv9y8_8,4199
46
- scanoss/api/provenance/v2/scanoss_provenance_pb2_grpc.py,sha256=WdiNTDe1Xo0XBn0XVNHLrzEfHX99Xxo9fdVzvC0oQ5w,4799
44
+ scanoss/api/geoprovenance/__init__.py,sha256=KlDD87JmyZP-10T-fuJo0_v2zt1gxWfTgs70wjky9xg,1139
45
+ scanoss/api/geoprovenance/v2/__init__.py,sha256=KlDD87JmyZP-10T-fuJo0_v2zt1gxWfTgs70wjky9xg,1139
46
+ scanoss/api/geoprovenance/v2/scanoss_geoprovenance_pb2.py,sha256=Z4k9qvU2klesnPRW9DRV6Lq79GT2XJSxYHKpSm3s1HA,5403
47
+ scanoss/api/geoprovenance/v2/scanoss_geoprovenance_pb2_grpc.py,sha256=B6sv2Taagt05CMWaw7T6silg7PW8E6xQVbqn_4-v14U,6854
47
48
  scanoss/api/scanning/__init__.py,sha256=hx-P78xbDsh6WQIigewkJ7Y7y1fqc_eYnyHC5IZTKmo,1122
48
49
  scanoss/api/scanning/v2/__init__.py,sha256=hx-P78xbDsh6WQIigewkJ7Y7y1fqc_eYnyHC5IZTKmo,1122
49
50
  scanoss/api/scanning/v2/scanoss_scanning_pb2.py,sha256=rHScTNN5_jsgLu_y3UIPTjeBX74GUw0kyjA-IMoz7mQ,4324
@@ -56,7 +57,7 @@ scanoss/api/vulnerabilities/__init__.py,sha256=IFrDk_DTJgKSZmmU-nuLXuq_s8sQZlrSC
56
57
  scanoss/api/vulnerabilities/v2/__init__.py,sha256=IFrDk_DTJgKSZmmU-nuLXuq_s8sQZlrSCHhIDMJT4r0,1122
57
58
  scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2.py,sha256=CFhF80av8tenGvn9AIsGEtRJPuV2dC_syA5JLZb2lDw,5464
58
59
  scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2_grpc.py,sha256=HlS4k4Zmx6RIAqaO9I96jD-eyF5yU6Xx04pVm7pdqOg,6864
59
- scanoss/data/build_date.txt,sha256=GqrDjXg6xymtFEJevLsewXnvrdsXhzDh27Sv0aQl75U,40
60
+ scanoss/data/build_date.txt,sha256=PDQnZE2-WtpYAXPgkmN0EbClN0u6qP3jO1XlbqtFxSk,40
60
61
  scanoss/data/scanoss-settings-schema.json,sha256=ClkRYAkjAN0Sk704G8BE_Ok006oQ6YnIGmX84CF8h9w,8798
61
62
  scanoss/data/spdx-exceptions.json,sha256=s7UTYxC7jqQXr11YBlIWYCNwN6lRDFTR33Y8rpN_dA4,17953
62
63
  scanoss/data/spdx-licenses.json,sha256=A6Z0q82gaTLtnopBfzeIVZjJFxkdRW1g2TuumQc-lII,228794
@@ -69,15 +70,15 @@ scanoss/scanners/__init__.py,sha256=D4C0lWLuNp8k_BjQZEc07WZcUgAvriVwQWOk063b0ZU,
69
70
  scanoss/scanners/container_scanner.py,sha256=leP4roes6B9B95F49mJ0P_F8WcKCQkvJgk9azWyJrjg,16294
70
71
  scanoss/scanners/folder_hasher.py,sha256=ePWinOTN3neSVz7T81TAF7GZVAGNYGJ8SfhM5LBYWb8,9824
71
72
  scanoss/scanners/scanner_config.py,sha256=egG7cw3S2akU-D9M1aLE5jLrfz_c8e7_DIotMnnpM84,2601
72
- scanoss/scanners/scanner_hfh.py,sha256=7w4WwNtjqBcZmu5ujmNkz1ejpGwO1s_XZbYBH2BsO9k,5773
73
+ scanoss/scanners/scanner_hfh.py,sha256=KksrC1XnOv7mXSlGyo_AJXwtPfKjqffkttdPoNDc-AQ,5802
73
74
  scanoss/utils/__init__.py,sha256=0hjb5ktavp7utJzFhGMPImPaZiHWgilM2HwvTp5lXJE,1122
74
75
  scanoss/utils/abstract_presenter.py,sha256=teiDTxBj5jBMCk2T8i4l1BJPf_u4zBLWrtCTFHSSECM,3148
75
76
  scanoss/utils/crc64.py,sha256=TMrwQimSdE6imhFOUL7oAG6Kxu-8qMpGWMuMg8QpSVs,3169
76
- scanoss/utils/file.py,sha256=yVyv7C7xLWtFNfUrv3r6W8tkIqEuPjZ7_mgIT01IjJs,2933
77
+ scanoss/utils/file.py,sha256=62cA9a17TU9ZvfA3FY5HY4-QOajJeSrc8S6xLA_f-3M,2980
77
78
  scanoss/utils/simhash.py,sha256=6iu8DOcecPAY36SZjCOzrrLMT9oIE7-gI6QuYwUQ7B0,5793
78
- scanoss-1.22.0.dist-info/licenses/LICENSE,sha256=LLUaXoiyOroIbr5ubAyrxBOwSRLTm35ETO2FmLpy8QQ,1074
79
- scanoss-1.22.0.dist-info/METADATA,sha256=vA4ujKiW-TKlanQrlQa_V30a6FsxHgfs3g_YL28kSF8,6060
80
- scanoss-1.22.0.dist-info/WHEEL,sha256=pxyMxgL8-pra_rKaQ4drOZAegBVuX-G_4nRHjjgWbmo,91
81
- scanoss-1.22.0.dist-info/entry_points.txt,sha256=Uy28xnaDL5KQ7V77sZD5VLDXPNxYYzSr5tsqtiXVzAs,48
82
- scanoss-1.22.0.dist-info/top_level.txt,sha256=V11PrQ6Pnrc-nDF9xnisnJ8e6-i7HqSIKVNqduRWcL8,27
83
- scanoss-1.22.0.dist-info/RECORD,,
79
+ scanoss-1.24.0.dist-info/licenses/LICENSE,sha256=LLUaXoiyOroIbr5ubAyrxBOwSRLTm35ETO2FmLpy8QQ,1074
80
+ scanoss-1.24.0.dist-info/METADATA,sha256=wQSSRp3ABZrmz68RkCS802sgrqTAylb9XzXmMGt_7TI,6060
81
+ scanoss-1.24.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
82
+ scanoss-1.24.0.dist-info/entry_points.txt,sha256=Uy28xnaDL5KQ7V77sZD5VLDXPNxYYzSr5tsqtiXVzAs,48
83
+ scanoss-1.24.0.dist-info/top_level.txt,sha256=V11PrQ6Pnrc-nDF9xnisnJ8e6-i7HqSIKVNqduRWcL8,27
84
+ scanoss-1.24.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (79.0.0)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5