scanoss 1.18.0__py3-none-any.whl → 1.19.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.
@@ -26,7 +26,13 @@ import json
26
26
  from pathlib import Path
27
27
  from typing import List, TypedDict
28
28
 
29
+ import importlib_resources
30
+ from jsonschema import validate
31
+
29
32
  from .scanossbase import ScanossBase
33
+ from .utils.file import validate_json_file
34
+
35
+ DEFAULT_SCANOSS_JSON_FILE = 'scanoss.json'
30
36
 
31
37
 
32
38
  class BomEntry(TypedDict, total=False):
@@ -34,15 +40,46 @@ class BomEntry(TypedDict, total=False):
34
40
  path: str
35
41
 
36
42
 
43
+ class SizeFilter(TypedDict, total=False):
44
+ patterns: List[str]
45
+ min: int
46
+ max: int
47
+
48
+
49
+ class ScanossSettingsError(Exception):
50
+ pass
51
+
52
+
53
+ def _load_settings_schema() -> dict:
54
+ """
55
+ Load the SCANOSS settings schema from a JSON file.
56
+
57
+ Returns:
58
+ dict: The parsed JSON content of the SCANOSS settings schema.
59
+
60
+ Raises:
61
+ ScanossSettingsError: If there is any issue in locating, reading, or parsing the JSON file
62
+ """
63
+ try:
64
+ schema_path = importlib_resources.files(__name__) / 'data' / 'scanoss-settings-schema.json'
65
+ with importlib_resources.as_file(schema_path) as f:
66
+ with open(f, 'r', encoding='utf-8') as file:
67
+ return json.load(file)
68
+ except Exception as e:
69
+ raise ScanossSettingsError(f'ERROR: Problem parsing Scanoss Settings Schema JSON file: {e}') from e
70
+
71
+
37
72
  class ScanossSettings(ScanossBase):
38
- """Handles the loading and parsing of the SCANOSS settings file"""
73
+ """
74
+ Handles the loading and parsing of the SCANOSS settings file
75
+ """
39
76
 
40
77
  def __init__(
41
78
  self,
42
79
  debug: bool = False,
43
80
  trace: bool = False,
44
81
  quiet: bool = False,
45
- filepath: str = None,
82
+ filepath: 'str | None' = None,
46
83
  ):
47
84
  """
48
85
  Args:
@@ -51,38 +88,44 @@ class ScanossSettings(ScanossBase):
51
88
  quiet (bool, optional): Quiet. Defaults to False.
52
89
  filepath (str, optional): Path to settings file. Defaults to None.
53
90
  """
54
-
55
91
  super().__init__(debug, trace, quiet)
56
92
  self.data = {}
57
93
  self.settings_file_type = None
58
94
  self.scan_type = None
59
-
95
+ self.schema = _load_settings_schema()
60
96
  if filepath:
61
97
  self.load_json_file(filepath)
62
98
 
63
- def load_json_file(self, filepath: str):
64
- """Load the scan settings file
99
+ def load_json_file(self, filepath: 'str | None' = None) -> 'ScanossSettings':
100
+ """
101
+ Load the scan settings file. If no filepath is provided, scanoss.json will be used as default.
65
102
 
66
103
  Args:
67
104
  filepath (str): Path to the SCANOSS settings file
