fosslight-util 1.4.34__py3-none-any.whl → 2.1.28__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.
@@ -4,60 +4,489 @@
4
4
  # SPDX-License-Identifier: Apache-2.0
5
5
  import logging
6
6
  import re
7
+ import requests
8
+ from lastversion import latest
7
9
  from bs4 import BeautifulSoup
8
10
  from urllib.request import urlopen
9
11
  import fosslight_util.constant as constant
10
- from npm.bindings import npm_run
11
12
 
12
13
  logger = logging.getLogger(constant.LOGGER_NAME)
13
14
 
14
15
 
15
- def get_downloadable_url(link):
16
+ def version_exists(pkg_type, origin_name, version):
17
+ try:
18
+ if pkg_type in ['npm', 'npm2']:
19
+ r = requests.get(f"https://registry.npmjs.org/{origin_name}", timeout=5)
20
+ if r.status_code == 200:
21
+ data = r.json()
22
+ return version in data.get('versions', {})
23
+ elif pkg_type == 'pypi':
24
+ r = requests.get(f"https://pypi.org/pypi/{origin_name}/{version}/json", timeout=5)
25
+ return r.status_code == 200
26
+ elif pkg_type == 'maven':
27
+ r = requests.get(f'https://api.deps.dev/v3alpha/systems/maven/packages/{origin_name}', timeout=5)
28
+ if r.status_code == 200:
29
+ versions = r.json().get('versions', [])
30
+ for vobj in versions:
31
+ vkey = vobj.get('versionKey') or {}
32
+ if vkey.get('version') == version:
33
+ return True
34
+ return False
35
+ elif pkg_type == 'pub':
36
+ r = requests.get(f'https://pub.dev/api/packages/{origin_name}', timeout=5)
37
+ if r.status_code == 200:
38
+ versions = r.json().get('versions', [])
39
+ return any(v.get('version') == version for v in versions if isinstance(v, dict))
40
+ elif pkg_type == 'go':
41
+ if not version.startswith('v'):
42
+ version = f'v{version}'
43
+ r = requests.get(f'https://proxy.golang.org/{origin_name}/@v/list', timeout=5)
44
+ if r.status_code == 200:
45
+ listed = r.text.splitlines()
46
+ return version in listed
47
+ except Exception as e:
48
+ logger.info(f'version_exists check failed ({pkg_type}:{origin_name}:{version}) {e}')
49
+ return True
50
+ return False
51
+
52
+
53
+ def extract_name_version_from_link(link, checkout_version):
54
+ oss_name = ""
55
+ oss_version = ""
56
+ matched = False
57
+ direct_maven = False
58
+
59
+ if link.startswith("www."):
60
+ link = link.replace("www.", "https://www.", 1)
61
+
62
+ if (not matched and (
63
+ link.startswith('https://repo1.maven.org/maven2/') or
64
+ link.startswith('https://dl.google.com/android/maven2/')
65
+ )):
66
+ parsed = parse_direct_maven_url(link)
67
+ if parsed:
68
+ origin_name, parsed_version = parsed
69
+ oss_name = origin_name # groupId:artifactId
70
+ oss_version = parsed_version or ""
71
+ matched = True
72
+ direct_maven = True
73
+ pkg_type = 'maven'
74
+
75
+ for direct_key in ["maven_repo1", "maven_google"]:
76
+ pattern = constant.PKG_PATTERN.get(direct_key)
77
+ if pattern and re.match(pattern, link):
78
+ parsed = parse_direct_maven_url(link)
79
+ if parsed:
80
+ origin_name, parsed_version = parsed
81
+ oss_name = origin_name
82
+ oss_version = parsed_version or ""
83
+ matched = True
84
+ direct_maven = True
85
+ pkg_type = 'maven'
86
+ break
87
+
88
+ if not matched:
89
+ for key, value in constant.PKG_PATTERN.items():
90
+ if key in ["maven_repo1", "maven_google"]:
91
+ continue
92
+ p = re.compile(value)
93
+ match = p.match(link)
94
+ if match:
95
+ try:
96
+ pkg_type = key
97
+ origin_name = match.group(1)
98
+ if (key == "pypi") or (key == "pypi2"):
99
+ oss_name = f"pypi:{origin_name}"
100
+ oss_name = re.sub(r"[-_.]+", "-", oss_name)
101
+ oss_version = match.group(2)
102
+ pkg_type = 'pypi'
103
+ elif key == "maven":
104
+ artifact = match.group(2)
105
+ oss_name = f"{origin_name}:{artifact}"
106
+ origin_name = oss_name
107
+ oss_version = match.group(3)
108
+ elif key == "npm" or key == "npm2":
109
+ oss_name = f"npm:{origin_name}"
110
+ oss_version = match.group(2)
111
+ elif key == "pub":
112
+ oss_name = f"pub:{origin_name}"
113
+ oss_version = match.group(2)
114
+ elif key == "cocoapods":
115
+ oss_name = f"cocoapods:{origin_name}"
116
+ elif key == "go":
117
+ if origin_name.endswith('/'):
118
+ origin_name = origin_name[:-1]
119
+ oss_name = f"go:{origin_name}"
120
+ oss_version = match.group(2)
121
+ elif key == "cargo":
122
+ oss_name = f"cargo:{origin_name}"
123
+ oss_version = match.group(2)
124
+ except Exception as ex:
125
+ logger.info(f"extract_name_version_from_link {key}:{ex}")
126
+ if oss_name:
127
+ matched = True
128
+ break
129
+
130
+ if not matched:
131
+ return "", "", link, ""
132
+ else:
133
+ need_latest = False
134
+ if not oss_version and checkout_version:
135
+ oss_version = checkout_version.strip()
136
+ if pkg_type in ["pypi", "maven", "npm", "npm2", "pub", "go"]:
137
+ if oss_version:
138
+ try:
139
+ if not version_exists(pkg_type, origin_name, oss_version):
140
+ logger.info(f'Version {oss_version} not found for {oss_name}; will attempt latest fallback')
141
+ need_latest = True
142
+ except Exception as e:
143
+ logger.info(f'Version validation failed ({oss_name}:{oss_version}) {e}; will attempt latest fallback')
144
+ need_latest = True
145
+ else:
146
+ need_latest = True
147
+ if need_latest:
148
+ latest_ver = get_latest_package_version(link, pkg_type, origin_name)
149
+ if latest_ver:
150
+ if oss_version and latest_ver != oss_version:
151
+ logger.info(f'Fallback to latest version {latest_ver} (previous invalid: {oss_version})')
152
+ elif not oss_version:
153
+ logger.info(f'Using latest version {latest_ver} (no version detected)')
154
+ oss_version = latest_ver
155
+
156
+ try:
157
+ if oss_version:
158
+ if pkg_type == 'maven' and direct_maven:
159
+ # Skip if oss_name malformed
160
+ if ':' in oss_name:
161
+ parts = oss_name.split(':', 1)
162
+ group_id, artifact_id = parts[0], parts[1]
163
+ group_path = group_id.replace('.', '/')
164
+ if (
165
+ link.startswith('https://repo1.maven.org/maven2/') or
166
+ link.startswith('http://repo1.maven.org/maven2/')
167
+ ):
168
+ if not re.search(r'/\d[^/]*/*$', link.rstrip('/')):
169
+ link = (
170
+ f'https://repo1.maven.org/maven2/{group_path}/'
171
+ f'{artifact_id}/{oss_version}'
172
+ )
173
+ elif (
174
+ link.startswith('https://dl.google.com/android/maven2/') or
175
+ link.startswith('http://dl.google.com/android/maven2/')
176
+ ):
177
+ if not re.search(r'/\d[^/]*/*$', link.rstrip('/')):
178
+ link = (
179
+ f'https://dl.google.com/android/maven2/{group_path}/'
180
+ f'{artifact_id}/{oss_version}/{artifact_id}-{oss_version}-sources.jar'
181
+ )
182
+ else:
183
+ logger.debug(f'Skip maven normalization due to invalid oss_name: {oss_name}')
184
+ else:
185
+ link = get_new_link_with_version(link, pkg_type, origin_name, oss_version)
186
+ except Exception as _e:
187
+ logger.info(f'Failed to build versioned link for {oss_name or origin_name}:{oss_version} {_e}')
188
+
189
+ return oss_name, oss_version, link, pkg_type
190
+
191
+
192
+ def parse_direct_maven_url(url):
193
+ try:
194
+ clean_url = url.replace('https://', '').replace('http://', '')
195
+ if clean_url.startswith('repo1.maven.org/maven2/'):
196
+ base_path = clean_url[len('repo1.maven.org/maven2/'):]
197
+ elif clean_url.startswith('dl.google.com/android/maven2/'):
198
+ base_path = clean_url[len('dl.google.com/android/maven2/'):]
199
+ else:
200
+ return None
201
+
202
+ base_path = base_path.rstrip('/')
203
+ # Strip file name if ends with known artifact extension.
204
+ if any(base_path.endswith(ext) for ext in ['.jar', '.pom', '.aar']):
205
+ base_path = '/'.join(base_path.split('/')[:-1])
206
+
207
+ parts = base_path.split('/')
208
+ if len(parts) < 2:
209
+ return None
210
+
211
+ version = None
212
+ artifact_id = None
213
+ if len(parts) >= 3:
214
+ potential_version = parts[-1]
215
+ potential_artifact = parts[-2]
216
+ if re.search(r'\d', potential_version):
217
+ version = potential_version
218
+ artifact_id = potential_artifact
219
+ group_parts = parts[:-2]
220
+ else:
221
+ artifact_id = parts[-1]
222
+ group_parts = parts[:-1]
223
+ else:
224
+ artifact_id = parts[-1]
225
+ group_parts = parts[:-1]
226
+
227
+ group_id = '.'.join(group_parts)
228
+ if not group_id or not artifact_id:
229
+ return None
230
+
231
+ maven_name = f"{group_id}:{artifact_id}"
232
+ return maven_name, version
233
+ except Exception as e:
234
+ logger.debug(f'Failed to parse direct Maven URL {url}: {e}')
235
+ return None
236
+
237
+
238
+ def get_new_link_with_version(link, pkg_type, oss_name, oss_version):
239
+ if pkg_type == "pypi":
240
+ link = f'https://pypi.org/project/{oss_name}/{oss_version}'
241
+ elif pkg_type == "maven":
242
+ oss_name = oss_name.replace(':', '/')
243
+ link = f'https://mvnrepository.com/artifact/{oss_name}/{oss_version}'
244
+ elif pkg_type == "npm" or pkg_type == "npm2":
245
+ link = f'https://www.npmjs.com/package/{oss_name}/v/{oss_version}'
246
+ elif pkg_type == "pub":
247
+ link = f'https://pub.dev/packages/{oss_name}/versions/{oss_version}'
248
+ elif pkg_type == "go":
249
+ if not oss_version.startswith('v'):
250
+ oss_version = f'v{oss_version}'
251
+ link = f'https://pkg.go.dev/{oss_name}@{oss_version}'
252
+ elif pkg_type == "cargo":
253
+ link = f'https://crates.io/crates/{oss_name}/{oss_version}'
254
+ return link
255
+
256
+
257
+ def get_latest_package_version(link, pkg_type, oss_name):
258
+ find_version = ''
259
+
260
+ try:
261
+ if pkg_type in ['npm', 'npm2']:
262
+ npm_response = requests.get(f"https://registry.npmjs.org/{oss_name}")
263
+ if npm_response.status_code == 200:
264
+ find_version = npm_response.json().get("dist-tags", {}).get("latest")
265
+ elif pkg_type == 'pypi':
266
+ find_version = str(latest(oss_name, at='pip', output_format='version', pre_ok=True))
267
+ elif pkg_type == 'maven':
268
+ maven_response = requests.get(f'https://api.deps.dev/v3alpha/systems/maven/packages/{oss_name}')
269
+ if maven_response.status_code == 200:
270
+ versions = maven_response.json().get('versions', [])
271
+ if versions:
272
+ # Some version entries may miss publishedAt; fallback to semantic version ordering.
273
+ def sem_key(vstr: str):
274
+ # Parse semantic version with optional prerelease label
275
+ # Examples: 1.9.0, 1.10.0-alpha, 2.0.0-rc
276
+ m = re.match(r'^(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:[-.]([A-Za-z0-9]+))?$', vstr)
277
+ if not m:
278
+ return (0, 0, 0, 999)
279
+ major = int(m.group(1) or 0)
280
+ minor = int(m.group(2) or 0)
281
+ patch = int(m.group(3) or 0)
282
+ label = (m.group(4) or '').lower()
283
+ # Assign label weights: stable > rc > beta > alpha
284
+ label_weight_map = {
285
+ 'alpha': -3,
286
+ 'beta': -2,
287
+ 'rc': -1
288
+ }
289
+ weight = label_weight_map.get(label, 0 if label == '' else -4)
290
+ return (major, minor, patch, weight)
291
+
292
+ with_pub = [v for v in versions if v.get('publishedAt')]
293
+ if with_pub:
294
+ cand = max(with_pub, key=lambda v: v.get('publishedAt'))
295
+ else:
296
+ decorated = []
297
+ for v in versions:
298
+ vkey = v.get('versionKey', {})
299
+ ver = vkey.get('version', '')
300
+ if ver:
301
+ decorated.append((sem_key(ver), ver, v))
302
+ if decorated:
303
+ decorated.sort(key=lambda t: t[0])
304
+ stable_candidates = [t for t in decorated if t[0][3] == 0]
305
+ if stable_candidates:
306
+ cand = stable_candidates[-1][2]
307
+ else:
308
+ cand = decorated[-1][2]
309
+ else:
310
+ cand = versions[-1]
311
+ find_version = cand.get('versionKey', {}).get('version', '')
312
+ elif pkg_type == 'pub':
313
+ pub_response = requests.get(f'https://pub.dev/api/packages/{oss_name}')
314
+ if pub_response.status_code == 200:
315
+ find_version = pub_response.json().get('latest').get('version')
316
+ elif pkg_type == 'go':
317
+ go_response = requests.get(f'https://proxy.golang.org/{oss_name}/@latest')
318
+ if go_response.status_code == 200:
319
+ find_version = go_response.json().get('Version')
320
+ if find_version.startswith('v'):
321
+ find_version = find_version[1:]
322
+ except Exception as e:
323
+ logger.info(f'Fail to get latest package version({link}:{e})')
324
+ return find_version
325
+
326
+
327
+ def get_downloadable_url(link, checkout_version):
16
328
 
