fosslight-util 2.1.7__py3-none-any.whl → 2.1.18__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.
- fosslight_util/_get_downloadable_url.py +79 -8
- fosslight_util/constant.py +3 -1
- fosslight_util/correct.py +4 -6
- fosslight_util/download.py +46 -22
- fosslight_util/exclude.py +65 -0
- fosslight_util/help.py +8 -2
- fosslight_util/output_format.py +7 -3
- fosslight_util/set_log.py +8 -2
- fosslight_util/write_cyclonedx.py +8 -15
- fosslight_util/write_excel.py +5 -1
- fosslight_util/write_scancodejson.py +31 -14
- {fosslight_util-2.1.7.dist-info → fosslight_util-2.1.18.dist-info}/METADATA +1 -1
- fosslight_util-2.1.18.dist-info/RECORD +32 -0
- fosslight_util-2.1.7.dist-info/RECORD +0 -31
- {fosslight_util-2.1.7.dist-info → fosslight_util-2.1.18.dist-info}/LICENSE +0 -0
- {fosslight_util-2.1.7.dist-info → fosslight_util-2.1.18.dist-info}/WHEEL +0 -0
- {fosslight_util-2.1.7.dist-info → fosslight_util-2.1.18.dist-info}/entry_points.txt +0 -0
- {fosslight_util-2.1.7.dist-info → fosslight_util-2.1.18.dist-info}/top_level.txt +0 -0
|
@@ -27,7 +27,7 @@ def extract_name_version_from_link(link):
|
|
|
27
27
|
origin_name = match.group(1)
|
|
28
28
|
if (key == "pypi") or (key == "pypi2"):
|
|
29
29
|
oss_name = f"pypi:{origin_name}"
|
|
30
|
-
oss_name = re.sub(r"[-_.]+", "-", oss_name)
|
|
30
|
+
oss_name = re.sub(r"[-_.]+", "-", oss_name)
|
|
31
31
|
oss_version = match.group(2)
|
|
32
32
|
elif key == "maven":
|
|
33
33
|
artifact = match.group(2)
|
|
@@ -42,12 +42,20 @@ def extract_name_version_from_link(link):
|
|
|
42
42
|
oss_version = match.group(2)
|
|
43
43
|
elif key == "cocoapods":
|
|
44
44
|
oss_name = f"cocoapods:{origin_name}"
|
|
45
|
+
elif key == "go":
|
|
46
|
+
if origin_name.endswith('/'):
|
|
47
|
+
origin_name = origin_name[:-1]
|
|
48
|
+
oss_name = f"go:{origin_name}"
|
|
49
|
+
oss_version = match.group(2)
|
|
50
|
+
elif key == "cargo":
|
|
51
|
+
oss_name = f"cargo:{origin_name}"
|
|
52
|
+
oss_version = match.group(2)
|
|
45
53
|
except Exception as ex:
|
|
46
54
|
logger.info(f"extract_name_version_from_link {key}:{ex}")
|
|
47
55
|
if oss_name and (not oss_version):
|
|
48
|
-
if key in ["pypi", "maven", "npm", "npm2", "pub"]:
|
|
56
|
+
if key in ["pypi", "maven", "npm", "npm2", "pub", "go"]:
|
|
49
57
|
oss_version, link = get_latest_package_version(link, key, origin_name)
|
|
50
|
-
logger.
|
|
58
|
+
logger.info(f'Try to download with the latest version:{link}')
|
|
51
59
|
break
|
|
52
60
|
return oss_name, oss_version, link, key
|
|
53
61
|
|
|
@@ -76,8 +84,13 @@ def get_latest_package_version(link, pkg_type, oss_name):
|
|
|
76
84
|
if pub_response.status_code == 200:
|
|
77
85
|
find_version = pub_response.json().get('latest').get('version')
|
|
78
86
|
link_with_version = f'https://pub.dev/packages/{oss_name}/versions/{find_version}'
|
|
87
|
+
elif pkg_type == 'go':
|
|
88
|
+
go_response = requests.get(f'https://proxy.golang.org/{oss_name}/@latest')
|
|
89
|
+
if go_response.status_code == 200:
|
|
90
|
+
find_version = go_response.json().get('Version')
|
|
91
|
+
link_with_version = f'https://pkg.go.dev/{oss_name}@{find_version}'
|
|
79
92
|
except Exception as e:
|
|
80
|
-
logger.
|
|
93
|
+
logger.info(f'Fail to get latest package version({link}:{e})')
|
|
81
94
|
return find_version, link_with_version
|
|
82
95
|
|
|
83
96
|
|
|
@@ -98,8 +111,66 @@ def get_downloadable_url(link):
|
|
|
98
111
|
ret, result_link = get_download_location_for_npm(new_link)
|
|
99
112
|
elif pkg_type == "pub":
|
|
100
113
|
ret, result_link = get_download_location_for_pub(new_link)
|
|
114
|
+
elif pkg_type == "go":
|
|
115
|
+
ret, result_link = get_download_location_for_go(new_link)
|
|
116
|
+
elif pkg_type == "cargo":
|
|
117
|
+
ret, result_link = get_download_location_for_cargo(new_link)
|
|
118
|
+
return ret, result_link, oss_name, oss_version, pkg_type
|
|
101
119
|
|
|
102
|
-
|
|
120
|
+
|
|
121
|
+
def get_download_location_for_cargo(link):
|
|
122
|
+
# get the url for downloading source file: https://crates.io/api/v1/crates/<name>/<version>/download
|
|
123
|
+
ret = False
|
|
124
|
+
new_link = ''
|
|
125
|
+
host = 'https://crates.io/api/v1/crates'
|
|
126
|
+
|
|
127
|
+
try:
|
|
128
|
+
dn_loc_re = re.findall(r'crates.io\/crates\/([^\/]+)\/?([^\/]*)', link)
|
|
129
|
+
if dn_loc_re:
|
|
130
|
+
oss_name = dn_loc_re[0][0]
|
|
131
|
+
oss_version = dn_loc_re[0][1]
|
|
132
|
+
|
|
133
|
+
new_link = f'{host}/{oss_name}/{oss_version}/download'
|
|
134
|
+
res = urlopen(new_link)
|
|
135
|
+
if res.getcode() == 200:
|
|
136
|
+
ret = True
|
|
137
|
+
else:
|
|
138
|
+
logger.warning(f'Cannot find the valid link for cargo (url:{new_link}')
|
|
139
|
+
except Exception as error:
|
|
140
|
+
ret = False
|
|
141
|
+
logger.warning(f'Cannot find the link for cargo (url:{link}({(new_link)})): {error}')
|
|
142
|
+
|
|
143
|
+
return ret, new_link
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def get_download_location_for_go(link):
|
|
147
|
+
# get the url for downloading source file: https://proxy.golang.org/<module>/@v/VERSION.zip
|
|
148
|
+
ret = False
|
|
149
|
+
new_link = ''
|
|
150
|
+
host = 'https://proxy.golang.org'
|
|
151
|
+
|
|
152
|
+
try:
|
|
153
|
+
dn_loc_re = re.findall(r'pkg.go.dev\/([^\@]+)\@?([^\/]*)', link)
|
|
154
|
+
if dn_loc_re:
|
|
155
|
+
oss_name = dn_loc_re[0][0]
|
|
156
|
+
if oss_name.endswith('/'):
|
|
157
|
+
oss_name = oss_name[:-1]
|
|
158
|
+
oss_version = dn_loc_re[0][1]
|
|
159
|
+
|
|
160
|
+
new_link = f'{host}/{oss_name}/@v/{oss_version}.zip'
|
|
161
|
+
try:
|
|
162
|
+
res = urlopen(new_link)
|
|
163
|
+
if res.getcode() == 200:
|
|
164
|
+
ret = True
|
|
165
|
+
else:
|
|
166
|
+
logger.warning(f'Cannot find the valid link for go (url:{new_link}')
|
|
167
|
+
except Exception as e:
|
|
168
|
+
logger.warning(f'Fail to find the valid link for go (url:{new_link}: {e}')
|
|
169
|
+
except Exception as error:
|
|
170
|
+
ret = False
|
|
171
|
+
logger.warning(f'Cannot find the link for go (url:{link}({(new_link)})): {error}')
|
|
172
|
+
|
|
173
|
+
return ret, new_link
|
|
103
174
|
|
|
104
175
|
|
|
105
176
|
def get_download_location_for_pypi(link):
|
|
@@ -111,7 +182,7 @@ def get_download_location_for_pypi(link):
|
|
|
111
182
|
try:
|
|
112
183
|
dn_loc_re = re.findall(r'pypi.org\/project\/?([^\/]*)\/?([^\/]*)', link)
|
|
113
184
|
oss_name = dn_loc_re[0][0]
|
|
114
|
-
oss_name = re.sub(r"[-_.]+", "-", oss_name)
|
|
185
|
+
oss_name = re.sub(r"[-_.]+", "-", oss_name)
|
|
115
186
|
oss_version = dn_loc_re[0][1]
|
|
116
187
|
|
|
117
188
|
new_link = f'{host}/packages/source/{oss_name[0]}/{oss_name}/{oss_name}-{oss_version}.tar.gz'
|
|
@@ -121,8 +192,8 @@ def get_download_location_for_pypi(link):
|
|
|
121
192
|
ret = True
|
|
122
193
|
else:
|
|
123
194
|
logger.warning(f'Cannot find the valid link for pypi (url:{new_link}')
|
|
124
|
-
except Exception
|
|
125
|
-
oss_name = re.sub(r"[-]+", "_", oss_name)
|
|
195
|
+
except Exception:
|
|
196
|
+
oss_name = re.sub(r"[-]+", "_", oss_name)
|
|
126
197
|
new_link = f'{host}/packages/source/{oss_name[0]}/{oss_name}/{oss_name}-{oss_version}.tar.gz'
|
|
127
198
|
res = urlopen(new_link)
|
|
128
199
|
if res.getcode() == 200:
|
fosslight_util/constant.py
CHANGED
|
@@ -35,6 +35,7 @@ SHEET_NAME_FOR_SCANNER = {
|
|
|
35
35
|
# pub: https://pub.dev/packages/(package)/versions/(version)
|
|
36
36
|
# Cocoapods : https://cocoapods.org/(package)
|
|
37
37
|
# go : https://pkg.go.dev/(package_name_with_slash)@(version)
|
|
38
|
+
# cargo : https://crates.io/crates/(crate_name)/(version)
|
|
38
39
|
PKG_PATTERN = {
|
|
39
40
|
"pypi": r'https?:\/\/pypi\.org\/project\/([^\/]+)[\/]?([^\/]*)',
|
|
40
41
|
"pypi2": r'https?:\/\/files\.pythonhosted\.org\/packages\/source\/[\w]\/([^\/]+)\/[\S]+-([^\-]+)\.tar\.gz',
|
|
@@ -43,5 +44,6 @@ PKG_PATTERN = {
|
|
|
43
44
|
"npm2": r'https?:\/\/www\.npmjs\.com\/package\/(\@[^\/]+\/[^\/]+)(?:\/v\/)?([^\/]*)',
|
|
44
45
|
"pub": r'https?:\/\/pub\.dev\/packages\/([^\/]+)(?:\/versions\/)?([^\/]*)',
|
|
45
46
|
"cocoapods": r'https?:\/\/cocoapods\.org\/pods\/([^\/]+)',
|
|
46
|
-
"go": r'https?:\/\/pkg.go.dev\/([^\@]+)\@?v?([^\/]*)'
|
|
47
|
+
"go": r'https?:\/\/pkg.go.dev\/([^\@]+)\@?v?([^\/]*)',
|
|
48
|
+
"cargo": r'https?:\/\/crates\.io\/crates\/([^\/]+)\/?([^\/]*)',
|
|
47
49
|
}
|
fosslight_util/correct.py
CHANGED
|
@@ -61,17 +61,15 @@ def correct_with_yaml(correct_filepath, path_to_scan, scan_item):
|
|
|
61
61
|
|
|
62
62
|
yaml_path_exists = True
|
|
63
63
|
exclude_fileitems.append(idx)
|
|
64
|
-
|
|
65
|
-
if not yaml_path_exists:
|
|
64
|
+
if scanner_name == FOSSLIGHT_SOURCE and not yaml_path_exists:
|
|
66
65
|
correct_item = copy.deepcopy(yaml_file_item)
|
|
67
66
|
if os.path.exists(os.path.normpath(yaml_file_item.source_name_or_path)):
|
|
68
67
|
correct_item.comment = 'Loaded from sbom-info.yaml'
|
|
69
68
|
correct_fileitems.append(correct_item)
|
|
70
69
|
else:
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
correct_fileitems.append(correct_item)
|
|
70
|
+
correct_item.exclude = True
|
|
71
|
+
correct_item.comment = 'Added by sbom-info.yaml'
|
|
72
|
+
correct_fileitems.append(correct_item)
|
|
75
73
|
if correct_fileitems:
|
|
76
74
|
scan_item.append_file_items(correct_fileitems, scanner_name)
|
|
77
75
|
find_match = True
|
fosslight_util/download.py
CHANGED
|
@@ -26,6 +26,7 @@ import platform
|
|
|
26
26
|
import subprocess
|
|
27
27
|
import re
|
|
28
28
|
from typing import Tuple
|
|
29
|
+
import urllib.parse
|
|
29
30
|
|
|
30
31
|
logger = logging.getLogger(constant.LOGGER_NAME)
|
|
31
32
|
compression_extension = {".tar.bz2", ".tar.gz", ".tar.xz", ".tgz", ".tar", ".zip", ".jar", ".bz2"}
|
|
@@ -94,7 +95,8 @@ def parse_src_link(src_link):
|
|
|
94
95
|
|
|
95
96
|
def cli_download_and_extract(link: str, target_dir: str, log_dir: str, checkout_to: str = "",
|
|
96
97
|
compressed_only: bool = False, ssh_key: str = "",
|
|
97
|
-
id: str = "", git_token: str = ""
|
|
98
|
+
id: str = "", git_token: str = "",
|
|
99
|
+
called_cli: bool = True) -> Tuple[bool, str, str, str]:
|
|
98
100
|
global logger
|
|
99
101
|
|
|
100
102
|
success = True
|
|
@@ -123,8 +125,11 @@ def cli_download_and_extract(link: str, target_dir: str, log_dir: str, checkout_
|
|
|
123
125
|
is_rubygems = src_info.get("rubygems", False)
|
|
124
126
|
|
|
125
127
|
# General download (git clone, wget)
|
|
126
|
-
success_git, msg, oss_name, oss_version = download_git_clone(link, target_dir,
|
|
127
|
-
|
|
128
|
+
success_git, msg, oss_name, oss_version = download_git_clone(link, target_dir,
|
|
129
|
+
checkout_to,
|
|
130
|
+
tag, branch,
|
|
131
|
+
ssh_key, id, git_token,
|
|
132
|
+
called_cli)
|
|
128
133
|
link = change_ssh_link_to_https(link)
|
|
129
134
|
if (not is_rubygems) and (not success_git):
|
|
130
135
|
if os.path.isfile(target_dir):
|
|
@@ -202,34 +207,44 @@ def get_github_token(git_url):
|
|
|
202
207
|
return github_token
|
|
203
208
|
|
|
204
209
|
|
|
205
|
-
def download_git_repository(refs_to_checkout, git_url, target_dir, tag):
|
|
210
|
+
def download_git_repository(refs_to_checkout, git_url, target_dir, tag, called_cli=True):
|
|
206
211
|
success = False
|
|
207
212
|
oss_version = ""
|
|
208
|
-
clone_default_branch_flag = False
|
|
209
213
|
|
|
210
214
|
logger.info(f"Download git url :{git_url}")
|
|
215
|
+
env = os.environ.copy()
|
|
216
|
+
if not called_cli:
|
|
217
|
+
env["GIT_TERMINAL_PROMPT"] = "0"
|
|
211
218
|
if refs_to_checkout:
|
|
212
219
|
try:
|
|
213
220
|
# gitPython uses the branch argument the same whether you check out to a branch or a tag.
|
|
214
|
-
|
|
215
|
-
|
|
221
|
+
Repo.clone_from(git_url, target_dir, branch=refs_to_checkout, env=env)
|
|
222
|
+
if any(Path(target_dir).iterdir()):
|
|
223
|
+
success = True
|
|
224
|
+
oss_version = refs_to_checkout
|
|
225
|
+
logger.info(f"Files found in {target_dir} after clone.")
|
|
226
|
+
else:
|
|
227
|
+
logger.info(f"No files found in {target_dir} after clone.")
|
|
228
|
+
success = False
|
|
216
229
|
except GitCommandError as error:
|
|
217
|
-
logger.
|
|
230
|
+
logger.info(f"Git checkout error:{error}")
|
|
231
|
+
success = False
|
|
232
|
+
except Exception as e:
|
|
233
|
+
logger.info(f"Repo.clone_from error:{e}")
|
|
218
234
|
success = False
|
|
219
235
|
|
|
220
236
|
if not success:
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
else:
|
|
228
|
-
oss_version = repo.git.describe('--tags')
|
|
237
|
+
Repo.clone_from(git_url, target_dir, env=env)
|
|
238
|
+
if any(Path(target_dir).iterdir()):
|
|
239
|
+
success = True
|
|
240
|
+
else:
|
|
241
|
+
logger.info(f"No files found in {target_dir} after clone.")
|
|
242
|
+
success = False
|
|
229
243
|
return success, oss_version
|
|
230
244
|
|
|
231
245
|
|
|
232
|
-
def download_git_clone(git_url, target_dir, checkout_to="", tag="", branch="",
|
|
246
|
+
def download_git_clone(git_url, target_dir, checkout_to="", tag="", branch="",
|
|
247
|
+
ssh_key="", id="", git_token="", called_cli=True):
|
|
233
248
|
oss_name = get_github_ossname(git_url)
|
|
234
249
|
refs_to_checkout = decide_checkout(checkout_to, tag, branch)
|
|
235
250
|
msg = ""
|
|
@@ -253,17 +268,19 @@ def download_git_clone(git_url, target_dir, checkout_to="", tag="", branch="", s
|
|
|
253
268
|
logger.info(f"Download git with ssh_key:{git_url}")
|
|
254
269
|
git_ssh_cmd = f'ssh -i {ssh_key}'
|
|
255
270
|
with Git().custom_environment(GIT_SSH_COMMAND=git_ssh_cmd):
|
|
256
|
-
success, oss_version = download_git_repository(refs_to_checkout, git_url, target_dir, tag)
|
|
271
|
+
success, oss_version = download_git_repository(refs_to_checkout, git_url, target_dir, tag, called_cli)
|
|
257
272
|
else:
|
|
258
273
|
if id and git_token:
|
|
259
274
|
try:
|
|
260
275
|
m = re.match(r"^(ht|f)tp(s?)\:\/\/", git_url)
|
|
261
276
|
protocol = m.group()
|
|
262
277
|
if protocol:
|
|
263
|
-
|
|
278
|
+
encoded_git_token = urllib.parse.quote(git_token, safe='')
|
|
279
|
+
encoded_id = urllib.parse.quote(id, safe='')
|
|
280
|
+
git_url = git_url.replace(protocol, f"{protocol}{encoded_id}:{encoded_git_token}@")
|
|
264
281
|
except Exception as error:
|
|
265
282
|
logger.info(f"Failed to insert id, token to git url:{error}")
|
|
266
|
-
success, oss_version = download_git_repository(refs_to_checkout, git_url, target_dir, tag)
|
|
283
|
+
success, oss_version = download_git_repository(refs_to_checkout, git_url, target_dir, tag, called_cli)
|
|
267
284
|
|
|
268
285
|
logger.info(f"git checkout: {oss_version}")
|
|
269
286
|
refs_to_checkout = oss_version
|
|
@@ -297,7 +314,7 @@ def download_wget(link, target_dir, compressed_only):
|
|
|
297
314
|
|
|
298
315
|
Path(target_dir).mkdir(parents=True, exist_ok=True)
|
|
299
316
|
|
|
300
|
-
ret, new_link, oss_name, oss_version = get_downloadable_url(link)
|
|
317
|
+
ret, new_link, oss_name, oss_version, pkg_type = get_downloadable_url(link)
|
|
301
318
|
if ret and new_link:
|
|
302
319
|
link = new_link
|
|
303
320
|
|
|
@@ -306,6 +323,9 @@ def download_wget(link, target_dir, compressed_only):
|
|
|
306
323
|
if link.endswith(ext):
|
|
307
324
|
success = True
|
|
308
325
|
break
|
|
326
|
+
if not success:
|
|
327
|
+
if pkg_type == 'cargo':
|
|
328
|
+
success = True
|
|
309
329
|
else:
|
|
310
330
|
success = True
|
|
311
331
|
|
|
@@ -313,7 +333,11 @@ def download_wget(link, target_dir, compressed_only):
|
|
|
313
333
|
raise Exception('Not supported compression type (link:{0})'.format(link))
|
|
314
334
|
|
|
315
335
|
logger.info(f"wget: {link}")
|
|
316
|
-
|
|
336
|
+
if pkg_type == 'cargo':
|
|
337
|
+
outfile = os.path.join(target_dir, f'{oss_name}.tar.gz')
|
|
338
|
+
downloaded_file = wget.download(link, out=outfile)
|
|
339
|
+
else:
|
|
340
|
+
downloaded_file = wget.download(link, target_dir)
|
|
317
341
|
if platform.system() != "Windows":
|
|
318
342
|
signal.alarm(0)
|
|
319
343
|
else:
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Copyright (c) 2025 LG Electronics Inc.
|
|
4
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
|
|
6
|
+
import os
|
|
7
|
+
import fnmatch
|
|
8
|
+
from typing import List
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def excluding_files(patterns: List[str], path_to_scan: str) -> List[str]:
|
|
12
|
+
excluded_paths = set()
|
|
13
|
+
|
|
14
|
+
# Normalize patterns: e.g., 'sample/', 'sample/*' -> 'sample'
|
|
15
|
+
# Replace backslash with slash
|
|
16
|
+
normalized_patterns = []
|
|
17
|
+
for pattern in patterns:
|
|
18
|
+
pattern = pattern.replace('\\', '/')
|
|
19
|
+
if pattern.endswith('/') or pattern.endswith('/*'):
|
|
20
|
+
pattern = pattern.rstrip('/*')
|
|
21
|
+
normalized_patterns.append(pattern)
|
|
22
|
+
|
|
23
|
+
# Traverse directories
|
|
24
|
+
for root, dirs, files in os.walk(path_to_scan):
|
|
25
|
+
remove_dir_list = []
|
|
26
|
+
|
|
27
|
+
# (1) Directory matching
|
|
28
|
+
for d in dirs:
|
|
29
|
+
dir_name = d
|
|
30
|
+
dir_path = os.path.relpath(os.path.join(root, d), path_to_scan).replace('\\', '/')
|
|
31
|
+
matched = False
|
|
32
|
+
|
|
33
|
+
for pat in normalized_patterns:
|
|
34
|
+
# Match directory name
|
|
35
|
+
if fnmatch.fnmatch(dir_name, pat):
|
|
36
|
+
matched = True
|
|
37
|
+
|
|
38
|
+
# Match the full relative path
|
|
39
|
+
if not matched:
|
|
40
|
+
if fnmatch.fnmatch(dir_path, pat) or fnmatch.fnmatch(dir_path, pat + "/*"):
|
|
41
|
+
matched = True
|
|
42
|
+
|
|
43
|
+
# If matched, exclude all files under this directory and stop checking patterns
|
|
44
|
+
if matched:
|
|
45
|
+
sub_root_path = os.path.join(root, d)
|
|
46
|
+
for sr, _, sf in os.walk(sub_root_path):
|
|
47
|
+
for sub_file in sf:
|
|
48
|
+
sub_file_path = os.path.relpath(os.path.join(sr, sub_file), path_to_scan)
|
|
49
|
+
excluded_paths.add(sub_file_path.replace('\\', '/'))
|
|
50
|
+
remove_dir_list.append(d)
|
|
51
|
+
break
|
|
52
|
+
|
|
53
|
+
# (1-2) Prune matched directories from further traversal
|
|
54
|
+
for rd in remove_dir_list:
|
|
55
|
+
dirs.remove(rd)
|
|
56
|
+
|
|
57
|
+
# (2) File matching
|
|
58
|
+
for f in files:
|
|
59
|
+
file_path = os.path.relpath(os.path.join(root, f), path_to_scan).replace('\\', '/')
|
|
60
|
+
for pat in normalized_patterns:
|
|
61
|
+
if fnmatch.fnmatch(file_path, pat) or fnmatch.fnmatch(file_path, pat + "/*"):
|
|
62
|
+
excluded_paths.add(file_path)
|
|
63
|
+
break
|
|
64
|
+
|
|
65
|
+
return sorted(excluded_paths)
|
fosslight_util/help.py
CHANGED
|
@@ -3,7 +3,10 @@
|
|
|
3
3
|
# Copyright (c) 2021 LG Electronics Inc.
|
|
4
4
|
# SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
import sys
|
|
6
|
-
|
|
6
|
+
try:
|
|
7
|
+
from importlib.metadata import version, PackageNotFoundError
|
|
8
|
+
except ImportError:
|
|
9
|
+
from importlib_metadata import version, PackageNotFoundError # Python <3.8
|
|
7
10
|
|
|
8
11
|
_HELP_MESSAGE_COMMON = """
|
|
9
12
|
_______ _______ _______ _______ ___ ___ __
|
|
@@ -50,7 +53,10 @@ class PrintHelpMsg():
|
|
|
50
53
|
def print_package_version(pkg_name: str, msg: str = "", exitopt: bool = True) -> str:
|
|
51
54
|
if msg == "":
|
|
52
55
|
msg = f"{pkg_name} Version:"
|
|
53
|
-
|
|
56
|
+
try:
|
|
57
|
+
cur_version = version(pkg_name)
|
|
58
|
+
except PackageNotFoundError:
|
|
59
|
+
cur_version = "unknown"
|
|
54
60
|
|
|
55
61
|
if exitopt:
|
|
56
62
|
print(f'{msg} {cur_version}')
|
fosslight_util/output_format.py
CHANGED
|
@@ -48,7 +48,8 @@ def check_output_format(output='', format='', customized_format={}):
|
|
|
48
48
|
if format:
|
|
49
49
|
if output_extension != basename_extension:
|
|
50
50
|
success = False
|
|
51
|
-
msg = f"(-o & -f option) Enter the same extension of output file(-o:'{output}')
|
|
51
|
+
msg = f"(-o & -f option) Enter the same extension of output file(-o:'{output}') \
|
|
52
|
+
with format(-f:'{format}')."
|
|
52
53
|
else:
|
|
53
54
|
if basename_extension not in support_format.values():
|
|
54
55
|
success = False
|
|
@@ -96,7 +97,8 @@ def check_output_formats(output='', formats=[], customized_format={}):
|
|
|
96
97
|
if formats:
|
|
97
98
|
if basename_extension not in output_extensions:
|
|
98
99
|
success = False
|
|
99
|
-
msg = f"(-o & -f option) The format of output file(-o:'{output}')
|
|
100
|
+
msg = f"(-o & -f option) The format of output file(-o:'{output}') \
|
|
101
|
+
should be in the format list(-f:'{formats}')."
|
|
100
102
|
else:
|
|
101
103
|
if basename_extension not in support_format.values():
|
|
102
104
|
success = False
|
|
@@ -145,7 +147,8 @@ def check_output_formats_v2(output='', formats=[], customized_format={}):
|
|
|
145
147
|
if formats:
|
|
146
148
|
if basename_extension not in output_extensions:
|
|
147
149
|
success = False
|
|
148
|
-
msg = f"(-o & -f option) The format of output file(-o:'{output}')
|
|
150
|
+
msg = f"(-o & -f option) The format of output file(-o:'{output}') \
|
|
151
|
+
should be in the format list(-f:'{formats}')."
|
|
149
152
|
else:
|
|
150
153
|
if basename_extension not in support_format.values():
|
|
151
154
|
success = False
|
|
@@ -157,6 +160,7 @@ def check_output_formats_v2(output='', formats=[], customized_format={}):
|
|
|
157
160
|
if not output_extensions:
|
|
158
161
|
output_extensions = ['.xlsx']
|
|
159
162
|
if not formats:
|
|
163
|
+
formats = []
|
|
160
164
|
for ext in output_extensions:
|
|
161
165
|
for key, value in support_format.items():
|
|
162
166
|
if value == ext:
|
fosslight_util/set_log.py
CHANGED
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
import logging
|
|
7
7
|
import os
|
|
8
8
|
from pathlib import Path
|
|
9
|
-
import pkg_resources
|
|
10
9
|
import sys
|
|
11
10
|
import platform
|
|
12
11
|
from . import constant as constant
|
|
@@ -15,6 +14,11 @@ import coloredlogs
|
|
|
15
14
|
from typing import Tuple
|
|
16
15
|
from logging import Logger
|
|
17
16
|
|
|
17
|
+
try:
|
|
18
|
+
from importlib.metadata import version, PackageNotFoundError
|
|
19
|
+
except ImportError:
|
|
20
|
+
from importlib_metadata import version, PackageNotFoundError # Python <3.8
|
|
21
|
+
|
|
18
22
|
|
|
19
23
|
def init_check_latest_version(pkg_version="", main_package_name=""):
|
|
20
24
|
|
|
@@ -92,9 +96,11 @@ def init_log(log_file: str, create_file: bool = True, stream_log_level: int = lo
|
|
|
92
96
|
if main_package_name != "":
|
|
93
97
|
pkg_info = main_package_name
|
|
94
98
|
try:
|
|
95
|
-
pkg_version =
|
|
99
|
+
pkg_version = version(main_package_name)
|
|
96
100
|
init_check_latest_version(pkg_version, main_package_name)
|
|
97
101
|
pkg_info = main_package_name + " v" + pkg_version
|
|
102
|
+
except PackageNotFoundError:
|
|
103
|
+
logger.debug('Cannot check the version: Package not found')
|
|
98
104
|
except Exception as error:
|
|
99
105
|
logger.debug('Cannot check the version:' + str(error))
|
|
100
106
|
_result_log["Tool Info"] = pkg_info
|
|
@@ -5,16 +5,11 @@
|
|
|
5
5
|
# SPDX-License-Identifier: Apache-2.0
|
|
6
6
|
|
|
7
7
|
import os
|
|
8
|
-
import sys
|
|
9
8
|
import logging
|
|
10
9
|
import re
|
|
11
|
-
import json
|
|
12
10
|
from pathlib import Path
|
|
13
|
-
from datetime import datetime
|
|
14
|
-
from fosslight_util.spdx_licenses import get_spdx_licenses_json, get_license_from_nick
|
|
15
11
|
from fosslight_util.constant import (LOGGER_NAME, FOSSLIGHT_DEPENDENCY, FOSSLIGHT_SCANNER,
|
|
16
|
-
|
|
17
|
-
from fosslight_util.oss_item import CHECKSUM_NULL, get_checksum_sha1
|
|
12
|
+
FOSSLIGHT_SOURCE)
|
|
18
13
|
import traceback
|
|
19
14
|
|
|
20
15
|
logger = logging.getLogger(LOGGER_NAME)
|
|
@@ -27,14 +22,11 @@ try:
|
|
|
27
22
|
from cyclonedx.model import XsUri, ExternalReferenceType
|
|
28
23
|
from cyclonedx.model.bom import Bom
|
|
29
24
|
from cyclonedx.model.component import Component, ComponentType, HashAlgorithm, HashType, ExternalReference
|
|
30
|
-
from cyclonedx.model.contact import OrganizationalEntity
|
|
31
25
|
from cyclonedx.output import make_outputter, BaseOutput
|
|
32
26
|
from cyclonedx.output.json import JsonV1Dot6
|
|
33
27
|
from cyclonedx.schema import OutputFormat, SchemaVersion
|
|
34
|
-
from cyclonedx.validation import make_schemabased_validator
|
|
35
28
|
from cyclonedx.validation.json import JsonStrictValidator
|
|
36
29
|
from cyclonedx.output.json import Json as JsonOutputter
|
|
37
|
-
from cyclonedx.output.xml import Xml as XmlOutputter
|
|
38
30
|
from cyclonedx.validation.xml import XmlValidator
|
|
39
31
|
except Exception:
|
|
40
32
|
logger.info('No import cyclonedx-python-lib')
|
|
@@ -66,7 +58,6 @@ def write_cyclonedx(output_file_without_ext, output_extension, scan_item):
|
|
|
66
58
|
type=ComponentType.APPLICATION,
|
|
67
59
|
bom_ref=str(comp_id))
|
|
68
60
|
relation_tree = {}
|
|
69
|
-
bom_ref_packages = []
|
|
70
61
|
|
|
71
62
|
output_dir = os.path.dirname(output_file_without_ext)
|
|
72
63
|
Path(output_dir).mkdir(parents=True, exist_ok=True)
|
|
@@ -82,7 +73,7 @@ def write_cyclonedx(output_file_without_ext, output_extension, scan_item):
|
|
|
82
73
|
comp_type = ComponentType.LIBRARY
|
|
83
74
|
|
|
84
75
|
for oss_item in file_item.oss_items:
|
|
85
|
-
if oss_item.name == '':
|
|
76
|
+
if oss_item.name == '' or oss_item.name == '-':
|
|
86
77
|
if scanner_name == FOSSLIGHT_DEPENDENCY:
|
|
87
78
|
continue
|
|
88
79
|
else:
|
|
@@ -102,7 +93,8 @@ def write_cyclonedx(output_file_without_ext, output_extension, scan_item):
|
|
|
102
93
|
if scanner_name == FOSSLIGHT_DEPENDENCY and file_item.purl:
|
|
103
94
|
comp.purl = PackageURL.from_string(file_item.purl)
|
|
104
95
|
if scanner_name != FOSSLIGHT_DEPENDENCY:
|
|
105
|
-
|
|
96
|
+
if file_item.checksum != '0':
|
|
97
|
+
comp.hashes = [HashType(alg=HashAlgorithm.SHA_1, content=file_item.checksum)]
|
|
106
98
|
|
|
107
99
|
if oss_item.download_location != '':
|
|
108
100
|
comp.external_references = [ExternalReference(url=XsUri(oss_item.download_location),
|
|
@@ -113,7 +105,7 @@ def write_cyclonedx(output_file_without_ext, output_extension, scan_item):
|
|
|
113
105
|
try:
|
|
114
106
|
oss_licenses.append(lc_factory.make_from_string(ol))
|
|
115
107
|
except Exception:
|
|
116
|
-
logger.info(f'No spdx license name: {
|
|
108
|
+
logger.info(f'No spdx license name: {ol}')
|
|
117
109
|
if oss_licenses:
|
|
118
110
|
comp.licenses = oss_licenses
|
|
119
111
|
|
|
@@ -192,9 +184,9 @@ def write_cyclonedx_json(bom, result_file):
|
|
|
192
184
|
except MissingOptionalDependencyException as error:
|
|
193
185
|
logger.debug(f'JSON-validation was skipped due to {error}')
|
|
194
186
|
except Exception as e:
|
|
187
|
+
logger.warning(f'Fail to write cyclonedx json: {e}')
|
|
195
188
|
success = False
|
|
196
189
|
return success
|
|
197
|
-
|
|
198
190
|
|
|
199
191
|
|
|
200
192
|
def write_cyclonedx_xml(bom, result_file):
|
|
@@ -213,5 +205,6 @@ def write_cyclonedx_xml(bom, result_file):
|
|
|
213
205
|
except MissingOptionalDependencyException as error:
|
|
214
206
|
logger.debug(f'XML-validation was skipped due to {error}')
|
|
215
207
|
except Exception as e:
|
|
208
|
+
logger.warning(f'Fail to write cyclonedx xml: {e}')
|
|
216
209
|
success = False
|
|
217
|
-
return success
|
|
210
|
+
return success
|
fosslight_util/write_excel.py
CHANGED
|
@@ -34,6 +34,7 @@ IDX_FILE = 0
|
|
|
34
34
|
IDX_EXCLUDE = 7
|
|
35
35
|
logger = logging.getLogger(LOGGER_NAME)
|
|
36
36
|
COVER_SHEET_NAME = 'Scanner Info'
|
|
37
|
+
MAX_EXCEL_URL_LENGTH = 255
|
|
37
38
|
|
|
38
39
|
|
|
39
40
|
def get_header_row(sheet_name, extended_header={}):
|
|
@@ -181,7 +182,10 @@ def write_result_to_sheet(worksheet, sheet_contents):
|
|
|
181
182
|
for row_item in sheet_contents:
|
|
182
183
|
worksheet.write(row, 0, row)
|
|
183
184
|
for col_num, value in enumerate(row_item):
|
|
184
|
-
|
|
185
|
+
if len(value) > MAX_EXCEL_URL_LENGTH and (value.startswith("http://") or value.startswith("https://")):
|
|
186
|
+
worksheet.write_string(row, col_num + 1, str(value))
|
|
187
|
+
else:
|
|
188
|
+
worksheet.write(row, col_num + 1, str(value))
|
|
185
189
|
row += 1
|
|
186
190
|
|
|
187
191
|
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import logging
|
|
7
7
|
import os
|
|
8
8
|
import json
|
|
9
|
-
from fosslight_util.constant import LOGGER_NAME
|
|
9
|
+
from fosslight_util.constant import LOGGER_NAME, FOSSLIGHT_DEPENDENCY
|
|
10
10
|
from fosslight_util.oss_item import ScannerItem
|
|
11
11
|
from typing import List
|
|
12
12
|
|
|
@@ -20,22 +20,27 @@ def write_scancodejson(output_dir: str, output_filename: str, oss_list: List[Sca
|
|
|
20
20
|
json_output['summary'] = {}
|
|
21
21
|
json_output['license_detections'] = []
|
|
22
22
|
json_output['files'] = []
|
|
23
|
+
json_output['dependencies'] = []
|
|
23
24
|
|
|
24
|
-
for file_items in oss_list.file_items.
|
|
25
|
+
for scanner, file_items in oss_list.file_items.items():
|
|
25
26
|
for fi in file_items:
|
|
26
|
-
if
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
fi.
|
|
32
|
-
|
|
27
|
+
if scanner == FOSSLIGHT_DEPENDENCY:
|
|
28
|
+
json_output['dependencies'] = add_item_in_deps(fi, json_output['dependencies'])
|
|
29
|
+
else:
|
|
30
|
+
if fi.exclude:
|
|
31
|
+
continue
|
|
32
|
+
if fi.oss_items and (all(oss_item.exclude for oss_item in fi.oss_items)):
|
|
33
|
+
continue
|
|
34
|
+
if not fi.source_name_or_path:
|
|
35
|
+
fi.source_name_or_path = EMPTY_FILE_PATH
|
|
36
|
+
json_output['files'] = add_item_in_files(fi, json_output['files'])
|
|
33
37
|
|
|
34
38
|
with open(os.path.join(output_dir, output_filename), 'w') as f:
|
|
35
39
|
json.dump(json_output, f, sort_keys=False, indent=4)
|
|
36
40
|
|
|
37
41
|
|
|
38
|
-
def
|
|
42
|
+
def get_oss_item_list(oss_items):
|
|
43
|
+
scan_oss_items = []
|
|
39
44
|
for oi in oss_items:
|
|
40
45
|
if oi.exclude:
|
|
41
46
|
continue
|
|
@@ -46,9 +51,9 @@ def append_oss_item_in_filesitem(oss_items, files_item):
|
|
|
46
51
|
oss_item['copyright'] = oi.copyright
|
|
47
52
|
oss_item['download_location'] = oi.download_location
|
|
48
53
|
oss_item['comment'] = oi.comment
|
|
49
|
-
|
|
54
|
+
scan_oss_items.append(oss_item)
|
|
50
55
|
|
|
51
|
-
return
|
|
56
|
+
return scan_oss_items
|
|
52
57
|
|
|
53
58
|
|
|
54
59
|
def add_item_in_files(file_item, files_list):
|
|
@@ -57,8 +62,20 @@ def add_item_in_files(file_item, files_list):
|
|
|
57
62
|
files_item['name'] = os.path.basename(file_item.source_name_or_path)
|
|
58
63
|
files_item['is_binary'] = file_item.is_binary
|
|
59
64
|
files_item['base_name'], files_item['extension'] = os.path.splitext(os.path.basename(file_item.source_name_or_path))
|
|
60
|
-
files_item['oss'] =
|
|
61
|
-
|
|
65
|
+
files_item['oss'] = get_oss_item_list(file_item.oss_items)
|
|
66
|
+
|
|
62
67
|
files_list.append(files_item)
|
|
63
68
|
|
|
64
69
|
return files_list
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def add_item_in_deps(file_item, deps_list):
|
|
73
|
+
deps_item = {}
|
|
74
|
+
deps_item['purl'] = file_item.purl
|
|
75
|
+
deps_item['scope'] = 'dependencies'
|
|
76
|
+
deps_item['depends_on'] = file_item.depends_on
|
|
77
|
+
deps_item['oss'] = get_oss_item_list(file_item.oss_items)
|
|
78
|
+
|
|
79
|
+
deps_list.append(deps_item)
|
|
80
|
+
|
|
81
|
+
return deps_list
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
fosslight_util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
fosslight_util/_get_downloadable_url.py,sha256=SqXCESg1GVXhCpObZoceXdFJVecDrDp-7qW88w0QsCY,12091
|
|
3
|
+
fosslight_util/compare_yaml.py,sha256=eLqqCLgERxRHN5vsnpQVMXIEU862Lx66mD_y4uMgQE4,2916
|
|
4
|
+
fosslight_util/constant.py,sha256=zElnWOzXt020sYiFTiRQn8ZjZyZpL3aPmfAqfQLcxJk,2278
|
|
5
|
+
fosslight_util/correct.py,sha256=1WEAL-9_KhjFPLucPhv0PNN3K7avm0z8mU6sTuSyeHM,3864
|
|
6
|
+
fosslight_util/cover.py,sha256=qqqKzxqFwKimal764FaugRUBcHWdeKt8af6xeK0mH8E,2040
|
|
7
|
+
fosslight_util/download.py,sha256=V3EBgXt-xHarJZFrskXHaX4Ij81ZPjj6hzvtmpKu7xE,17642
|
|
8
|
+
fosslight_util/exclude.py,sha256=fDmBsZJ_F7O9Oh2T-07R03XNbElo1tFaf_z01KfSAqU,2399
|
|
9
|
+
fosslight_util/help.py,sha256=Bmyz-eFP0X0qUfgFPrWiuyUPE0TLQfWjgfHTzJBIInc,2377
|
|
10
|
+
fosslight_util/oss_item.py,sha256=8W2HlwqGH3l1iPPdvycrRYKsBSBpqAkqYyYtBVPgMtY,6868
|
|
11
|
+
fosslight_util/output_format.py,sha256=BP23LspxawDZ_a99oWLVKWUQ-G7P5uoUpjEXhkRFKwc,8801
|
|
12
|
+
fosslight_util/parsing_yaml.py,sha256=2zx_N5lMkXT1dRmfJMpzlrru-y_2F_CkVbGlba6vQpU,5380
|
|
13
|
+
fosslight_util/read_excel.py,sha256=-QvrdxaNqYOpIm1H7ZqIEh5NLvFPymZo6BAOZcQmQug,5263
|
|
14
|
+
fosslight_util/set_log.py,sha256=AbcLFLvY9GSOYSN0a110wO5gNcyc8KKnNjl7GxHEW9A,4008
|
|
15
|
+
fosslight_util/spdx_licenses.py,sha256=GvMNe_D4v2meapTVwPu2BJXInnTo3_gIzg669eJhUu0,3691
|
|
16
|
+
fosslight_util/timer_thread.py,sha256=5VbZENQPD-N0NUmzEktqGr6Am-e7vxD79K05mmr29g0,433
|
|
17
|
+
fosslight_util/write_cyclonedx.py,sha256=hq817j-0OM89B8jtZKgHgvVa0YEaYHlz_8R5vNpe21I,9662
|
|
18
|
+
fosslight_util/write_excel.py,sha256=QUIMCnmEKJoSpri5RctBcKLvhDShLdZUP_dhHv-sVy8,10165
|
|
19
|
+
fosslight_util/write_opossum.py,sha256=ltmo6SkugKWdAYupeCqwE4-3lua0GwLpix1XqFC-tT8,11678
|
|
20
|
+
fosslight_util/write_scancodejson.py,sha256=dMCjTtUnNR5BCL6gBCleDT8bTSAN5Gg2RAfimmkGXUE,2692
|
|
21
|
+
fosslight_util/write_spdx.py,sha256=Ov9jBlfVrkWIymcfAxbupUxDZKfCOZZGOPZ4v-x230M,12108
|
|
22
|
+
fosslight_util/write_txt.py,sha256=BEFjYBppqk1CITx-fUN4vfvKv0XCs1GXWtc2Iu-etU4,629
|
|
23
|
+
fosslight_util/write_yaml.py,sha256=QlEKoIPQsEaYERfbP53TeKgnllYzhLQWm5wYjnWtVjE,3238
|
|
24
|
+
fosslight_util/resources/frequentLicenselist.json,sha256=GUhzK6tu7ok10fekOnmVmUgIGRC-acGABZKTNKfDyYA,4776157
|
|
25
|
+
fosslight_util/resources/frequent_license_nick_list.json,sha256=ryU2C_6ZxHbz90_sUN9OvI9GXkCMLu7oGcmd9W79YYo,5005
|
|
26
|
+
fosslight_util/resources/licenses.json,sha256=mK55z-bhY7Mjpj2KsO1crKGGL-X3F6MBFQJ0zLlx010,240843
|
|
27
|
+
fosslight_util-2.1.18.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
28
|
+
fosslight_util-2.1.18.dist-info/METADATA,sha256=eiYd-q6MOwvzp-SPII-NU2MPNQs6rdm9PgPZEWdweFY,6500
|
|
29
|
+
fosslight_util-2.1.18.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
|
|
30
|
+
fosslight_util-2.1.18.dist-info/entry_points.txt,sha256=bzXX5i7HZ13V8BLKvtu_9KO3ZjtRypH-XszOXT6I3bU,69
|
|
31
|
+
fosslight_util-2.1.18.dist-info/top_level.txt,sha256=2qyYWGLakgBRy4BqoBNt-I5C29tBr_e93e5e1pbuTGA,15
|
|
32
|
+
fosslight_util-2.1.18.dist-info/RECORD,,
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
fosslight_util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
fosslight_util/_get_downloadable_url.py,sha256=tZz7UTUuLAbz2muXocOb9epMY_6RXIt-GEM8jhN0c3o,9315
|
|
3
|
-
fosslight_util/compare_yaml.py,sha256=eLqqCLgERxRHN5vsnpQVMXIEU862Lx66mD_y4uMgQE4,2916
|
|
4
|
-
fosslight_util/constant.py,sha256=Ig3ACm9_QirE4389Wt-IfxOqRkVOUjqGnX1B05z2Byo,2151
|
|
5
|
-
fosslight_util/correct.py,sha256=3iUipan8ZX8sbyIIGAPtMkAGvZ4YucjeJwx1K1Bx_z4,3897
|
|
6
|
-
fosslight_util/cover.py,sha256=qqqKzxqFwKimal764FaugRUBcHWdeKt8af6xeK0mH8E,2040
|
|
7
|
-
fosslight_util/download.py,sha256=bCKvW76XJTnKMAUW5sJZxg_wBUhiybXovJuL04W4P4c,16364
|
|
8
|
-
fosslight_util/help.py,sha256=M3_XahUkP794US9Q0NS6ujmGvrFFnKBHsTU95Fg1KpA,2181
|
|
9
|
-
fosslight_util/oss_item.py,sha256=8W2HlwqGH3l1iPPdvycrRYKsBSBpqAkqYyYtBVPgMtY,6868
|
|
10
|
-
fosslight_util/output_format.py,sha256=AdQVzCpar6n3PCDtijLWbJyFAGKQVE7JhLXlHPtITH4,8678
|
|
11
|
-
fosslight_util/parsing_yaml.py,sha256=2zx_N5lMkXT1dRmfJMpzlrru-y_2F_CkVbGlba6vQpU,5380
|
|
12
|
-
fosslight_util/read_excel.py,sha256=-QvrdxaNqYOpIm1H7ZqIEh5NLvFPymZo6BAOZcQmQug,5263
|
|
13
|
-
fosslight_util/set_log.py,sha256=Xpa94AiOyGEK8ucaYkvkAllvlen1Pq_d6UG6kPYBYBc,3780
|
|
14
|
-
fosslight_util/spdx_licenses.py,sha256=GvMNe_D4v2meapTVwPu2BJXInnTo3_gIzg669eJhUu0,3691
|
|
15
|
-
fosslight_util/timer_thread.py,sha256=5VbZENQPD-N0NUmzEktqGr6Am-e7vxD79K05mmr29g0,433
|
|
16
|
-
fosslight_util/write_cyclonedx.py,sha256=N6r32zj_ikoGkZa9xoreKqdsncoOfFKnV7lHpeiiEhI,9902
|
|
17
|
-
fosslight_util/write_excel.py,sha256=G0fIslbWoOtWZCJxbBGLCpUKbhmwrrqhI5PHwRw8_44,9931
|
|
18
|
-
fosslight_util/write_opossum.py,sha256=ltmo6SkugKWdAYupeCqwE4-3lua0GwLpix1XqFC-tT8,11678
|
|
19
|
-
fosslight_util/write_scancodejson.py,sha256=81n7cWNYoyIKE_V4Kx5YtL2CgjMPIjoKdnSU3inkpJY,2163
|
|
20
|
-
fosslight_util/write_spdx.py,sha256=Ov9jBlfVrkWIymcfAxbupUxDZKfCOZZGOPZ4v-x230M,12108
|
|
21
|
-
fosslight_util/write_txt.py,sha256=BEFjYBppqk1CITx-fUN4vfvKv0XCs1GXWtc2Iu-etU4,629
|
|
22
|
-
fosslight_util/write_yaml.py,sha256=QlEKoIPQsEaYERfbP53TeKgnllYzhLQWm5wYjnWtVjE,3238
|
|
23
|
-
fosslight_util/resources/frequentLicenselist.json,sha256=GUhzK6tu7ok10fekOnmVmUgIGRC-acGABZKTNKfDyYA,4776157
|
|
24
|
-
fosslight_util/resources/frequent_license_nick_list.json,sha256=ryU2C_6ZxHbz90_sUN9OvI9GXkCMLu7oGcmd9W79YYo,5005
|
|
25
|
-
fosslight_util/resources/licenses.json,sha256=mK55z-bhY7Mjpj2KsO1crKGGL-X3F6MBFQJ0zLlx010,240843
|
|
26
|
-
fosslight_util-2.1.7.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
27
|
-
fosslight_util-2.1.7.dist-info/METADATA,sha256=_SbQsVJDKbUmd3C0i1fs7C-B9z92g_SLHWrQVb2mi_s,6499
|
|
28
|
-
fosslight_util-2.1.7.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
|
|
29
|
-
fosslight_util-2.1.7.dist-info/entry_points.txt,sha256=bzXX5i7HZ13V8BLKvtu_9KO3ZjtRypH-XszOXT6I3bU,69
|
|
30
|
-
fosslight_util-2.1.7.dist-info/top_level.txt,sha256=2qyYWGLakgBRy4BqoBNt-I5C29tBr_e93e5e1pbuTGA,15
|
|
31
|
-
fosslight_util-2.1.7.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|