68
105
  """
106
+ if not filepath:
107
+ filepath = DEFAULT_SCANOSS_JSON_FILE
69
108
  json_file = Path(filepath).resolve()
70
109
 
71
- if not json_file.exists():
72
- self.print_stderr(f'Scan settings file not found: {filepath}')
73
- self.data = {}
74
-
75
- with open(json_file, 'r') as jsonfile:
76
- self.print_debug(f'Loading scan settings from: {filepath}')
77
- try:
78
- self.data = json.load(jsonfile)
79
- except Exception as e:
80
- self.print_stderr(f'ERROR: Problem parsing input JSON: {e}')
110
+ if filepath == DEFAULT_SCANOSS_JSON_FILE and not json_file.exists():
111
+ self.print_debug(f'Default settings file "{filepath}" not found. Skipping...')
112
+ return self
113
+ self.print_msg(f'Loading settings file {filepath}...')
114
+
115
+ result = validate_json_file(json_file)
116
+ if not result.is_valid:
117
+ raise ScanossSettingsError(f'Problem with settings file. {result.error}')
118
+ try:
119
+ validate(result.data, self.schema)
120
+ except Exception as e:
121
+ raise ScanossSettingsError(f'Invalid settings file. {e}') from e
122
+ self.data = result.data
123
+ self.print_debug(f'Loading scan settings from: {filepath}')
81
124
  return self
82
125
 
83
126
  def set_file_type(self, file_type: str):
84
- """Set the file type in order to support both legacy SBOM.json and new scanoss.json files
85
-
127
+ """
128
+ Set the file type in order to support both legacy SBOM.json and new scanoss.json files
86
129
  Args:
87
130
  file_type (str): 'legacy' or 'new'
88
131
 
@@ -95,8 +138,8 @@ class ScanossSettings(ScanossBase):
95
138
  return self
96
139
 
97
140
  def set_scan_type(self, scan_type: str):
98
- """Set the scan type to support legacy SBOM.json files
99
-
141
+ """
142
+ Set the scan type to support legacy SBOM.json files
100
143
  Args:
101
144
  scan_type (str): 'identify' or 'exclude'
102
145
  """
@@ -104,8 +147,8 @@ class ScanossSettings(ScanossBase):
104
147
  return self
105
148
 
106
149
  def _is_valid_sbom_file(self):
107
- """Check if the scan settings file is valid
108
-
150
+ """
151
+ Check if the scan settings file is valid
109
152
  Returns:
110
153
  bool: True if the file is valid, False otherwise
111
154
  """
@@ -114,8 +157,8 @@ class ScanossSettings(ScanossBase):
114
157
  return True
115
158
 
116
159
  def _get_bom(self):
117
- """Get the Billing of Materials from the settings file
118
-
160
+ """
161
+ Get the Billing of Materials from the settings file
119
162
  Returns:
120
163
  dict: If using scanoss.json
121
164
  list: If using SBOM.json
@@ -130,8 +173,8 @@ class ScanossSettings(ScanossBase):
130
173
  return self.data.get('bom', {})
131
174
 
132
175
  def get_bom_include(self) -> List[BomEntry]:
133
- """Get the list of components to include in the scan
134
-
176
+ """
177
+ Get the list of components to include in the scan
135
178
  Returns:
136
179
  list: List of components to include in the scan
137
180
  """
@@ -140,8 +183,8 @@ class ScanossSettings(ScanossBase):
140
183
  return self._get_bom().get('include', [])
141
184
 
142
185
  def get_bom_remove(self) -> List[BomEntry]:
143
- """Get the list of components to remove from the scan
144
-
186
+ """
187
+ Get the list of components to remove from the scan
145
188
  Returns:
146
189
  list: List of components to remove from the scan
147
190
  """
@@ -150,8 +193,8 @@ class ScanossSettings(ScanossBase):
150
193
  return self._get_bom().get('remove', [])
151
194
 
152
195
  def get_bom_replace(self) -> List[BomEntry]:
153
- """Get the list of components to replace in the scan
154
-
196
+ """
197
+ Get the list of components to replace in the scan
155
198
  Returns:
156
199
  list: List of components to replace in the scan
157
200
  """
@@ -160,8 +203,8 @@ class ScanossSettings(ScanossBase):
160
203
  return self._get_bom().get('replace', [])
161
204
 
162
205
  def get_sbom(self):
163
- """Get the SBOM to be sent to the SCANOSS API
164
-
206
+ """
207
+ Get the SBOM to be sent to the SCANOSS API
165
208
  Returns:
166
209
  dict: SBOM request payload