329
+ ret = False
330
+ result_link = link
331
+
332
+ oss_name, oss_version, new_link, pkg_type = extract_name_version_from_link(link, checkout_version)
333
+ new_link = new_link.replace('http://', '')
334
+ new_link = new_link.replace('https://', '')
335
+
336
+ if pkg_type == "pypi":
337
+ ret, result_link = get_download_location_for_pypi(new_link)
338
+ elif pkg_type == "maven" or new_link.startswith('repo1.maven.org/') or new_link.startswith('dl.google.com/android/maven2/'):
339
+ ret, result_link = get_download_location_for_maven(new_link)
340
+ elif (pkg_type in ["npm", "npm2"]) or new_link.startswith('registry.npmjs.org/'):
341
+ ret, result_link = get_download_location_for_npm(new_link)
342
+ elif pkg_type == "pub":
343
+ ret, result_link = get_download_location_for_pub(new_link)
344
+ elif pkg_type == "go":
345
+ ret, result_link = get_download_location_for_go(new_link)
346
+ elif pkg_type == "cargo":
347
+ ret, result_link = get_download_location_for_cargo(new_link)
348
+ return ret, result_link, oss_name, oss_version, pkg_type
349
+
350
+
351
+ def get_download_location_for_cargo(link):
352
+ # get the url for downloading source file: https://crates.io/api/v1/crates/<name>/<version>/download
17
353
  ret = False
