fosslight-dependency 4.1.18__py3-none-any.whl → 4.1.20__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_dependency/_analyze_dependency.py +2 -2
- fosslight_dependency/_help.py +1 -0
- fosslight_dependency/_package_manager.py +2 -0
- fosslight_dependency/package_manager/Npm.py +8 -8
- fosslight_dependency/package_manager/Pypi.py +96 -94
- fosslight_dependency/run_dependency_scanner.py +96 -58
- {fosslight_dependency-4.1.18.dist-info → fosslight_dependency-4.1.20.dist-info}/METADATA +8 -7
- {fosslight_dependency-4.1.18.dist-info → fosslight_dependency-4.1.20.dist-info}/RECORD +15 -15
- {fosslight_dependency-4.1.18.dist-info → fosslight_dependency-4.1.20.dist-info}/entry_points.txt +0 -1
- {fosslight_dependency-4.1.18.dist-info → fosslight_dependency-4.1.20.dist-info}/Apache-2.0.txt +0 -0
- {fosslight_dependency-4.1.18.dist-info → fosslight_dependency-4.1.20.dist-info}/LICENSE +0 -0
- {fosslight_dependency-4.1.18.dist-info → fosslight_dependency-4.1.20.dist-info}/LicenseRef-3rd_party_licenses.txt +0 -0
- {fosslight_dependency-4.1.18.dist-info → fosslight_dependency-4.1.20.dist-info}/MIT.txt +0 -0
- {fosslight_dependency-4.1.18.dist-info → fosslight_dependency-4.1.20.dist-info}/WHEEL +0 -0
- {fosslight_dependency-4.1.18.dist-info → fosslight_dependency-4.1.20.dist-info}/top_level.txt +0 -0
@@ -92,11 +92,11 @@ def analyze_dependency(package_manager_name, input_dir, output_dir, pip_activate
|
|
92
92
|
package_manager.parse_oss_information_for_pnpm()
|
93
93
|
package_dep_item_list.extend(package_manager.dep_items)
|
94
94
|
if ret:
|
95
|
-
logger.warning(f"### Complete to analyze: {package_manager_name}")
|
95
|
+
logger.warning(f"### Complete to analyze: {package_manager_name}({input_dir}: {','.join(manifest_file_name)})")
|
96
96
|
if package_manager.cover_comment:
|
97
97
|
cover_comment = package_manager.cover_comment
|
98
98
|
else:
|
99
|
-
logger.error(f"### Fail to analyze: {package_manager_name}")
|
99
|
+
logger.error(f"### Fail to analyze: {package_manager_name}({input_dir}: {','.join(manifest_file_name)})")
|
100
100
|
|
101
101
|
del package_manager
|
102
102
|
|
fosslight_dependency/_help.py
CHANGED
@@ -46,6 +46,7 @@ _HELP_MESSAGE_DEPENDENCY = """
|
|
46
46
|
\t\t\t\t\t--graph-path option is required
|
47
47
|
--direct\t\t\t Print the direct/transitive dependency type in comment.
|
48
48
|
\t\tChoice 'True' or 'False'. (default:True)
|
49
|
+
-r\t\t\t\t Recursive mode. Scan all subdirectories for manifest files.
|
49
50
|
--notice\t\t\t Print the open source license notice text.
|
50
51
|
|
51
52
|
Required only for swift, carthage
|
@@ -108,6 +108,7 @@ class PackageManager:
|
|
108
108
|
cmd_gradle = "./gradlew"
|
109
109
|
else:
|
110
110
|
ret_task = False
|
111
|
+
self.set_direct_dependencies(False)
|
111
112
|
logger.warning('No gradlew file exists (Skip to find dependencies relationship.).')
|
112
113
|
if ret_plugin:
|
113
114
|
logger.warning('Also it cannot run android-dependency-scanning plugin.')
|
@@ -153,6 +154,7 @@ class PackageManager:
|
|
153
154
|
shutil.move(module_gradle_backup, module_build_gradle)
|
154
155
|
if os.path.isfile(self.input_file_name):
|
155
156
|
logger.info(f'Found {self.input_file_name}, skip to run plugin.')
|
157
|
+
self.set_direct_dependencies(False)
|
156
158
|
ret_task = True
|
157
159
|
return ret_task
|
158
160
|
|
@@ -31,12 +31,12 @@ class Npm(PackageManager):
|
|
31
31
|
super().__init__(self.package_manager_name, self.dn_url, input_dir, output_dir)
|
32
32
|
|
33
33
|
def __del__(self):
|
34
|
-
if os.path.isfile(self.input_file_name):
|
35
|
-
os.remove(self.input_file_name)
|
34
|
+
if os.path.isfile(os.path.join(self.input_dir, self.input_file_name)):
|
35
|
+
os.remove(os.path.join(self.input_dir, self.input_file_name))
|
36
36
|
if self.flag_tmp_node_modules:
|
37
|
-
shutil.rmtree(node_modules, ignore_errors=True)
|
38
|
-
if os.path.exists(self.tmp_custom_json):
|
39
|
-
os.remove(self.tmp_custom_json)
|
37
|
+
shutil.rmtree(os.path.join(self.input_dir, node_modules), ignore_errors=True)
|
38
|
+
if os.path.exists(os.path.join(self.input_dir, self.tmp_custom_json)):
|
39
|
+
os.remove(os.path.join(self.input_dir, self.tmp_custom_json))
|
40
40
|
|
41
41
|
def run_plugin(self):
|
42
42
|
ret = self.start_license_checker()
|
@@ -122,9 +122,9 @@ class Npm(PackageManager):
|
|
122
122
|
if len(rel_json) < 1:
|
123
123
|
ret = False
|
124
124
|
else:
|
125
|
-
self.package_name = f'{rel_json[_name]}({rel_json
|
125
|
+
self.package_name = f'{rel_json[_name]}({rel_json.get(_version, "")})'
|
126
126
|
if _dependencies in rel_json:
|
127
|
-
self.parse_rel_dependencies(rel_json[_name], rel_json
|
127
|
+
self.parse_rel_dependencies(rel_json[_name], rel_json.get(_version, ""), rel_json[_dependencies])
|
128
128
|
except Exception as e:
|
129
129
|
ret = False
|
130
130
|
err_msg = e
|
@@ -178,7 +178,7 @@ class Npm(PackageManager):
|
|
178
178
|
|
179
179
|
oss_item.download_location = f"{self.dn_url}{oss_init_name}/v/{oss_item.version}"
|
180
180
|
dn_loc = f"{self.dn_url}{oss_init_name}"
|
181
|
-
dep_item.purl = get_url_to_purl(
|
181
|
+
dep_item.purl = get_url_to_purl(oss_item.download_location, self.package_manager_name)
|
182
182
|
purl_dict[f'{oss_init_name}({oss_item.version})'] = dep_item.purl
|
183
183
|
if d[_repository]:
|
184
184
|
dn_loc = d[_repository]
|
@@ -13,7 +13,7 @@ import re
|
|
13
13
|
import fosslight_util.constant as constant
|
14
14
|
import fosslight_dependency.constant as const
|
15
15
|
from fosslight_dependency._package_manager import PackageManager
|
16
|
-
from fosslight_dependency._package_manager import
|
16
|
+
from fosslight_dependency._package_manager import get_url_to_purl, check_license_name
|
17
17
|
from fosslight_dependency.dependency_item import DependencyItem, change_dependson_to_purl
|
18
18
|
from fosslight_util.oss_item import OssItem
|
19
19
|
|
@@ -26,7 +26,6 @@ class Pypi(PackageManager):
|
|
26
26
|
dn_url = 'https://pypi.org/project/'
|
27
27
|
venv_tmp_dir = 'venv_osc_dep_tmp'
|
28
28
|
tmp_file_name = "tmp_pip_license_output.json"
|
29
|
-
tmp_pip_license_info_file_name = "tmp_pip_license_info_output.json"
|
30
29
|
tmp_deptree_file = "tmp_pipdeptree.json"
|
31
30
|
pip_activate_cmd = ''
|
32
31
|
pip_deactivate_cmd = ''
|
@@ -41,9 +40,6 @@ class Pypi(PackageManager):
|
|
41
40
|
if os.path.isfile(self.tmp_file_name):
|
42
41
|
os.remove(self.tmp_file_name)
|
43
42
|
|
44
|
-
if os.path.isfile(self.tmp_pip_license_info_file_name):
|
45
|
-
os.remove(self.tmp_pip_license_info_file_name)
|
46
|
-
|
47
43
|
shutil.rmtree(self.venv_tmp_dir, ignore_errors=True)
|
48
44
|
|
49
45
|
if os.path.isfile(self.tmp_deptree_file):
|
@@ -73,7 +69,7 @@ class Pypi(PackageManager):
|
|
73
69
|
ret = self.create_virtualenv()
|
74
70
|
|
75
71
|
if ret:
|
76
|
-
ret = self.
|
72
|
+
ret = self.start_pip_inspect()
|
77
73
|
|
78
74
|
return ret
|
79
75
|
|
@@ -103,7 +99,7 @@ class Pypi(PackageManager):
|
|
103
99
|
activate_cmd = os.path.join(self.venv_tmp_dir, "Scripts", "activate.bat")
|
104
100
|
cmd_separator = "&"
|
105
101
|
else:
|
106
|
-
create_venv_cmd = f"
|
102
|
+
create_venv_cmd = f"virtualenv -p python3 {self.venv_tmp_dir}"
|
107
103
|
activate_cmd = ". " + os.path.join(venv_path, "bin", "activate")
|
108
104
|
cmd_separator = ";"
|
109
105
|
|
@@ -117,11 +113,12 @@ class Pypi(PackageManager):
|
|
117
113
|
return False
|
118
114
|
|
119
115
|
deactivate_cmd = "deactivate"
|
116
|
+
pip_upgrade_cmd = "pip install --upgrade pip"
|
120
117
|
|
121
118
|
self.set_pip_activate_cmd(activate_cmd)
|
122
119
|
self.set_pip_deactivate_cmd(deactivate_cmd)
|
123
120
|
|
124
|
-
cmd_list = [create_venv_cmd, activate_cmd, install_cmd, deactivate_cmd]
|
121
|
+
cmd_list = [create_venv_cmd, activate_cmd, install_cmd, pip_upgrade_cmd, deactivate_cmd]
|
125
122
|
cmd = cmd_separator.join(cmd_list)
|
126
123
|
|
127
124
|
try:
|
@@ -139,9 +136,9 @@ class Pypi(PackageManager):
|
|
139
136
|
try:
|
140
137
|
if (not ret) and (self.platform != const.WINDOWS):
|
141
138
|
ret = True
|
142
|
-
create_venv_cmd = f"
|
139
|
+
create_venv_cmd = f"python3 -m venv {self.venv_tmp_dir}"
|
143
140
|
|
144
|
-
cmd_list = [create_venv_cmd, activate_cmd, install_cmd, deactivate_cmd]
|
141
|
+
cmd_list = [create_venv_cmd, activate_cmd, install_cmd, pip_upgrade_cmd, deactivate_cmd]
|
145
142
|
cmd = cmd_separator.join(cmd_list)
|
146
143
|
cmd_ret = subprocess.run(cmd, shell=True, stderr=subprocess.PIPE)
|
147
144
|
if cmd_ret.returncode != 0:
|
@@ -160,14 +157,9 @@ class Pypi(PackageManager):
|
|
160
157
|
|
161
158
|
return ret
|
162
159
|
|
163
|
-
def
|
160
|
+
def start_pip_inspect(self):
|
164
161
|
ret = True
|
165
|
-
pip_licenses = 'pip-licenses'
|
166
|
-
prettytable = 'prettytable'
|
167
|
-
wcwidth = 'wcwidth'
|
168
162
|
pipdeptree = 'pipdeptree'
|
169
|
-
pip_licenses_default_options = ' --from=mixed --with-url --format=json --with-license-file'
|
170
|
-
pip_licenses_system_option = ' --with-system -p '
|
171
163
|
tmp_pip_list = "tmp_list.txt"
|
172
164
|
python_cmd = "python -m"
|
173
165
|
|
@@ -193,11 +185,21 @@ class Pypi(PackageManager):
|
|
193
185
|
command_list = [activate_command, pip_list_command, deactivate_command]
|
194
186
|
command = command_separator.join(command_list)
|
195
187
|
|
188
|
+
exists_pipdeptree = False
|
196
189
|
try:
|
197
190
|
cmd_ret = subprocess.call(command, shell=True)
|
198
191
|
if cmd_ret != 0:
|
199
192
|
ret = False
|
200
193
|
err_msg = f"cmd ret code({cmd_ret})"
|
194
|
+
else:
|
195
|
+
if os.path.isfile(tmp_pip_list):
|
196
|
+
with open(tmp_pip_list, 'r', encoding='utf-8') as pip_list_file:
|
197
|
+
for pip_list in pip_list_file.readlines():
|
198
|
+
pip_list_name = pip_list.split('==')[0]
|
199
|
+
if pip_list_name == pipdeptree:
|
200
|
+
exists_pipdeptree = True
|
201
|
+
break
|
202
|
+
os.remove(tmp_pip_list)
|
201
203
|
except Exception as e:
|
202
204
|
ret = False
|
203
205
|
err_msg = str(e)
|
@@ -206,63 +208,11 @@ class Pypi(PackageManager):
|
|
206
208
|
logger.error(f"Failed to freeze dependencies ({command}): {err_msg})")
|
207
209
|
return False
|
208
210
|
|
209
|
-
exists_pip_licenses = False
|
210
|
-
exists_prettytable = False
|
211
|
-
exists_wcwidth = False
|
212
|
-
pip_license_pkg_list = []
|
213
|
-
uninstall_pkg_list = []
|
214
|
-
exists_pipdeptree = False
|
215
|
-
|
216
|
-
if os.path.isfile(tmp_pip_list):
|
217
|
-
try:
|
218
|
-
with open(tmp_pip_list, 'r', encoding='utf-8') as pip_list_file:
|
219
|
-
for pip_list in pip_list_file.readlines():
|
220
|
-
pip_list_name = pip_list.split('==')[0]
|
221
|
-
if pip_list_name == pip_licenses:
|
222
|
-
exists_pip_licenses = True
|
223
|
-
if pip_list_name == prettytable:
|
224
|
-
exists_prettytable = True
|
225
|
-
if pip_list_name == wcwidth:
|
226
|
-
exists_wcwidth = True
|
227
|
-
if pip_list_name == pipdeptree:
|
228
|
-
exists_pipdeptree = True
|
229
|
-
os.remove(tmp_pip_list)
|
230
|
-
except Exception as e:
|
231
|
-
logger.error(f"Failed to read freezed package list file: {e}")
|
232
|
-
return False
|
233
|
-
if exists_pip_licenses:
|
234
|
-
pip_license_pkg_list.append(pip_licenses)
|
235
|
-
else:
|
236
|
-
uninstall_pkg_list.append(pip_licenses)
|
237
|
-
if exists_prettytable:
|
238
|
-
pip_license_pkg_list.append(prettytable)
|
239
|
-
else:
|
240
|
-
uninstall_pkg_list.append(prettytable)
|
241
|
-
if exists_wcwidth:
|
242
|
-
pip_license_pkg_list.append(wcwidth)
|
243
|
-
else:
|
244
|
-
uninstall_pkg_list.append(wcwidth)
|
245
|
-
|
246
211
|
command_list = []
|
247
212
|
command_list.append(activate_command)
|
248
|
-
if not exists_pip_licenses:
|
249
|
-
install_pip_command = f"{python_cmd} pip install {pip_licenses}"
|
250
|
-
command_list.append(install_pip_command)
|
251
|
-
|
252
|
-
pip_licenses_command = f"{pip_licenses}{pip_licenses_default_options} > {self.tmp_file_name}"
|
253
|
-
command_list.append(pip_licenses_command)
|
254
|
-
|
255
|
-
if len(pip_license_pkg_list) != 0:
|
256
|
-
pip_licenses_info_command = f"{pip_licenses}{pip_licenses_default_options}{pip_licenses_system_option}"
|
257
|
-
pip_licenses_info_command += " ".join(pip_license_pkg_list)
|
258
|
-
|
259
|
-
pip_licenses_info_command += f" > {self.tmp_pip_license_info_file_name}"
|
260
|
-
command_list.append(pip_licenses_info_command)
|
261
213
|
|
262
|
-
|
263
|
-
|
264
|
-
uninstall_pip_command += ' '.join(uninstall_pkg_list)
|
265
|
-
command_list.append(uninstall_pip_command)
|
214
|
+
pip_inspect_command = f"{python_cmd} pip inspect > {self.tmp_file_name}"
|
215
|
+
command_list.append(pip_inspect_command)
|
266
216
|
|
267
217
|
if not exists_pipdeptree:
|
268
218
|
install_deptree_command = f"{python_cmd} pip install {pipdeptree}"
|
@@ -270,30 +220,37 @@ class Pypi(PackageManager):
|
|
270
220
|
uninstall_deptree_command = f"{python_cmd} pip uninstall -y {pipdeptree}"
|
271
221
|
pipdeptree_command = f"{pipdeptree} --json-tree -e 'pipdeptree,pip,wheel,setuptools' > {self.tmp_deptree_file}"
|
272
222
|
command_list.append(pipdeptree_command)
|
273
|
-
|
223
|
+
|
224
|
+
if not exists_pipdeptree:
|
225
|
+
command_list.append(uninstall_deptree_command)
|
226
|
+
|
274
227
|
command_list.append(deactivate_command)
|
275
228
|
command = command_separator.join(command_list)
|
276
229
|
|
277
230
|
try:
|
278
231
|
cmd_ret = subprocess.call(command, shell=True)
|
279
232
|
if cmd_ret == 0:
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
233
|
+
if os.path.exists(self.tmp_file_name):
|
234
|
+
self.append_input_package_list_file(self.tmp_file_name)
|
235
|
+
|
236
|
+
with open(self.tmp_file_name, 'r', encoding='utf-8') as json_f:
|
237
|
+
inspect_data = json.load(json_f)
|
238
|
+
for package in inspect_data.get('installed', []):
|
239
|
+
metadata = package.get('metadata', {})
|
240
|
+
package_name = metadata.get('name', '')
|
241
|
+
if package_name:
|
242
|
+
if package_name in ['pip', 'setuptools']:
|
243
|
+
continue
|
244
|
+
self.total_dep_list.append(re.sub(r"[-_.]+", "-", package_name).lower())
|
245
|
+
else:
|
246
|
+
logger.error(f"pip inspect output file not found: {self.tmp_file_name}")
|
247
|
+
ret = False
|
291
248
|
else:
|
292
249
|
logger.error(f"Failed to run command: {command}")
|
293
250
|
ret = False
|
294
251
|
except Exception as e:
|
295
252
|
ret = False
|
296
|
-
logger.error(f"Failed to
|
253
|
+
logger.error(f"Failed to get package information using pip inspect: {e}")
|
297
254
|
|
298
255
|
return ret
|
299
256
|
|
@@ -302,25 +259,70 @@ class Pypi(PackageManager):
|
|
302
259
|
try:
|
303
260
|
oss_init_name = ''
|
304
261
|
with open(f_name, 'r', encoding='utf-8') as json_file:
|
305
|
-
|
262
|
+
inspect_data = json.load(json_file)
|
306
263
|
|
307
|
-
for
|
264
|
+
for package in inspect_data.get('installed', []):
|
308
265
|
dep_item = DependencyItem()
|
309
266
|
oss_item = OssItem()
|
310
|
-
|
267
|
+
metadata = package.get('metadata', {})
|
268
|
+
if not metadata:
|
269
|
+
continue
|
270
|
+
|
271
|
+
oss_init_name = metadata.get('name', '')
|
311
272
|
oss_init_name = re.sub(r"[-_.]+", "-", oss_init_name).lower()
|
273
|
+
if oss_init_name not in self.total_dep_list:
|
274
|
+
continue
|
312
275
|
oss_item.name = f"{self.package_manager_name}:{oss_init_name}"
|
313
|
-
|
314
|
-
|
315
|
-
|
276
|
+
oss_item.version = metadata.get('version', '')
|
277
|
+
|
278
|
+
# license_expression > license > classifier
|
279
|
+
license_info = check_UNKNOWN(metadata.get('license_expression', ''))
|
280
|
+
if not license_info:
|
281
|
+
license_info = metadata.get('license', '')
|
282
|
+
if '\n' in license_info:
|
283
|
+
license_info = check_UNKNOWN(check_license_name(license_info))
|
284
|
+
if not license_info:
|
285
|
+
classifiers = metadata.get('classifier', [])
|
286
|
+
license_classifiers = [c for c in classifiers if c.startswith('License ::')]
|
287
|
+
if license_classifiers:
|
288
|
+
license_info_l = []
|
289
|
+
for license_classifier in license_classifiers:
|
290
|
+
if license_classifier.startswith('License :: OSI Approved ::'):
|
291
|
+
license_info_l.append(license_classifier.split('::')[-1].strip())
|
292
|
+
break
|
293
|
+
license_info = ','.join(license_info_l)
|
294
|
+
license_name = check_UNKNOWN(license_info)
|
295
|
+
if license_name:
|
296
|
+
license_name = license_name.replace(';', ',')
|
297
|
+
oss_item.license = license_name
|
298
|
+
|
316
299
|
oss_item.download_location = f"{self.dn_url}{oss_init_name}/{oss_item.version}"
|
300
|
+
|
301
|
+
# project_url 'source' > download_url > project_url 'homepage' > homepage
|
302
|
+
homepage_url = check_UNKNOWN(metadata.get('home_page', ''))
|
303
|
+
download_url = check_UNKNOWN(metadata.get('download_url', ''))
|
304
|
+
project_urls = check_UNKNOWN(metadata.get('project_url', []))
|
305
|
+
if project_urls:
|
306
|
+
priority_order = ['source', 'repository', 'github', 'code', 'source code', 'homepage']
|
307
|
+
for priority in priority_order:
|
308
|
+
for url_entry in project_urls:
|
309
|
+
url_entry_lower = url_entry.lower()
|
310
|
+
if url_entry_lower.startswith(priority):
|
311
|
+
download_url = url_entry.split(', ')[-1]
|
312
|
+
break
|
313
|
+
if download_url:
|
314
|
+
break
|
315
|
+
oss_item.homepage = download_url or homepage_url or f"{self.dn_url}{oss_init_name}"
|
316
|
+
|
317
317
|
dep_item.purl = get_url_to_purl(oss_item.download_location, self.package_manager_name)
|
318
318
|
purl_dict[f'{oss_init_name}({oss_item.version})'] = dep_item.purl
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
319
|
+
|
320
|
+
direct_url = package.get('direct_url', {})
|
321
|
+
if direct_url:
|
322
|
+
oss_item.download_location = direct_url.get('url', '')
|
323
|
+
oss_item.homepage = oss_item.download_location
|
324
|
+
if not package.get('installer', ''):
|
325
|
+
oss_item.download_location = oss_item.homepage
|
324
326
|
|
325
327
|
if oss_init_name == self.package_name:
|
326
328
|
oss_item.comment = 'root package'
|
@@ -30,7 +30,7 @@ EXTENDED_HEADER = {_sheet_name: ['ID', 'Package URL', 'OSS Name',
|
|
30
30
|
'OSS Version', 'License', 'Download Location',
|
31
31
|
'Homepage', 'Copyright Text', 'Exclude',
|
32
32
|
'Comment', 'Depends On']}
|
33
|
-
_exclude_dir = ['
|
33
|
+
_exclude_dir = ['node_modules', 'venv', 'Pods', 'Carthage']
|
34
34
|
|
35
35
|
|
36
36
|
def get_terminal_size():
|
@@ -50,7 +50,7 @@ def paginate_file(file_path):
|
|
50
50
|
input("Press Enter to see the next page...")
|
51
51
|
|
52
52
|
|
53
|
-
def find_package_manager(input_dir, abs_path_to_exclude=[], manifest_file_name=[]):
|
53
|
+
def find_package_manager(input_dir, abs_path_to_exclude=[], manifest_file_name=[], recursive=False):
|
54
54
|
ret = True
|
55
55
|
if not manifest_file_name:
|
56
56
|
for value in const.SUPPORT_PACKAE.values():
|
@@ -62,9 +62,8 @@ def find_package_manager(input_dir, abs_path_to_exclude=[], manifest_file_name=[
|
|
62
62
|
found_manifest_file = []
|
63
63
|
suggested_files = []
|
64
64
|
for parent, dirs, files in os.walk(input_dir):
|
65
|
-
|
66
|
-
|
67
|
-
if os.path.basename(parent) in _exclude_dir:
|
65
|
+
parent_parts = parent.split(os.sep)
|
66
|
+
if any(ex_dir in parent_parts for ex_dir in _exclude_dir):
|
68
67
|
continue
|
69
68
|
if os.path.abspath(parent) in abs_path_to_exclude:
|
70
69
|
continue
|
@@ -75,7 +74,8 @@ def find_package_manager(input_dir, abs_path_to_exclude=[], manifest_file_name=[
|
|
75
74
|
for exclude_path in abs_path_to_exclude):
|
76
75
|
continue
|
77
76
|
if file in manifest_file_name:
|
78
|
-
|
77
|
+
path_with_filename = os.path.join(parent, file)
|
78
|
+
found_manifest_file.append(path_with_filename)
|
79
79
|
if file in const.SUGGESTED_PACKAGE.keys():
|
80
80
|
suggested_files.append(os.path.join(parent, file))
|
81
81
|
for dir in dirs:
|
@@ -84,31 +84,32 @@ def find_package_manager(input_dir, abs_path_to_exclude=[], manifest_file_name=[
|
|
84
84
|
if len(manifest_l) > 1:
|
85
85
|
if manifest_l[0] == dir:
|
86
86
|
if os.path.exists(os.path.join(parent, manifest_f)):
|
87
|
-
found_manifest_file.append(manifest_f)
|
88
|
-
if
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
87
|
+
found_manifest_file.append(os.path.join(parent, manifest_f))
|
88
|
+
if not recursive:
|
89
|
+
if len(found_manifest_file) > 0:
|
90
|
+
input_dir = parent
|
91
|
+
break
|
92
|
+
|
93
|
+
found_package_manager = defaultdict(lambda: defaultdict(list))
|
94
|
+
for f_with_path in found_manifest_file:
|
95
|
+
f_name = os.path.basename(f_with_path)
|
96
|
+
dir_path = os.path.dirname(f_with_path)
|
93
97
|
for key, value in const.SUPPORT_PACKAE.items():
|
94
98
|
if isinstance(value, list):
|
95
|
-
|
96
|
-
|
97
|
-
if key in found_package_manager.keys():
|
98
|
-
found_package_manager[key].append(f_idx)
|
99
|
-
else:
|
100
|
-
found_package_manager[key] = [f_idx]
|
99
|
+
if f_name in value:
|
100
|
+
found_package_manager[key][dir_path].append(f_name)
|
101
101
|
else:
|
102
|
-
if
|
103
|
-
found_package_manager[key]
|
102
|
+
if f_name == value:
|
103
|
+
found_package_manager[key][dir_path].append(f_name)
|
104
|
+
found_package_manager = {k: dict(v) for k, v in found_package_manager.items()}
|
104
105
|
|
105
106
|
# both npm and pnpm are detected, remove npm.
|
106
|
-
if 'npm' in found_package_manager and 'pnpm' in found_package_manager:
|
107
|
+
if 'npm' in found_package_manager.keys() and 'pnpm' in found_package_manager.keys():
|
107
108
|
del found_package_manager['npm']
|
108
109
|
if len(found_package_manager) >= 1:
|
109
|
-
|
110
|
-
|
111
|
-
logger.
|
110
|
+
log_lines = ["\nDetected Manifest Files automatically"]
|
111
|
+
log_lines = print_package_info(found_package_manager, log_lines)
|
112
|
+
logger.info('\n'.join(log_lines))
|
112
113
|
else:
|
113
114
|
ret = False
|
114
115
|
logger.info("Cannot find the manifest file.")
|
@@ -116,10 +117,20 @@ def find_package_manager(input_dir, abs_path_to_exclude=[], manifest_file_name=[
|
|
116
117
|
return ret, found_package_manager, input_dir, suggested_files
|
117
118
|
|
118
119
|
|
120
|
+
def print_package_info(success_pm, log_lines):
|
121
|
+
if success_pm:
|
122
|
+
for pm, dir_dict in success_pm.items():
|
123
|
+
log_lines.append(f"- {pm}:")
|
124
|
+
for path, files in dir_dict.items():
|
125
|
+
file_list = ', '.join(files)
|
126
|
+
log_lines.append(f" {path}: {file_list}")
|
127
|
+
return log_lines
|
128
|
+
|
129
|
+
|
119
130
|
def run_dependency_scanner(package_manager='', input_dir='', output_dir_file='', pip_activate_cmd='',
|
120
131
|
pip_deactivate_cmd='', output_custom_dir='', app_name=const.default_app_name,
|
121
132
|
github_token='', formats=[], direct=True, path_to_exclude=[], graph_path='',
|
122
|
-
graph_size=(600, 600)):
|
133
|
+
graph_size=(600, 600), recursive=False):
|
123
134
|
global logger
|
124
135
|
|
125
136
|
ret = True
|
@@ -217,9 +228,8 @@ def run_dependency_scanner(package_manager='', input_dir='', output_dir_file='',
|
|
217
228
|
try:
|
218
229
|
ret, found_package_manager, input_dir, suggested_files = find_package_manager(input_dir,
|
219
230
|
abs_path_to_exclude,
|
220
|
-
manifest_file_name
|
221
|
-
|
222
|
-
os.chdir(input_dir)
|
231
|
+
manifest_file_name,
|
232
|
+
recursive)
|
223
233
|
except Exception as e:
|
224
234
|
if autodetect:
|
225
235
|
logger.error(f'Fail to find package manager: {e}')
|
@@ -228,7 +238,7 @@ def run_dependency_scanner(package_manager='', input_dir='', output_dir_file='',
|
|
228
238
|
if not ret:
|
229
239
|
if not autodetect:
|
230
240
|
logger.info('Try to analyze dependency without manifest file. (Manual mode)')
|
231
|
-
found_package_manager[package_manager] =
|
241
|
+
found_package_manager[package_manager] = {}
|
232
242
|
else:
|
233
243
|
ret = False
|
234
244
|
if suggested_files:
|
@@ -243,40 +253,64 @@ def run_dependency_scanner(package_manager='', input_dir='', output_dir_file='',
|
|
243
253
|
else:
|
244
254
|
scan_item.set_cover_comment("No Package manager detected.")
|
245
255
|
|
246
|
-
pass_key = 'PASS'
|
247
|
-
success_pm =
|
248
|
-
fail_pm =
|
256
|
+
pass_key = ['PASS']
|
257
|
+
success_pm = defaultdict(lambda: defaultdict(list))
|
258
|
+
fail_pm = defaultdict(lambda: defaultdict(list))
|
249
259
|
cover_comment = ''
|
250
|
-
for pm,
|
251
|
-
if
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
if const.ANDROID in found_package_manager.keys():
|
262
|
-
found_package_manager[const.ANDROID] = pass_key
|
263
|
-
if f"{const.ANDROID} ({', '.join(manifest_file_name)})" in fail_pm:
|
264
|
-
fail_pm.remove(f"{const.ANDROID} ({', '.join(manifest_file_name)})")
|
265
|
-
elif pm == const.ANDROID:
|
266
|
-
if const.GRADLE in found_package_manager.keys():
|
267
|
-
found_package_manager[const.GRADLE] = pass_key
|
268
|
-
if f"{const.GRADLE} ({', '.join(manifest_file_name)})" in fail_pm:
|
269
|
-
fail_pm.remove(f"{const.GRADLE} ({', '.join(manifest_file_name)})")
|
260
|
+
for pm, manifest_file_name_list in found_package_manager.items():
|
261
|
+
if not manifest_file_name_list and not autodetect:
|
262
|
+
ret, package_dep_item_list, cover_comment = analyze_dependency(pm, input_dir, output_path,
|
263
|
+
pip_activate_cmd, pip_deactivate_cmd,
|
264
|
+
output_custom_dir, app_name, github_token,
|
265
|
+
[], direct)
|
266
|
+
if ret:
|
267
|
+
success_pm[pm][input_dir].extend(['manual mode (-m option)'])
|
268
|
+
scan_item.append_file_items(package_dep_item_list)
|
269
|
+
else:
|
270
|
+
fail_pm[pm][input_dir].extend(['manual mode (-m option)'])
|
270
271
|
else:
|
271
|
-
|
272
|
+
for manifest_dir, manifest_file_name in manifest_file_name_list.items():
|
273
|
+
input_dir = manifest_dir
|
274
|
+
if manifest_file_name == pass_key:
|
275
|
+
continue
|
276
|
+
os.chdir(input_dir)
|
277
|
+
ret, package_dep_item_list, cover_comment = analyze_dependency(pm, input_dir, output_path,
|
278
|
+
pip_activate_cmd, pip_deactivate_cmd,
|
279
|
+
output_custom_dir, app_name, github_token,
|
280
|
+
manifest_file_name, direct)
|
281
|
+
if ret:
|
282
|
+
success_pm[pm][input_dir].extend(manifest_file_name)
|
283
|
+
scan_item.append_file_items(package_dep_item_list)
|
284
|
+
|
285
|
+
dup_pm = None
|
286
|
+
if pm == const.GRADLE and const.ANDROID in found_package_manager:
|
287
|
+
dup_pm = const.ANDROID
|
288
|
+
elif pm == const.ANDROID and const.GRADLE in found_package_manager:
|
289
|
+
dup_pm = const.GRADLE
|
290
|
+
|
291
|
+
if dup_pm:
|
292
|
+
if dup_pm in fail_pm and input_dir in fail_pm[dup_pm]:
|
293
|
+
fail_pm[dup_pm].pop(input_dir, None)
|
294
|
+
if not fail_pm[dup_pm]:
|
295
|
+
fail_pm.pop(dup_pm, None)
|
296
|
+
else:
|
297
|
+
found_package_manager[dup_pm][manifest_dir] = pass_key
|
298
|
+
else:
|
299
|
+
fail_pm[pm][input_dir].extend(manifest_file_name)
|
272
300
|
|
301
|
+
success_pm = {k: dict(v) for k, v in success_pm.items()}
|
302
|
+
fail_pm = {k: dict(v) for k, v in fail_pm.items()}
|
273
303
|
if len(found_package_manager.keys()) > 0:
|
274
304
|
if len(success_pm) > 0:
|
275
|
-
|
305
|
+
log_lines = ["Success to analyze:"]
|
306
|
+
log_lines = print_package_info(success_pm, log_lines)
|
307
|
+
scan_item.set_cover_comment('\n'.join(log_lines))
|
276
308
|
if len(fail_pm) > 0:
|
277
|
-
|
278
|
-
|
279
|
-
scan_item.set_cover_comment(
|
309
|
+
log_lines = ["Fail to analyze:"]
|
310
|
+
log_lines = print_package_info(fail_pm, log_lines)
|
311
|
+
scan_item.set_cover_comment('\n'.join(log_lines))
|
312
|
+
scan_item.set_cover_comment('Check log file(fosslight_log*.txt) '
|
313
|
+
'and https://fosslight.org/fosslight-guide-en/scanner/3_dependency.html#-prerequisite.')
|
280
314
|
|
281
315
|
if ret and graph_path:
|
282
316
|
graph_path = os.path.abspath(graph_path)
|
@@ -335,6 +369,7 @@ def main():
|
|
335
369
|
graph_path = ''
|
336
370
|
graph_size = (600, 600)
|
337
371
|
direct = True
|
372
|
+
recursive = False
|
338
373
|
|
339
374
|
parser = argparse.ArgumentParser(add_help=False)
|
340
375
|
parser.add_argument('-h', '--help', action='store_true', required=False)
|
@@ -353,6 +388,7 @@ def main():
|
|
353
388
|
parser.add_argument('--graph-size', nargs=2, type=int, metavar=("WIDTH", "HEIGHT"), required=False)
|
354
389
|
parser.add_argument('--direct', choices=('true', 'false'), default='True', required=False)
|
355
390
|
parser.add_argument('--notice', action='store_true', required=False)
|
391
|
+
parser.add_argument('-r', '--recursive', action='store_true', required=False)
|
356
392
|
|
357
393
|
args = parser.parse_args()
|
358
394
|
|
@@ -405,10 +441,12 @@ def main():
|
|
405
441
|
paginate_file(source_file)
|
406
442
|
shutil.copyfile(source_file, destination_file)
|
407
443
|
sys.exit(0)
|
444
|
+
if args.recursive: # -r option
|
445
|
+
recursive = True
|
408
446
|
|
409
447
|
run_dependency_scanner(package_manager, input_dir, output_dir, pip_activate_cmd, pip_deactivate_cmd,
|
410
448
|
output_custom_dir, app_name, github_token, format, direct, path_to_exclude,
|
411
|
-
graph_path, graph_size)
|
449
|
+
graph_path, graph_size, recursive)
|
412
450
|
|
413
451
|
|
414
452
|
if __name__ == '__main__':
|
@@ -1,19 +1,22 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: fosslight-dependency
|
3
|
-
Version: 4.1.
|
3
|
+
Version: 4.1.20
|
4
4
|
Summary: FOSSLight Dependency Scanner
|
5
5
|
Home-page: https://github.com/fosslight/fosslight_dependency_scanner
|
6
|
+
Download-URL: https://github.com/fosslight/fosslight_dependency_scanner
|
6
7
|
Author: LG Electronics
|
7
8
|
License: Apache-2.0
|
8
|
-
Download-URL: https://github.com/fosslight/fosslight_dependency_scanner
|
9
|
-
Platform: UNKNOWN
|
10
9
|
Classifier: License :: OSI Approved :: Apache Software License
|
11
10
|
Classifier: Programming Language :: Python :: 3
|
12
|
-
Classifier: Programming Language :: Python :: 3.8
|
13
|
-
Classifier: Programming Language :: Python :: 3.9
|
14
11
|
Classifier: Programming Language :: Python :: 3.10
|
15
12
|
Classifier: Programming Language :: Python :: 3.11
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
14
|
+
Requires-Python: >=3.10,<3.13
|
16
15
|
Description-Content-Type: text/markdown
|
16
|
+
License-File: LICENSE
|
17
|
+
License-File: LICENSES/Apache-2.0.txt
|
18
|
+
License-File: LICENSES/LicenseRef-3rd_party_licenses.txt
|
19
|
+
License-File: LICENSES/MIT.txt
|
17
20
|
Requires-Dist: openpyxl
|
18
21
|
Requires-Dist: beautifulsoup4
|
19
22
|
Requires-Dist: lxml
|
@@ -190,5 +193,3 @@ Please see the [CONTRIBUTING guide](https://github.com/fosslight/fosslight_depen
|
|
190
193
|
|
191
194
|
Copyright (c) 2020 LG Electronics, Inc.
|
192
195
|
FOSSLight Dependency Scanner is licensed under Apache-2.0, as found in the [LICENSE](https://github.com/fosslight/fosslight_dependency_scanner/blob/main/LICENSE) file.
|
193
|
-
|
194
|
-
|
@@ -1,11 +1,11 @@
|
|
1
1
|
fosslight_dependency/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
-
fosslight_dependency/_analyze_dependency.py,sha256=
|
2
|
+
fosslight_dependency/_analyze_dependency.py,sha256=oJ_6gka5V8cdafxoiQhgepGDnjO5EVM9JX4AdBacMzw,4707
|
3
3
|
fosslight_dependency/_graph_convertor.py,sha256=D8GwmJfuj9Wg3_DeKRPLGGdyHSLcoU2Q0VzKQbkJG4g,2267
|
4
|
-
fosslight_dependency/_help.py,sha256=
|
5
|
-
fosslight_dependency/_package_manager.py,sha256=
|
4
|
+
fosslight_dependency/_help.py,sha256=wt7M6wnyJJr-RIQ1pvMceevpGAKCSTQsAlGiKOXMQUE,3595
|
5
|
+
fosslight_dependency/_package_manager.py,sha256=mN1ukEmZkm6COhxWm-mVfhCZkHppfFgXyXzBT1x02Sw,15016
|
6
6
|
fosslight_dependency/constant.py,sha256=5upuTFSTmmQwqv2u-MRcEG4lxaIZAIi_c-rAPhOrsfM,1226
|
7
7
|
fosslight_dependency/dependency_item.py,sha256=wNLWcsNycf3HQ5Pib2WrMeo2dn0eHCRg20NLcL95Qew,3345
|
8
|
-
fosslight_dependency/run_dependency_scanner.py,sha256=
|
8
|
+
fosslight_dependency/run_dependency_scanner.py,sha256=1F9zrKd4VjeXI9l5M-ZW0qxq-Cf27u8u7_aw8l_O7vQ,20406
|
9
9
|
fosslight_dependency/LICENSES/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
10
10
|
fosslight_dependency/LICENSES/LicenseRef-3rd_party_licenses.txt,sha256=EcsFt7aE1rp3OXAdJgmXayfOZdpRdBMcmRnyoqWMCsw,95687
|
11
11
|
fosslight_dependency/package_manager/Android.py,sha256=0UZFvbLxDIreerK4fR316YPyhUpPliV_kfZulrxkUyo,3218
|
@@ -16,20 +16,20 @@ fosslight_dependency/package_manager/Go.py,sha256=eEWvPoE3Jd0lMJAxWMNdFcoi21fJF0
|
|
16
16
|
fosslight_dependency/package_manager/Gradle.py,sha256=IYmj9q3XiE_DPKdtll6lyRr98lFuyKWW2qz57X26Fn0,4359
|
17
17
|
fosslight_dependency/package_manager/Helm.py,sha256=ucx2Y0tWX37UHIzIGaRyTe7uQ2vlu2nUuO09hOMq9ZU,4223
|
18
18
|
fosslight_dependency/package_manager/Maven.py,sha256=vAiBEAEGQD5eaFGVSLmrZ8AAtoz_IuTmhaWuPTmsku0,10503
|
19
|
-
fosslight_dependency/package_manager/Npm.py,sha256=
|
19
|
+
fosslight_dependency/package_manager/Npm.py,sha256=1ILIBYiU1gwi6yTbc4GSyjYf7omChoBntUBf_SnyBGU,10845
|
20
20
|
fosslight_dependency/package_manager/Nuget.py,sha256=u4w084Qozk4nrVdT4o_nDiT8v4URIlXaOrDh11Hu1Bw,8885
|
21
21
|
fosslight_dependency/package_manager/Pnpm.py,sha256=LDKooFGQHui_Q5U7XqSJ8KcCPiLVndXf5oGKTJExh5w,7056
|
22
22
|
fosslight_dependency/package_manager/Pub.py,sha256=Rrz8_6wdrmMU6f3vbbuAwyMbODBauXNnBbI619OQgDk,10184
|
23
|
-
fosslight_dependency/package_manager/Pypi.py,sha256=
|
23
|
+
fosslight_dependency/package_manager/Pypi.py,sha256=Iko_MGEBPrYr1I2-430bG4mkAwFqTUPpjWWKfJ9SM1c,17178
|
24
24
|
fosslight_dependency/package_manager/Swift.py,sha256=8fdbdAXTNlp2NDoSqQXm48JGAg9UhxA91M1-NhHkT40,6752
|
25
25
|
fosslight_dependency/package_manager/Unity.py,sha256=n1006GZ6Qrk8wAdO6wla1Q-JD7Evin7REVj-HDeTARc,5142
|
26
26
|
fosslight_dependency/package_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
27
|
-
fosslight_dependency-4.1.
|
28
|
-
fosslight_dependency-4.1.
|
29
|
-
fosslight_dependency-4.1.
|
30
|
-
fosslight_dependency-4.1.
|
31
|
-
fosslight_dependency-4.1.
|
32
|
-
fosslight_dependency-4.1.
|
33
|
-
fosslight_dependency-4.1.
|
34
|
-
fosslight_dependency-4.1.
|
35
|
-
fosslight_dependency-4.1.
|
27
|
+
fosslight_dependency-4.1.20.dist-info/Apache-2.0.txt,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
28
|
+
fosslight_dependency-4.1.20.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
29
|
+
fosslight_dependency-4.1.20.dist-info/LicenseRef-3rd_party_licenses.txt,sha256=EcsFt7aE1rp3OXAdJgmXayfOZdpRdBMcmRnyoqWMCsw,95687
|
30
|
+
fosslight_dependency-4.1.20.dist-info/METADATA,sha256=9FAGK-KEqZOfJJUntY_zcvBL6Pjf-kTakBdTSrrZtEE,5213
|
31
|
+
fosslight_dependency-4.1.20.dist-info/MIT.txt,sha256=9cx4CbArgByWvkoEZNqpzbpJgA9TUe2D62rMocQpgfs,1082
|
32
|
+
fosslight_dependency-4.1.20.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
|
33
|
+
fosslight_dependency-4.1.20.dist-info/entry_points.txt,sha256=AeU-9Bl8al8Sa-XvhitGHdT3ZTPIrlhqADcp7s5OLF8,90
|
34
|
+
fosslight_dependency-4.1.20.dist-info/top_level.txt,sha256=Jc0V7VcVCH0TEM8ksb8dwroTYz4AmRaQnlr3FB71Hcs,21
|
35
|
+
fosslight_dependency-4.1.20.dist-info/RECORD,,
|
{fosslight_dependency-4.1.18.dist-info → fosslight_dependency-4.1.20.dist-info}/Apache-2.0.txt
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{fosslight_dependency-4.1.18.dist-info → fosslight_dependency-4.1.20.dist-info}/top_level.txt
RENAMED
File without changes
|