167
210
  """
@@ -173,8 +216,8 @@ class ScanossSettings(ScanossBase):
173
216
  }
174
217
 
175
218
  def _get_sbom_assets(self):
176
- """Get the SBOM assets
177
-
219
+ """
220
+ Get the SBOM assets
178
221
  Returns:
179
222
  List: List of SBOM assets
180
223
  """
@@ -191,11 +234,10 @@ class ScanossSettings(ScanossBase):
191
234
 
192
235
  @staticmethod
193
236
  def normalize_bom_entries(bom_entries) -> List[BomEntry]:
194
- """Normalize the BOM entries
195
-
237
+ """
238
+ Normalize the BOM entries
196
239
  Args:
197
240
  bom_entries (List[Dict]): List of BOM entries
198
-
199
241
  Returns:
200
242
  List: Normalized BOM entries
201
243
  """
@@ -210,11 +252,10 @@ class ScanossSettings(ScanossBase):
210
252
 
211
253
  @staticmethod
212
254
  def _remove_duplicates(bom_entries: List[BomEntry]) -> List[BomEntry]:
213
- """Remove duplicate BOM entries
214
-
255
+ """
256
+ Remove duplicate BOM entries
215
257
  Args:
216
258
  bom_entries (List[Dict]): List of BOM entries
217
-
218
259
  Returns:
219
260
  List: List of unique BOM entries
220
261
  """
@@ -226,3 +267,27 @@ class ScanossSettings(ScanossBase):
226
267
  already_added.add(entry_tuple)
227
268
  unique_entries.append(entry)
228
269
  return unique_entries
270
+
271
+ def is_legacy(self):
272
+ """Check if the settings file is legacy"""
273
+ return self.settings_file_type == 'legacy'
274
+
275
+ def get_skip_patterns(self, operation_type: str) -> List[str]:
276
+ """
277
+ Get the list of patterns to skip based on the operation type
278
+ Args:
279
+ operation_type (str): Operation type
280
+ Returns:
281
+ List: List of patterns to skip
282
+ """
283
+ return self.data.get('settings', {}).get('skip', {}).get('patterns', {}).get(operation_type, [])
284
+
285
+ def get_skip_sizes(self, operation_type: str) -> List[SizeFilter]:
286
+ """
287
+ Get the min and max sizes to skip based on the operation type
288
+ Args:
289
+ operation_type (str): Operation type
290
+ Returns:
291
+ List: Min and max sizes to skip
292
+ """
293
+ return self.data.get('settings', {}).get('skip', {}).get('sizes', {}).get(operation_type, [])
@@ -31,8 +31,52 @@ from .scanoss_settings import BomEntry, ScanossSettings
31
31
  from .scanossbase import ScanossBase
32
32
 
33
33
 
34
+ def _get_match_type_message(result_path: str, bom_entry: BomEntry, action: str) -> str:
35
+ """
36
+ Compose message based on match type
37
+
38
+ Args:
39
+ result_path (str): Path of the scan result
40
+ bom_entry (BomEntry): BOM entry to compare with
41
+ action (str): Post processing action being performed
42
+
43
+ Returns:
44
+ str: The message to be printed
45
+ """
46
+ if bom_entry.get('path') and bom_entry.get('purl'):
47
+ message = f"{action} '{result_path}'. Full match found."
48
+ elif bom_entry.get('purl'):
49
+ message = f"{action} '{result_path}'. Found PURL match."
50
+ else:
51
+ message = f"{action} '{result_path}'. Found path match."
52
+ return message
53
+
54
+
55
+ def _is_full_match(result_path: str, result_purls: List[str], bom_entry: BomEntry) -> bool:
56
+ """
57
+ Check if path and purl matches fully with the bom entry
58
+
59
+ Args:
60
+ result_path (str): Scan result path
61
+ result_purls (List[str]): Scan result purls
62
+ bom_entry (BomEntry): BOM entry to compare with
63
+
64
+ Returns:
65
+ bool: True if the path and purl match, False otherwise
66
+ """
67
+ if not result_purls:
68
+ return False
69
+ return bool(
70
+ (bom_entry.get('purl') and bom_entry.get('path'))
71
+ and (bom_entry.get('path') == result_path)
72
+ and (bom_entry.get('purl') in result_purls)
73
+ )
74
+
75
+
34
76
  class ScanPostProcessor(ScanossBase):