18
354
  new_link = ''
355
+ host = 'https://crates.io/api/v1/crates'
19
356
 
20
- link = link.replace('http://', '')
21
- link = link.replace('https://', '')
357
+ try:
358
+ dn_loc_re = re.findall(r'crates.io\/crates\/([^\/]+)\/?([^\/]*)', link)
359
+ if dn_loc_re:
360
+ oss_name = dn_loc_re[0][0]
361
+ oss_version = dn_loc_re[0][1]
362
+
363
+ new_link = f'{host}/{oss_name}/{oss_version}/download'
364
+ res = urlopen(new_link)
365
+ if res.getcode() == 200:
366
+ ret = True
367
+ else:
368
+ logger.warning(f'Cannot find the valid link for cargo (url:{new_link}')
369
+ except Exception as error:
370
+ ret = False
371
+ logger.warning(f'Cannot find the link for cargo (url:{link}({(new_link)})): {error}')
372
+
373
+ return ret, new_link
374
+
375
+
376
+ def get_download_location_for_go(link):
377
+ # get the url for downloading source file: https://proxy.golang.org/<module>/@v/VERSION.zip
378
+ ret = False
379
+ new_link = ''
380
+ host = 'https://proxy.golang.org'
22
381
 
23
- if link.startswith('pypi.org/'):
24
- ret, new_link = get_download_location_for_pypi(link)
25
- elif link.startswith('mvnrepository.com/artifact/') or link.startswith('repo1.maven.org/'):
26
- ret, new_link = get_download_location_for_maven(link)
27
- elif link.startswith('www.npmjs.com/') or link.startswith('registry.npmjs.org/'):
28
- ret, new_link = get_download_location_for_npm(link)
29
- elif link.startswith('pub.dev/'):
30
- ret, new_link = get_download_location_for_pub(link)
382
+ try:
383
+ dn_loc_re = re.findall(r'pkg.go.dev\/([^\@]+)\@?([^\/]*)', link)
384
+ if dn_loc_re:
385
+ oss_name = dn_loc_re[0][0]
386
+ if oss_name.endswith('/'):
387
+ oss_name = oss_name[:-1]
388
+ oss_version = dn_loc_re[0][1]
389
+
390
+ new_link = f'{host}/{oss_name}/@v/{oss_version}.zip'
391
+ try:
392
+ res = urlopen(new_link)
393
+ if res.getcode() == 200:
394
+ ret = True
395
+ else:
396
+ logger.warning(f'Cannot find the valid link for go (url:{new_link}')
397
+ except Exception as e:
398
+ logger.warning(f'Fail to find the valid link for go (url:{new_link}: {e}')
399
+ except Exception as error:
400
+ ret = False
401
+ logger.warning(f'Cannot find the link for go (url:{link}({(new_link)})): {error}')
31
402
 
