fosslight-util 2.1.29__py3-none-any.whl → 2.1.31__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_pom_license.py +120 -0
- fosslight_util/help.py +44 -11
- {fosslight_util-2.1.29.dist-info → fosslight_util-2.1.31.dist-info}/METADATA +2 -1
- {fosslight_util-2.1.29.dist-info → fosslight_util-2.1.31.dist-info}/RECORD +8 -7
- {fosslight_util-2.1.29.dist-info → fosslight_util-2.1.31.dist-info}/WHEEL +0 -0
- {fosslight_util-2.1.29.dist-info → fosslight_util-2.1.31.dist-info}/entry_points.txt +0 -0
- {fosslight_util-2.1.29.dist-info → fosslight_util-2.1.31.dist-info}/licenses/LICENSE +0 -0
- {fosslight_util-2.1.29.dist-info → fosslight_util-2.1.31.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,120 @@
|
|
|
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 logging
|
|
8
|
+
import urllib.request
|
|
9
|
+
from urllib.error import URLError, HTTPError
|
|
10
|
+
from defusedxml.ElementTree import fromstring as xml_fromstring
|
|
11
|
+
import fosslight_util.constant as constant
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(constant.LOGGER_NAME)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def get_license_from_pom(group_id: str = None,
|
|
17
|
+
artifact_id: str = None,
|
|
18
|
+
version: str = None,
|
|
19
|
+
pom_path: str = None,
|
|
20
|
+
check_parent: bool = True) -> str:
|
|
21
|
+
|
|
22
|
+
def build_urls(g, a, v):
|
|
23
|
+
group_path = g.replace('.', '/')
|
|
24
|
+
name = f"{a}-{v}.pom"
|
|
25
|
+
repo1 = f"https://repo1.maven.org/maven2/{group_path}/{a}/{v}/{name}"
|
|
26
|
+
google = f"https://dl.google.com/android/maven2/{group_path}/{a}/{v}/{name}"
|
|
27
|
+
return [repo1, google]
|
|
28
|
+
|
|
29
|
+
def fetch_pom(g, a, v):
|
|
30
|
+
for url in build_urls(g, a, v):
|
|
31
|
+
try:
|
|
32
|
+
with urllib.request.urlopen(url) as resp:
|
|
33
|
+
return resp.read().decode('utf-8')
|
|
34
|
+
except (HTTPError, URLError):
|
|
35
|
+
continue
|
|
36
|
+
return None
|
|
37
|
+
|
|
38
|
+
def extract_licenses(root):
|
|
39
|
+
licenses_elem = root.find('{*}licenses')
|
|
40
|
+
if licenses_elem is not None:
|
|
41
|
+
names = []
|
|
42
|
+
for lic in licenses_elem.findall('{*}license'):
|
|
43
|
+
name = lic.findtext('{*}name')
|
|
44
|
+
if name:
|
|
45
|
+
names.append(name.replace(',', ''))
|
|
46
|
+
if names:
|
|
47
|
+
return ', '.join(names)
|
|
48
|
+
return None
|
|
49
|
+
|
|
50
|
+
def extract_parent_info(root):
|
|
51
|
+
parent = root.find('{*}parent')
|
|
52
|
+
if parent is not None:
|
|
53
|
+
g = parent.findtext('{*}groupId') or parent.findtext('groupId')
|
|
54
|
+
a = parent.findtext('{*}artifactId') or parent.findtext('artifactId')
|
|
55
|
+
v = parent.findtext('{*}version') or parent.findtext('version')
|
|
56
|
+
if g and a and v:
|
|
57
|
+
return g, a, v
|
|
58
|
+
return None, None, None
|
|
59
|
+
|
|
60
|
+
visited = set()
|
|
61
|
+
|
|
62
|
+
def find_license_in_pom_recursive(g, a, v, check_parent_flag):
|
|
63
|
+
key = (g, a, v)
|
|
64
|
+
if key in visited:
|
|
65
|
+
return ''
|
|
66
|
+
visited.add(key)
|
|
67
|
+
content = fetch_pom(g, a, v)
|
|
68
|
+
if not content:
|
|
69
|
+
return ''
|
|
70
|
+
try:
|
|
71
|
+
root = xml_fromstring(content)
|
|
72
|
+
except Exception:
|
|
73
|
+
return ''
|
|
74
|
+
licenses = extract_licenses(root)
|
|
75
|
+
if licenses:
|
|
76
|
+
return licenses
|
|
77
|
+
if not check_parent_flag:
|
|
78
|
+
return ''
|
|
79
|
+
pg, pa, pv = extract_parent_info(root)
|
|
80
|
+
if pg and pa and pv:
|
|
81
|
+
return find_license_in_pom_recursive(pg, pa, pv, check_parent_flag)
|
|
82
|
+
return ''
|
|
83
|
+
|
|
84
|
+
try:
|
|
85
|
+
if pom_path:
|
|
86
|
+
if not os.path.exists(pom_path):
|
|
87
|
+
logger.warning(f"POM file not found: {pom_path}")
|
|
88
|
+
return ''
|
|
89
|
+
try:
|
|
90
|
+
with open(pom_path, 'r', encoding='utf-8') as f:
|
|
91
|
+
content = f.read()
|
|
92
|
+
xml_start = content.find('<?xml')
|
|
93
|
+
if xml_start > 0:
|
|
94
|
+
content = content[xml_start:]
|
|
95
|
+
elif xml_start == -1:
|
|
96
|
+
root_start = content.find('<project')
|
|
97
|
+
if root_start > 0:
|
|
98
|
+
content = content[root_start:]
|
|
99
|
+
root = xml_fromstring(content)
|
|
100
|
+
except Exception as e:
|
|
101
|
+
logger.warning(f"Failed to parse POM file {pom_path}: {e}")
|
|
102
|
+
return ''
|
|
103
|
+
|
|
104
|
+
licenses = extract_licenses(root)
|
|
105
|
+
if licenses:
|
|
106
|
+
return licenses
|
|
107
|
+
if not check_parent:
|
|
108
|
+
return ''
|
|
109
|
+
pg, pa, pv = extract_parent_info(root)
|
|
110
|
+
if pg and pa and pv:
|
|
111
|
+
return find_license_in_pom_recursive(pg, pa, pv, check_parent)
|
|
112
|
+
|
|
113
|
+
logger.debug(f"No license info found in local POM: {pom_path}, Retry with remote fetch.")
|
|
114
|
+
|
|
115
|
+
if not (group_id and artifact_id and version):
|
|
116
|
+
return ''
|
|
117
|
+
return find_license_in_pom_recursive(group_id, artifact_id, version, check_parent)
|
|
118
|
+
except Exception as e:
|
|
119
|
+
logger.warning(f"Error getting license from POM: {e}")
|
|
120
|
+
return ''
|
fosslight_util/help.py
CHANGED
|
@@ -3,22 +3,55 @@
|
|
|
3
3
|
# Copyright (c) 2021 LG Electronics Inc.
|
|
4
4
|
# SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
import sys
|
|
6
|
+
import os
|
|
6
7
|
try:
|
|
7
8
|
from importlib.metadata import version, PackageNotFoundError
|
|
8
9
|
except ImportError:
|
|
9
10
|
from importlib_metadata import version, PackageNotFoundError # Python <3.8
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
12
|
+
|
|
13
|
+
def _supports_color():
|
|
14
|
+
"""Check if the terminal supports color."""
|
|
15
|
+
# Check if output is redirected or if NO_COLOR environment variable is set
|
|
16
|
+
if not hasattr(sys.stdout, 'isatty') or not sys.stdout.isatty():
|
|
17
|
+
return False
|
|
18
|
+
if os.environ.get('NO_COLOR'):
|
|
19
|
+
return False
|
|
20
|
+
# Windows cmd.exe support (Windows 10+)
|
|
21
|
+
if sys.platform == 'win32':
|
|
22
|
+
return True
|
|
23
|
+
# Unix-like systems
|
|
24
|
+
return True
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
if _supports_color():
|
|
28
|
+
_RESET = "\033[0m"
|
|
29
|
+
_BOLD = "\033[1m"
|
|
30
|
+
_C1 = "\033[1;38;2;230;140;165m" # Toned Down Light Pink
|
|
31
|
+
_C2 = "\033[1;38;2;217;115;153m" # Toned Down Pink
|
|
32
|
+
_C3 = "\033[1;38;2;242;115;166m" # Medium Light Pink
|
|
33
|
+
_C4 = "\033[1;38;2;230;77;140m" # Pink
|
|
34
|
+
_C5 = "\033[1;38;2;217;38;115m" # Pink-Red
|
|
35
|
+
_C6 = "\033[1;38;2;191;19;89m" # Medium Red
|
|
36
|
+
_C7 = "\033[1;38;2;165;0;52m" # Burgundy (#A50034) - Middle
|
|
37
|
+
_C8 = "\033[1;38;2;140;0;44m" # Dark Burgundy
|
|
38
|
+
_C9 = "\033[1;38;2;115;0;36m" # Darker Burgundy
|
|
39
|
+
_C10 = "\033[1;38;2;89;0;28m" # Very Dark Burgundy
|
|
40
|
+
_STAR = "\033[1;38;5;226m" # Bright Yellow for stars
|
|
41
|
+
else:
|
|
42
|
+
# No color support
|
|
43
|
+
_RESET = _BOLD = _C1 = _C2 = _C3 = _C4 = _C5 = _C6 = _C7 = _C8 = _C9 = _C10 = _STAR = ""
|
|
44
|
+
|
|
45
|
+
_HELP_MESSAGE_COMMON = f"""
|
|
46
|
+
{_STAR} ═════════════════════════════════════════════════════════════════════{_RESET}
|
|
47
|
+
{_C1} ███████╗ {_C1}██████╗ {_C2}███████╗ {_C2}███████╗{_C3}██╗ {_C3}██╗ {_C4}██████╗ {_C5}██╗ {_C5}██╗{_C6}████████╗{_RESET}
|
|
48
|
+
{_C1} ██╔════╝{_C2}██╔═══██╗{_C2}██╔════╝ {_C3}██╔════╝{_C3}██║ {_C4}██║{_C4}██╔════╝ {_C5}██║ {_C6}██║{_C6}╚══██╔══╝{_RESET}
|
|
49
|
+
{_C2} █████╗ {_C2}██║ ██║{_C3}███████╗ {_C3}███████╗{_C4}██║ {_C5}██║{_C5}██║ ███╗{_C6}███████║{_C7} {_C7}██║ {_RESET}
|
|
50
|
+
{_C3} ██╔══╝ {_C3}██║ ██║{_C4}╚════██║ {_C4}╚════██║{_C5}██║ {_C6}██║{_C6}██║ ██║{_C7}██╔══██║{_C8} {_C8}██║ {_RESET}
|
|
51
|
+
{_C3} ██║ {_C4}╚██████╔╝{_C5}███████║ {_C5}███████║{_C6}███████╗{_C7}██║{_C7}╚██████╔╝{_C8}██║ {_C9}██║ {_C9}██║ {_RESET}
|
|
52
|
+
{_C4} ╚═╝ {_C5}╚═════╝ {_C5}╚══════╝ {_C6}╚══════╝{_C7}╚══════╝{_C8}╚═╝ {_C8}╚═════╝ {_C9}╚═╝ {_C10}╚═╝ {_C10}╚═╝ {_RESET}
|
|
53
|
+
{_STAR} ═════════════════════════════════════════════════════════════════════{_RESET}
|
|
54
|
+
{_STAR} ✨ Open Source Analysis Tool ✨{_RESET}
|
|
22
55
|
"""
|
|
23
56
|
|
|
24
57
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fosslight_util
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.31
|
|
4
4
|
Summary: FOSSLight Util
|
|
5
5
|
Home-page: https://github.com/fosslight/fosslight_util
|
|
6
6
|
Download-URL: https://github.com/fosslight/fosslight_util
|
|
@@ -28,6 +28,7 @@ Requires-Dist: numpy
|
|
|
28
28
|
Requires-Dist: requests
|
|
29
29
|
Requires-Dist: GitPython
|
|
30
30
|
Requires-Dist: cyclonedx-python-lib==8.5.*; sys_platform == "linux"
|
|
31
|
+
Requires-Dist: defusedxml
|
|
31
32
|
Dynamic: author
|
|
32
33
|
Dynamic: classifier
|
|
33
34
|
Dynamic: description
|
|
@@ -6,7 +6,8 @@ fosslight_util/correct.py,sha256=1WEAL-9_KhjFPLucPhv0PNN3K7avm0z8mU6sTuSyeHM,386
|
|
|
6
6
|
fosslight_util/cover.py,sha256=qqqKzxqFwKimal764FaugRUBcHWdeKt8af6xeK0mH8E,2040
|
|
7
7
|
fosslight_util/download.py,sha256=AWwD3FWhF-bMagWINJ-Dg1VMuycXbe8VXX7qQ09YjYs,23565
|
|
8
8
|
fosslight_util/exclude.py,sha256=fDmBsZJ_F7O9Oh2T-07R03XNbElo1tFaf_z01KfSAqU,2399
|
|
9
|
-
fosslight_util/
|
|
9
|
+
fosslight_util/get_pom_license.py,sha256=x4_RHpM91s01j1OUWpKIxUjTGDH6y5AxTNDGkMajs4I,4253
|
|
10
|
+
fosslight_util/help.py,sha256=nMS7TkrjFeBCwxHDrD1yFLScLhXIh3t_FuQsZJUBP0w,5084
|
|
10
11
|
fosslight_util/oss_item.py,sha256=8890JHb5ZoKQWAwN7Fl8badnlYatJtF4MVJz1rdS4yQ,6938
|
|
11
12
|
fosslight_util/output_format.py,sha256=BP23LspxawDZ_a99oWLVKWUQ-G7P5uoUpjEXhkRFKwc,8801
|
|
12
13
|
fosslight_util/parsing_yaml.py,sha256=2zx_N5lMkXT1dRmfJMpzlrru-y_2F_CkVbGlba6vQpU,5380
|
|
@@ -24,9 +25,9 @@ fosslight_util/write_yaml.py,sha256=QlEKoIPQsEaYERfbP53TeKgnllYzhLQWm5wYjnWtVjE,
|
|
|
24
25
|
fosslight_util/resources/frequentLicenselist.json,sha256=GUhzK6tu7ok10fekOnmVmUgIGRC-acGABZKTNKfDyYA,4776157
|
|
25
26
|
fosslight_util/resources/frequent_license_nick_list.json,sha256=ryU2C_6ZxHbz90_sUN9OvI9GXkCMLu7oGcmd9W79YYo,5005
|
|
26
27
|
fosslight_util/resources/licenses.json,sha256=mK55z-bhY7Mjpj2KsO1crKGGL-X3F6MBFQJ0zLlx010,240843
|
|
27
|
-
fosslight_util-2.1.
|
|
28
|
-
fosslight_util-2.1.
|
|
29
|
-
fosslight_util-2.1.
|
|
30
|
-
fosslight_util-2.1.
|
|
31
|
-
fosslight_util-2.1.
|
|
32
|
-
fosslight_util-2.1.
|
|
28
|
+
fosslight_util-2.1.31.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
29
|
+
fosslight_util-2.1.31.dist-info/METADATA,sha256=aAyYCFccvQnt0KDxkH4JtzhCubqG6Z5OXQ60yI7dmR8,6365
|
|
30
|
+
fosslight_util-2.1.31.dist-info/WHEEL,sha256=SmOxYU7pzNKBqASvQJ7DjX3XGUF92lrGhMb3R6_iiqI,91
|
|
31
|
+
fosslight_util-2.1.31.dist-info/entry_points.txt,sha256=0yZggRWNwDaClDG8UmUA10UFG8cVX3Jiy5gG9nW7hJs,68
|
|
32
|
+
fosslight_util-2.1.31.dist-info/top_level.txt,sha256=2qyYWGLakgBRy4BqoBNt-I5C29tBr_e93e5e1pbuTGA,15
|
|
33
|
+
fosslight_util-2.1.31.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|