35
- """Handles post-processing of the scan results"""
77
+ """
78
+ Handles post-processing of the scan results
79
+ """
36
80
 
37
81
  def __init__(
38
82
  self,
@@ -76,21 +120,28 @@ class ScanPostProcessor(ScanossBase):
76
120
  self.component_info_map[purl] = result
77
121
 
78
122
  def post_process(self):
79
- """Post-process the scan results
123
+ """
124
+ Post-process the scan results
80
125
 
81
126
  Returns:
82
127
  dict: Processed results
83
128
  """
129
+ if self.scan_settings.is_legacy():
130
+ self.print_stderr(
131
+ 'Legacy settings file detected. Post-processing is not supported for legacy settings file.'
132
+ )
133
+ return self.results
84
134
  self._remove_dismissed_files()
85
135
  self._replace_purls()
86
136
  return self.results
87
137
 
88
138
  def _remove_dismissed_files(self):
89
- """Remove entries from the results based on files and/or purls specified in the SCANOSS settings file"""
139
+ """
140
+ Remove entries from the results based on files and/or purls specified in the SCANOSS settings file
141
+ """
90
142
  to_remove_entries = self.scan_settings.get_bom_remove()
91
143
  if not to_remove_entries:
92
144
  return
93
-
94
145
  self.results = {
95
146
  result_path: result
96
147
  for result_path, result in self.results.items()
@@ -98,7 +149,9 @@ class ScanPostProcessor(ScanossBase):
98
149
  }
99
150
 
100
151
  def _replace_purls(self):
101
- """Replace purls in the results based on the SCANOSS settings file"""
152
+ """
153
+ Replace purls in the results based on the SCANOSS settings file
154
+ """
102
155
  to_replace_entries = self.scan_settings.get_bom_replace()
103
156
  if not to_replace_entries:
104
157
  return
@@ -128,9 +181,9 @@ class ScanPostProcessor(ScanossBase):
128
181
  try:
129
182
  new_component = PackageURL.from_string(to_replace_with_purl).to_dict()
130
183
  new_component_url = purl2url.get_repo_url(to_replace_with_purl)
131
- except Exception:
184
+ except RuntimeError:
132
185
  self.print_stderr(
133
- f"Error while replacing: Invalid PURL '{to_replace_with_purl}' in settings file. Abort replacing."
186
+ f"ERROR: Issue while replacing: Invalid PURL '{to_replace_with_purl}' in settings file. Skipping."
134
187
  )
135
188
  return result
136
189
 
@@ -154,13 +207,13 @@ class ScanPostProcessor(ScanossBase):
154
207
 
155
208
  return result
156
209
 
157
- def _should_replace_result(
158
- self, result_path: str, result: dict, to_replace_entries: List[BomEntry]
159
- ) -> Tuple[bool, str]:
160
- """Check if a result should be replaced based on the SCANOSS settings
210
+ def _should_replace_result(self, result_path: str, result: dict, to_replace_entries: List[BomEntry]
211
+ ) -> Tuple[bool, str]:
212
+ """
213
+ Check if a result should be replaced based on the SCANOSS settings
161
214
 
162
215
  Args:
163
- result_path (str): Path of the result
216
+ result_path (str): Path of the result data
164
217
  result (dict): Result to check
165
218
  to_replace_entries (List[BomEntry]): BOM entries to replace from the settings file
166
219
 
@@ -176,9 +229,8 @@ class ScanPostProcessor(ScanossBase):
176
229
 
177
230
  if not to_replace_path and not to_replace_purl or not to_replace_with:
178
231
  continue
179
-
180
232
  if (
181
- self._is_full_match(result_path, result_purls, to_replace_entry)
233
+ _is_full_match(result_path, result_purls, to_replace_entry)
182
234
  or (not to_replace_path and to_replace_purl in result_purls)
183
235
  or (not to_replace_purl and to_replace_path == result_path)
184
236
  ):
@@ -188,7 +240,14 @@ class ScanPostProcessor(ScanossBase):
188
240
  return False, None
189
241
 
190
242
  def _should_remove_result(self, result_path: str, result: dict, to_remove_entries: List[BomEntry]) -> bool:
191
- """Check if a result should be removed based on the SCANOSS settings"""
243
+ """
244
+ Check if a result should be removed based on the SCANOSS settings
245
+
246
+ :param result_path: path of the result data
247
+ :param result: result to check
248
+ :param to_remove_entries: BOM entries to remove from the result
249
+ :return:
250
+ """
192
251
  result = result[0] if isinstance(result, list) else result
193
252
  result_purls = result.get('purl', [])
194
253
 
@@ -198,9 +257,8 @@ class ScanPostProcessor(ScanossBase):
198
257
 
199
258
  if not to_remove_path and not to_remove_purl:
200
259
  continue
201
-
202
260
  if (
203
- self._is_full_match(result_path, result_purls, to_remove_entry)
261
+ _is_full_match(result_path, result_purls, to_remove_entry)
204
262
  or (not to_remove_path and to_remove_purl in result_purls)
205
263
  or (not to_remove_purl and to_remove_path == result_path)
206
264
  ):
@@ -209,75 +267,25 @@ class ScanPostProcessor(ScanossBase):
209
267
 
210
268
  return False
211
269
 
212
- def _print_message(
213
- self,
214
- result_path: str,
215
- result_purls: List[str],
216
- bom_entry: BomEntry,
217
- action: str,
218
- ) -> None:
219
- """Print a message about replacing or removing a result"""
270
+ def _print_message(self, result_path: str, result_purls: List[str], bom_entry: BomEntry, action: str) -> None:
271
+ """
272
+ Print a message about replacing or removing a result
273
+
274
+ :param result_path:
275
+ :param result_purls:
276
+ :param bom_entry:
277
+ :param action:
278
+ :return:
279
+ """
220
280
  message = (
221
- f"{self._get_match_type_message(result_path, result_purls, bom_entry, action)} \n"
281
+ f"{_get_match_type_message(result_path, bom_entry, action)} \n"
222
282
  f"Details:\n"
223
283
  f" - PURLs: {', '.join(result_purls)}\n"
224
284
  f" - Path: '{result_path}'\n"
225
285
  )
226
-
227
286
  if action == 'Replacing':
228
287
  message += f" - {action} with '{bom_entry.get('replace_with')}'"
229
-
230
288
  self.print_debug(message)
231
-
232
- def _get_match_type_message(
233
- self,
234
- result_path: str,
235
- result_purls: List[str],
236
- bom_entry: BomEntry,
237
- action: str,
238
- ) -> str:
239
- """Compose message based on match type
240
-
241
- Args:
242
- result_path (str): Path of the scan result
243
- result_purls (List[str]): Purls of the scan result
244
- bom_entry (BomEntry): BOM entry to compare with
245
- action (str): Post processing action being performed
246
-
247
- Returns:
248
- str: The message to be printed
249
- """
250
- if bom_entry.get('path') and bom_entry.get('purl'):
251
- message = f"{action} '{result_path}'. Full match found."
252
- elif bom_entry.get('purl'):
253
- message = f"{action} '{result_path}'. Found PURL match."
254
- else:
255
- message = f"{action} '{result_path}'. Found path match."
256
-
257
- return message
258
-
259
- def _is_full_match(
260
- self,
261
- result_path: str,
262
- result_purls: List[str],
263
- bom_entry: BomEntry,
264
- ) -> bool:
265
- """Check if path and purl matches fully with the bom entry
266
-
267
- Args:
268
- result_path (str): Scan result path
269
- result_purls (List[str]): Scan result purls
270
- bom_entry (BomEntry): BOM entry to compare with
271
-
272
- Returns:
273
- bool: True if the path and purl match, False otherwise
274
- """
275
-
276
- if not result_purls:
277
- return False
278
-
279
- return bool(
280
- (bom_entry.get('purl') and bom_entry.get('path'))
281
- and (bom_entry.get('path') == result_path)
282
- and (bom_entry.get('purl') in result_purls)
283
- )
289
+ #
290
+ # End of ScanPostProcessor Class
291
+ #
@@ -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
+ """
scanoss/utils/file.py ADDED
@@ -0,0 +1,57 @@
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
+ import os
26
+ import sys
27
+ from dataclasses import dataclass
28
+ from typing import Optional
29
+
30
+
31
+ @dataclass
32
+ class JsonValidation:
33
+ is_valid: bool
34
+ data: Optional[dict] = None
35
+ error: Optional[str] = None
36
+
37
+
38
+ def validate_json_file(json_file_path: str) -> JsonValidation:
39
+ """
40
+ Validate if the specified file is indeed a valid JSON file
41
+
42
+ Args:
43
+ json_file_path (str): The JSON file to validate
44
+
45
+ Returns:
46
+ Tuple[bool, str]: A tuple containing a boolean indicating if the file is valid and a message
47
+ """
48
+ if not json_file_path:
49
+ return JsonValidation(is_valid=False, error='No JSON file specified')
50
+ if not os.path.isfile(json_file_path):
51
+ return JsonValidation(is_valid=False, error=f'File not found: {json_file_path}')
52
+ try:
53
+ with open(json_file_path) as f:
54
+ data = json.load(f)
55
+ return JsonValidation(is_valid=True, data=data)
56
+ except json.JSONDecodeError as e:
57
+ return JsonValidation(is_valid=False, error=f'Problem parsing JSON file: "{json_file_path}": {e}')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: scanoss
3
- Version: 1.18.0
3
+ Version: 1.19.0
4
4
  Summary: Simple Python library to leverage the SCANOSS APIs
5
5
  Home-page: https://scanoss.com
6
6
  Author: SCANOSS
@@ -25,10 +25,12 @@ Requires-Dist: protobuf>3.19.1
25
25
  Requires-Dist: pypac
26
26
  Requires-Dist: pyOpenSSL
27
27
  Requires-Dist: google-api-core
28
- Requires-Dist: importlib-resources
28
+ Requires-Dist: importlib_resources
29
29
  Requires-Dist: packageurl-python
30
- Provides-Extra: fast_winnowing
31
- Requires-Dist: scanoss-winnowing>=0.5.0; extra == "fast-winnowing"
30
+ Requires-Dist: pathspec
31
+ Requires-Dist: jsonschema
32
+ Provides-Extra: fast-winnowing
33
+ Requires-Dist: scanoss_winnowing>=0.5.0; extra == "fast-winnowing"
32
34
 
33
35
  # SCANOSS Python Package
34
36
  The SCANOSS python package provides a simple easy to consume library for interacting with SCANOSS APIs/Engine.
@@ -4,20 +4,21 @@ 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=_jYIWkrW2Ht4mXs71uxI_j5ZKtzLx-vmW5npONyA9g4,1163
8
- scanoss/cli.py,sha256=WS5Vqe0V59EBLyVl-l8PD-_RTCCUNIm2JdANk4X5DxI,50863
7
+ scanoss/__init__.py,sha256=QII--iMwPZhf6bpdwYDt75o9BhE45V7pn0t7vHxYOK4,1163
8
+ scanoss/cli.py,sha256=8uvO6VFDqGTw4ZLySr0xhS9KTm-gdwq9K3mYv_LdxW8,51498
9
9
  scanoss/components.py,sha256=ZHZ1KA69shxOASZK7USD9yPTITpAc_RXL5q5zpDK23o,12590
10
10
  scanoss/csvoutput.py,sha256=hBwr_Fc6mBdOdXgyQcdFrockYH-PJ0jblowlExJ6OPg,9925
11
- scanoss/cyclonedx.py,sha256=JVBYeR3D-i4yP9cVSyWvm0_7Y8Kr2MC5GxMgRGAf8R0,12585
11
+ scanoss/cyclonedx.py,sha256=ZbFNinMz_R68ko4-ZPo2w4bBORpASh271VCmYYRTUCg,12746
12
+ scanoss/file_filters.py,sha256=HGGECJ-P0LL8pg8YVO4BP8ql24tCnanx0_S2wA8EWis,16642
12
13
  scanoss/filecount.py,sha256=o7xb6m387ucnsU4H1OXGzf_AdWsudhAHe49T8uX4Ieo,6660
13
14
  scanoss/results.py,sha256=7G33QAYYI9qI61TCzXjSLYXMmg5CDtZS5e2QhnQfE74,9883
14
15
  scanoss/scancodedeps.py,sha256=_9d7MAV20-FrET7mF7gW-BZiz2eHrtwudgrEcSX0oZQ,11321
15
- scanoss/scanner.py,sha256=iHDDaM4gzhYJN1pxN5VEvnynvTn78zMHlZ6kGInbNoo,51861
16
- scanoss/scanoss_settings.py,sha256=zJO149YsLnjWOqxPlpdGQ1Q_gytQS1U6b29-y8qAMgI,7647
16
+ scanoss/scanner.py,sha256=hF8N8XXSwYw93htpqv0h0t-IqswG_bcxH7awe4JA5Aw,45374
17
+ scanoss/scanoss_settings.py,sha256=AJKMJeLoPVLO15vb9Pd12b5tVCa3ALP5sOXeWR6KCb0,10144
17
18
  scanoss/scanossapi.py,sha256=TJxPctr-0DTn_26LfM__OAMfntaXzvheFTbdmU-5pnM,11953
18
19
  scanoss/scanossbase.py,sha256=zMDRCLbrcoRvYEKQRuZXnBiVY4_Vsplmg_APbB65oaU,3084
19
20
  scanoss/scanossgrpc.py,sha256=ythZkr6F0P0hl_KPYoHkos_IL97TxLKeYfAouX_CUnM,20491
20
- scanoss/scanpostprocessor.py,sha256=mUnH12otH9s5pEqCa9jzrd_aWcNAOR4PngvPa6gZtkQ,10758
21
+ scanoss/scanpostprocessor.py,sha256=OY75PLUMRas7hyjrHTCKiu4X-N_Z5t710wc9f3HPHqw,11074
21
22
  scanoss/scantype.py,sha256=R2-ExLGOrYxaJFtIK2AEo2caD0XrN1zpF5q1qT9Zsyc,1326
22
23
  scanoss/spdxlite.py,sha256=REChAWV-6qhp16jc4X2lMb1v7VvYiDH5nN9VDV3fDaQ,15828
23
24
  scanoss/threadeddependencies.py,sha256=sOIAjiPTmxybKz2yhT4-ixXBeC4K8UQVq6JQj4e8mLc,9906
@@ -50,7 +51,8 @@ scanoss/api/vulnerabilities/__init__.py,sha256=FLQtiDiv85Q1Chk-sJ9ky9WOV1mulZhEK
50
51
  scanoss/api/vulnerabilities/v2/__init__.py,sha256=FLQtiDiv85Q1Chk-sJ9ky9WOV1mulZhEKjiBihlwiaM,1139
51
52
  scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2.py,sha256=CFhF80av8tenGvn9AIsGEtRJPuV2dC_syA5JLZb2lDw,5464
52
53
  scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2_grpc.py,sha256=HlS4k4Zmx6RIAqaO9I96jD-eyF5yU6Xx04pVm7pdqOg,6864
53
- scanoss/data/build_date.txt,sha256=9ipmjb7WYIgf6aLKZmxtGRKvpBBytZ1IpVIg0m7LQo8,40
54
+ scanoss/data/build_date.txt,sha256=EgEEayPVruney0IcvaC1mlb6hMwjLliofFDgvTJTtfI,40
55
+ scanoss/data/scanoss-settings-schema.json,sha256=ClkRYAkjAN0Sk704G8BE_Ok006oQ6YnIGmX84CF8h9w,8798
54
56
  scanoss/data/spdx-exceptions.json,sha256=s7UTYxC7jqQXr11YBlIWYCNwN6lRDFTR33Y8rpN_dA4,17953
55
57
  scanoss/data/spdx-licenses.json,sha256=A6Z0q82gaTLtnopBfzeIVZjJFxkdRW1g2TuumQc-lII,228794
56
58
  scanoss/inspection/__init__.py,sha256=z62680zKq4OmBOugSODvgpSwdsloZL7bvcaMbnx3xgU,1139
@@ -58,9 +60,11 @@ scanoss/inspection/copyleft.py,sha256=dkiLkgNYz7cbIQZCzy6zThiIyHkqrper_xruZ9PQhA
58
60
  scanoss/inspection/policy_check.py,sha256=eo5VfEBwKoDSqIwRi0xwaVLy6EUR29HlH5Bl0Kpvx7I,14752
59
61
  scanoss/inspection/undeclared_component.py,sha256=c2xwWyrPtQbdl0MgHTN_CpaJwC1PAofqyfYBSuWt_yI,7965
60
62
  scanoss/inspection/utils/license_utils.py,sha256=mIaoVWXMA6shkRQmgmiP2mWchjxX4ex8LWs91Nf6rq4,5093
61
- scanoss-1.18.0.dist-info/LICENSE,sha256=LLUaXoiyOroIbr5ubAyrxBOwSRLTm35ETO2FmLpy8QQ,1074
62
- scanoss-1.18.0.dist-info/METADATA,sha256=oFubkhmg7cK4UVpmVN5-kbd4KDe3CPPgtqtfSK8IJRc,5969
63
- scanoss-1.18.0.dist-info/WHEEL,sha256=R06PA3UVYHThwHvxuRWMqaGcr-PuniXahwjmQRFMEkY,91
64
- scanoss-1.18.0.dist-info/entry_points.txt,sha256=Uy28xnaDL5KQ7V77sZD5VLDXPNxYYzSr5tsqtiXVzAs,48
65
- scanoss-1.18.0.dist-info/top_level.txt,sha256=V11PrQ6Pnrc-nDF9xnisnJ8e6-i7HqSIKVNqduRWcL8,27
66
- scanoss-1.18.0.dist-info/RECORD,,
63
+ scanoss/utils/__init__.py,sha256=0hjb5ktavp7utJzFhGMPImPaZiHWgilM2HwvTp5lXJE,1122
64
+ scanoss/utils/file.py,sha256=W-XFLgaTM_td31Y5rzd5DimO4_qXafQhBtKtY_p3JIQ,2184
65
+ scanoss-1.19.0.dist-info/LICENSE,sha256=LLUaXoiyOroIbr5ubAyrxBOwSRLTm35ETO2FmLpy8QQ,1074
66
+ scanoss-1.19.0.dist-info/METADATA,sha256=ElWs851Eb75AWscKw-8hKuZ4V68DgkMCaW8cBZ_qmyM,6019
67
+ scanoss-1.19.0.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
68
+ scanoss-1.19.0.dist-info/entry_points.txt,sha256=Uy28xnaDL5KQ7V77sZD5VLDXPNxYYzSr5tsqtiXVzAs,48
69
+ scanoss-1.19.0.dist-info/top_level.txt,sha256=V11PrQ6Pnrc-nDF9xnisnJ8e6-i7HqSIKVNqduRWcL8,27
70
+ scanoss-1.19.0.dist-info/RECORD,,