32
403
  return ret, new_link
33
404
 
34
405
 
406
+ def get_available_wheel_urls(name, version):
407
+ try:
408
+ api_url = f'https://pypi.org/pypi/{name}/{version}/json'
409
+ response = requests.get(api_url)
410
+ if response.status_code == 200:
411
+ data = response.json()
412
+ wheel_urls = []
413
+
414
+ for file_info in data.get('urls', []):
415
+ if file_info.get('packagetype') == 'bdist_wheel':
416
+ wheel_urls.append(file_info.get('url'))
417
+
418
+ return wheel_urls
419
+ else:
420
+ logger.warning(f'Cannot get PyPI API data for {name}({version})')
421
+ return []
422
+
423
+ except Exception as error:
424
+ logger.warning(f'Failed to get wheel URLs from PyPI API: {error}')
425
+ return []
426
+
427
+
35
428
  def get_download_location_for_pypi(link):
36
- # get the url for downloading source file in pypi.org/project/(oss_name)/(oss_version)/#files
429
+ # get the url for downloading source file: https://docs.pypi.org/api/ Predictable URLs
37
430
  ret = False
38
431
  new_link = ''
432
+ host = 'https://files.pythonhosted.org'
39
433
 
40
434
  try:
41
435
  dn_loc_re = re.findall(r'pypi.org\/project\/?([^\/]*)\/?([^\/]*)', link)
