fix: replace removed distutils.spawn with shutil.which (Python 3.12+) - #402
Conversation
distutils was removed from the standard library in Python 3.12, so ovos_utils.sound and ovos_utils.device_input fail to import with ModuleNotFoundError: No module named 'distutils'. shutil.which is a drop-in stdlib replacement for distutils.spawn.find_executable. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Warning Review limit reached
Next review available in: 56 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
The automated sentinels have completed their watch. 💂♂️I've aggregated the results of the automated checks for this PR below. 🔍 LintI've gathered the facts for your review. 📖 ❌ ruff: issues found — see job log 🏷️ Release PreviewThe release train is fueling up! 🚂 Current:
✅ PR title follows conventional commit format. 🚀 Release Channel Compatibility Predicted next version:
⚖️ License CheckI've checked the licenses of all dev-dependencies too. 🛠️ ✅ No license violations found. Policy: Apache 2.0 (universal donor). StrongCopyleft / NetworkCopyleft / WeakCopyleft / Other / Error categories fail. MPL allowed. 🔒 Security (pip-audit)The security scan is now complete. 🏁 ✅ No known vulnerabilities found (47 packages scanned). 📊 CoverageA forensic look at what's being executed. 🔎 ✅ 85.2% total coverage Files below 80% coverage (5 files)
Full report: download the 📋 Repo HealthChecking if we're following maintenance best practices. 📏 ✅ All required files present. Latest Version: ✅ 🔨 Build TestsThe build pipeline has finished its work. 🏁 ✅ All versions pass
Standard Automated Signature v2.0 🏷️ |
Problem
distutilswas removed from the Python standard library in 3.12. This breaks import of two modules that still use it:Affected modules:
ovos_utils.sound— usesdistutils.spawn.find_executableto locate audio players (play,ogg123,pw-play,paplay,aplay,mpg123) and media probes (ffprobe,mediainfo)ovos_utils.device_input— usesdistutils.spawn.find_executableto locatelibinput/xinputBoth modules fail to import at all on Python 3.12+.
Fix
Replace
from distutils.spawn import find_executablewithfrom shutil import which, and everyfind_executable(...)call withwhich(...).shutil.whichis the stdlib replacement recommended for this exact use case (same signature/behavior: returns the resolved path orNone).Existing unit tests (
test/unittests/test_sound.py,test/unittests/test_device_input.py) patchedfind_executableby name, so those mock targets were updated towhichas well. No behavior changes.Test plan
ast.parsesanity check on both edited modulesgrep -r distutils ovos_utils/returns nothingpytest test/unittests/test_sound.py test/unittests/test_device_input.py— 39 passedThis fix was authored with Claude Code.