[FIX] Replace statsmodels.robust.scale.mad with scipy.stats.median_abs_deviation to avoid enabling the GIL - #126
[FIX] Replace statsmodels.robust.scale.mad with scipy.stats.median_abs_deviation to avoid enabling the GIL#126pvlov wants to merge 1 commit into
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #126 +/- ##
==========================================
- Coverage 83.29% 83.28% -0.01%
==========================================
Files 25 25
Lines 2861 2860 -1
==========================================
- Hits 2383 2382 -1
Misses 478 478 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
Hi @pvlov thanks for this! Perfectly fine to open PRs here :) |
There was a problem hiding this comment.
Pull request overview
This PR removes the statsmodels dependency (which can re-enable the GIL under free-threaded CPython) by replacing the one usage of statsmodels.robust.scale.mad with scipy.stats.median_abs_deviation, and adds CI/test coverage to ensure importing meegkit does not re-enable the GIL on free-threaded builds.
Changes:
- Replace
statsmodels.robust.scale.madwithscipy.stats.median_abs_deviationin ASR window cleaning logic. - Drop
statsmodelsfromrequirements.txt. - Add a free-threaded-only test plus extend CI to run on
3.14and3.14t.
Reviewed changes
Copilot reviewed 3 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
meegkit/asr.py |
Replaces MAD implementation to avoid importing statsmodels (prevents triggering GIL enablement). |
requirements.txt |
Removes the statsmodels runtime dependency. |
tests/test_freethreading.py |
Adds a subprocess-based import test to verify GIL remains disabled on free-threaded CPython. |
.github/workflows/testing.yml |
Expands the Python matrix to include 3.14 and 3.14t. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| pytestmark = pytest.mark.skipif( | ||
| not sysconfig.get_config_var("Py_GIL_DISABLED"), | ||
| reason="requires a free-threaded CPython build", | ||
| ) |
There was a problem hiding this comment.
I know LLMs like their defensive coding but I wanted to make sure I'm not making any false assumptions, so I dug into cpython a bit.
First, if we have a look at sysconfig's documentation we can see that get_config_var will return genuine python ints for boolean values:
>>> import sysconfig
>>> sysconfig.get_config_var('Py_ENABLE_SHARED')
0
...Next, if we check the implementation of the sysconfig module in cpython, we can see that it does genuinely parse "int-like" values into python ints, unless it is forced to stay a str as per the set _ALWAYS_STR, which does not apply to Py_GIL_DISABLED. Further, undefs for config values set the config_var to 0 and for cypthons builds the build value for true is 1 so this is fine as well. So imo this is unnecessarily defensive.
…s_deviation to avoid enabling the GIL and remove statsmodels from dependencies
Hi! Since this is a small diff and I couldn't find a
CONTRIBUTING.md, I went ahead and opened a PR. I hope you don't mind!I wanted to use
meegkitin a project that uses a free-threaded Python interpreter, but I ran into the following warning:You can replicate this warning (using uv) with this command:
uv run --no-project --python 3.14t --with statsmodels python -c "import statsmodels.robust.scale"I checked where/how
statsmodelsis used and found only one occurrence:statsmodels.robust.scale.mad. This PR replaces it with the equivalentscipy.stats.median_abs_deviation. This makes the package usable in free-threaded contexts while also dropping thestatsmodelsdependency entirely.Additionally, I added a test using the built-in
sys._is_gil_enabledcheck to confirm the GIL stays disabled, and added3.14and3.14tto the CI python matrix. Let me know if you want to keep this or if I should drop this.