42
436
  oss_name = dn_loc_re[0][0]
437
+ oss_name = re.sub(r"[-_.]+", "-", oss_name)
43
438
  oss_version = dn_loc_re[0][1]
44
439
 
45
- pypi_url = 'https://pypi.org/project/' + oss_name + '/' + oss_version + '/#files'
46
-
47
- content = urlopen(pypi_url).read().decode('utf8')
48
- bs_obj = BeautifulSoup(content, 'html.parser')
49
-
50
- card_file_list = bs_obj.findAll('div', {'class': 'card file__card'})
51
-
52
- for card_file in card_file_list:
53
- file_code = card_file.find('code').text
54
- if file_code == "source":
55
- new_link = card_file.find('a').attrs['href']
440
+ # 1. Source distribution 시도
441
+ new_link = f'{host}/packages/source/{oss_name[0]}/{oss_name}/{oss_name}-{oss_version}.tar.gz'
442
+ try:
443
+ res = urlopen(new_link)
444
+ if res.getcode() == 200:
56
445
  ret = True
57
- break
446
+ return ret, new_link
447
+ except Exception:
448
+ oss_name = re.sub(r"[-]+", "_", oss_name)
449
+ new_link = f'{host}/packages/source/{oss_name[0]}/{oss_name}/{oss_name}-{oss_version}.tar.gz'
450
+ try:
451
+ res = urlopen(new_link)
452
+ if res.getcode() == 200:
453
+ ret = True
454
+ return ret, new_link
455
+ except Exception:
456
+ pass
457
+
458
+ # 2. Source distribution이 없으면 wheel 파일들을 시도
459
+ wheel_urls = get_available_wheel_urls(oss_name, oss_version)
460
+
461
+ if wheel_urls:
462
+ # Pure Python wheel을 우선적으로 찾기
463
+ for wheel_url in wheel_urls:
464
+ if 'py3-none-any' in wheel_url or 'py2.py3-none-any' in wheel_url:
465
+ try:
466
+ res = urlopen(wheel_url)
467
+ if res.getcode() == 200:
468
+ ret = True
469
+ new_link = wheel_url
470
+ logger.info(f'Using wheel file : {wheel_url}')
471
+ return ret, new_link
472
+ except Exception:
473
+ continue
474
+
475
+ # Pure Python wheel이 없으면 첫 번째 wheel 시도
476
+ if wheel_urls:
477
+ try:
478
+ res = urlopen(wheel_urls[0])
479
+ if res.getcode() == 200:
480
+ ret = True
481
+ new_link = wheel_urls[0]
482
+ logger.info(f'Using wheel file : {wheel_urls[0]}')
483
+ return ret, new_link
484
+ except Exception:
485
+ pass
486
+
58
487
  except Exception as error:
