Get the system's operating system, Python, packages, and external tool versions. Useful for debugging or filing bug reports. Used for the `scenedetect version -a` command.
()
| 338 | |
| 339 | |
| 340 | def get_system_version_info() -> str: |
| 341 | """Get the system's operating system, Python, packages, and external tool versions. |
| 342 | Useful for debugging or filing bug reports. |
| 343 | |
| 344 | Used for the `scenedetect version -a` command. |
| 345 | """ |
| 346 | line_separator = "-" * 60 |
| 347 | not_found_str = "Not Installed" |
| 348 | out_lines = [] |
| 349 | |
| 350 | system_info = ( |
| 351 | ("OS", f"{platform.platform()}"), |
| 352 | ("Python", f"{platform.python_implementation()} {platform.python_version()}"), |
| 353 | ("Architecture", " + ".join(platform.architecture())), |
| 354 | ) |
| 355 | |
| 356 | # Third-Party Packages: queried via PyPI distribution names with a module-attribute |
| 357 | # fallback. PyInstaller bundles ship the modules but not the `.dist-info` metadata |
| 358 | # directories, so `importlib.metadata.version()` alone reports "Not Installed" for |
| 359 | # every package in a frozen build; reading `module.__version__` recovers the version |
| 360 | # there. `scenedetect` is read from the package attribute since it must report a |
| 361 | # version even when run uninstalled (e.g. from a source checkout). The import is |
| 362 | # deferred to avoid a circular import at module load time. |
| 363 | from scenedetect import __version__ as scenedetect_version |
| 364 | |
| 365 | # (dist_name, fallback_module_name). Module fallback is only used when metadata is |
| 366 | # missing, so the metadata path still distinguishes `opencv-python` vs |
| 367 | # `opencv-python-headless` in source installs. In the frozen Windows build only |
| 368 | # `opencv-python-headless` is shipped, so `cv2` is attributed to that row alone. |
| 369 | third_party_packages = ( |
| 370 | ("av", "av"), |
| 371 | ("click", "click"), |
| 372 | ("opencv-python", None), |
| 373 | ("opencv-python-headless", "cv2"), |
| 374 | ("imageio", "imageio"), |
| 375 | ("imageio-ffmpeg", "imageio_ffmpeg"), |
| 376 | ("moviepy", "moviepy"), |
| 377 | ("numpy", "numpy"), |
| 378 | ("platformdirs", "platformdirs"), |
| 379 | ("tqdm", "tqdm"), |
| 380 | ) |
| 381 | package_versions = [("scenedetect", scenedetect_version)] + [ |
| 382 | (dist_name, _query_package_version(dist_name, fallback_module) or not_found_str) |
| 383 | for dist_name, fallback_module in third_party_packages |
| 384 | ] |
| 385 | |
| 386 | tool_versions = ( |
| 387 | ("ffmpeg", get_ffmpeg_version() or not_found_str), |
| 388 | ("mkvmerge", get_mkvmerge_version() or not_found_str), |
| 389 | ) |
| 390 | |
| 391 | # Size the label column to the longest label across every section so all three tables |
| 392 | # align consistently - `opencv-python-headless` exceeds the previous fixed width of 16. |
| 393 | label_width = max(len(name) for name, _ in (*system_info, *package_versions, *tool_versions)) |
| 394 | output_template = f"{{:<{label_width}}} {{}}" |
| 395 | |
| 396 | out_lines += ["System Info", line_separator] |
| 397 | out_lines += [output_template.format(name, value) for name, value in system_info] |
no test coverage detected