59
488
  ret = False
60
- logger.warning('Cannot find the link for pypi (url:'+link+') '+str(error))
489
+ logger.warning(f'Cannot find the link for pypi (url:{link}({new_link})) e:{str(error)}')
61
490
 
62
491
  return ret, new_link
63
492
 
@@ -83,6 +512,13 @@ def get_download_location_for_maven(link):
83
512
  return ret, new_link
84
513
  else:
85
514
  dn_loc = 'https://' + link
515
+ elif link.startswith('dl.google.com/android/maven2/'):
516
+ if link.endswith('.jar'):
517
+ new_link = 'https://' + link
518
+ ret = True
519
+ return ret, new_link
520
+ else:
521
+ dn_loc = 'https://' + link
86
522
  else:
87
523
  raise Exception("not valid url for maven")
88
524
 
@@ -118,6 +554,7 @@ def get_download_location_for_npm(link):
118
554
  oss_name_npm = ""
119
555
  tar_name = ""
120
556
 
557
+ link = link.replace('%40', '@')
121
558
  if link.startswith('www.npmjs.com/') or link.startswith('registry.npmjs.org/'):
122
559
  try:
123
560
  dn_loc_split = link.split('/')
@@ -133,16 +570,9 @@ def get_download_location_for_npm(link):
133
570
  oss_name_npm = dn_loc_split[idx]
134
571
  tar_name = oss_name_npm
135
572
  oss_version = dn_loc_split[idx+2]
136
- except Exception:
137
- pass
138
573
 
139
- try:
140
- if not oss_version:
141
- stderr, stdout = npm_run('view', oss_name_npm, 'version')
142
- if stdout:
143
- oss_version = stdout.strip()
144
- tar_name = f"{tar_name}-{oss_version}"
145
- new_link = 'https://registry.npmjs.org/' + oss_name_npm + '/-/' + tar_name + '.tgz'
574
+ tar_name = f'{tar_name}-{oss_version}'
575
+ new_link = f'https://registry.npmjs.org/{oss_name_npm}/-/{tar_name}.tgz'
146
576
  ret = True
147
577
  except Exception as error:
148
578
  ret = False
@@ -158,7 +588,7 @@ def get_download_location_for_pub(link):
158
588
  # download url format : https://pub.dev/packages/(oss_name)/versions/(oss_version).tar.gz
159
589
  try:
160
590
  if link.startswith('pub.dev/packages'):
161
- new_link = 'https://{link}.tar.gz'
591
+ new_link = f'https://{link}.tar.gz'
162
592
  ret = True
163
593
 
164
594
  except Exception as error:
@@ -4,9 +4,9 @@
4
4
  # SPDX-License-Identifier: Apache-2.0
5
5
 
6
6
  import logging
7
- import os
7
+ from typing import List, Dict
8
8
  from fosslight_util.constant import LOGGER_NAME
9
- from fosslight_util.parsing_yaml import parsing_yml
9
+ from fosslight_util.oss_item import FileItem
10
10
 
11
11
  logger = logging.getLogger(LOGGER_NAME)
12
12
  VERSION = 'version'
@@ -14,12 +14,16 @@ LICENSE = 'license'
14
14
  NAME = 'name'
15
15
 
16
16
 
17
- def compare_yaml(before_file, after_file):
18
- before_oss_items, _, _ = parsing_yml(before_file, os.path.dirname(before_file))
19
- after_oss_items, _, _ = parsing_yml(after_file, os.path.dirname(after_file))
17
+ def compare_yaml(before_fileitems: List[FileItem], after_fileitems: List[FileItem]) -> Dict[str, List]:
18
+ bf_raw = []
19
+ af_raw = []
20
+ for bf in before_fileitems:
21
+ bf_raw.extend(bf.get_print_json())
22
+ for af in after_fileitems:
23
+ af_raw.extend(af.get_print_json())
20
24
 
21
- before_items = get_merged_item(before_oss_items)
22
- after_items = get_merged_item(after_oss_items)
25
+ before_items = get_merged_item(bf_raw)
26
+ after_items = get_merged_item(af_raw)
23
27
 
24
28
  new_before = []
25
29
  for bi in before_items:
@@ -72,13 +76,18 @@ def compare_yaml(before_file, after_file):
72
76
  def get_merged_item(oss_items):
73
77
  item_list = []
74
78
  for oi in oss_items:
75
- if oi.exclude:
79
+ if oi.get("exclude", None):
76
80
  continue
77
- item_info = {NAME: oi.name, VERSION: oi.version, LICENSE: oi.license}
81
+ oi_name = oi.get("name", '')
82
+ oi_version = oi.get("version", '')
83
+ oi_license = oi.get("license", '')
84
+ if not (oi_name and oi_version and oi_license):
85
+ continue
86
+ item_info = {NAME: oi_name, VERSION: oi_version, LICENSE: oi_license}
78
87
 
79
- filtered = next(filter(lambda oss_dict: oss_dict[NAME] == oi.name and oss_dict[VERSION] == oi.version, item_list), None)
88
+ filtered = next(filter(lambda oss_dict: oss_dict[NAME] == oi_name and oss_dict[VERSION] == oi_version, item_list), None)
80
89
  if filtered:
81
- filtered[LICENSE].extend(oi.license)
90
+ filtered[LICENSE].extend(oi_license)
82
91
  filtered[LICENSE] = list(set(filtered[LICENSE]))
83
92
  else:
84
93
  item_list.append(item_info)
@@ -14,3 +14,38 @@ supported_sheet_and_scanner = {'SRC': FL_SOURCE,
14
14
  f'SRC_{FL_DEPENDENCY}': FL_DEPENDENCY,
15
15
  f'BIN_{FL_BINARY}': FL_BINARY,
16
16
  f'DEP_{FL_DEPENDENCY}': FL_DEPENDENCY}
17
+
18
+ FOSSLIGHT_SCANNER = 'fosslight_scanner'
19
+ FOSSLIGHT_SOURCE = 'fosslight_source'
20
+ FOSSLIGHT_DEPENDENCY = 'fosslight_dependency'
21
+ FOSSLIGHT_BINARY = 'fosslight_binary'
22
+
23
+ SHEET_NAME_FOR_SCANNER = {
24
+ FOSSLIGHT_SOURCE: 'SRC_FL_Source',
25
+ FOSSLIGHT_BINARY: 'BIN_FL_Binary',
26
+ FOSSLIGHT_DEPENDENCY: 'DEP_FL_Dependency'
27
+ }
28
+
29
+ # Github : https://github.com/(owner)/(repo)
30
+ # npm : https://www.npmjs.com/package/(package)/v/(version)
31
+ # npm2 : https://www.npmjs.com/package/@(group)/(package)/v/(version)
32
+ # pypi : https://pypi.org/project/(oss_name)/(version)
33
+ # pypi2 : https://files.pythonhosted.org/packages/source/(alphabet)/(oss_name)/(oss_name)-(version).tar.gz
34
+ # Maven: https://mvnrepository.com/artifact/(group)/(artifact)/(version)
35
+ # pub: https://pub.dev/packages/(package)/versions/(version)
36
+ # Cocoapods : https://cocoapods.org/(package)
37
+ # go : https://pkg.go.dev/(package_name_with_slash)@(version)
38
+ # cargo : https://crates.io/crates/(crate_name)/(version)
39
+ PKG_PATTERN = {
40
+ "pypi": r'https?:\/\/pypi\.org\/project\/([^\/]+)[\/]?([^\/]*)',
41
+ "pypi2": r'https?:\/\/files\.pythonhosted\.org\/packages\/source\/[\w]\/([^\/]+)\/[\S]+-([^\-]+)\.tar\.gz',
42
+ "maven": r'https?:\/\/mvnrepository\.com\/artifact\/([^\/]+)\/([^\/]+)\/?([^\/]*)',
43
+ "maven_repo1": r'https?:\/\/repo1\.maven\.org\/maven2\/(.*)',
44
+ "maven_google": r'https?:\/\/dl\.google\.com\/android\/maven2\/(.*)',
45
+ "npm": r'https?:\/\/www\.npmjs\.com\/package\/([^\/\@]+)(?:\/v\/)?([^\/]*)',
46
+ "npm2": r'https?:\/\/www\.npmjs\.com\/package\/(\@[^\/]+\/[^\/]+)(?:\/v\/)?([^\/]*)',
47
+ "pub": r'https?:\/\/pub\.dev\/packages\/([^\/]+)(?:\/versions\/)?([^\/]*)',
48
+ "cocoapods": r'https?:\/\/cocoapods\.org\/pods\/([^\/]+)',
49
+ "go": r'https?:\/\/pkg.go.dev\/([^\@]+)\@?v?([^\/]*)',
50
+ "cargo": r'https?:\/\/crates\.io\/crates\/([^\/]+)\/?([^\/]*)',
51
+ }