-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
[BUG] Fix infinite recursion in _SuppressWarningPattern
and LossySetitemError
in SummaryTransformer
#7903
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
ae76696
to
a1a1417
Compare
a1a1417
to
e5ae331
Compare
…n SummaryTransformer
e5ae331
to
c7c2075
Compare
Thanks for the fix! Failure occurs on main, so I would recommend a quick merge. |
I am not sure, if this is completely fixing the issue. I think it is related to some kind of race-condition see #7906 because of the threading backend used in some tests. If this is true, we need some kind of thread safe solution, i.e., guard this not only by a flag but by a lock. |
Can we somehow test that this is a fix? It does not seem too clear how we would establish the condition in a test. |
Not sure if this should be implemented in a test case. But you might check it using the following lines of code: import time
import warnings
import joblib
from sktime.utils.warnings import _suppress_pd22_warning
def f(set_warning):
if set_warning:
with warnings.catch_warnings():
with _suppress_pd22_warning:
time.sleep(2)
#warnings.warn("'HI' is deprecated and will be removed in a future version, please use 'HELLO' instead", category=FutureWarning)
warnings.warn("'HI' is deprecated and will be removed in a future version, please use 'HELLO' instead" + str(set_warning), category=FutureWarning)
if __name__ == "__main__":
joblib.Parallel(n_jobs=2, backend="threading")(joblib.delayed(f)(set_warning) for set_warning in [True, False]) This should print the warning two times (for both threads). But it is only printing the warning once. (Compare with multiprocessing, there the warning is printed two times). I checked it on this branch and it is only printing the warning once. EDIT |
@benHeid, but is the race condition addressed? |
No printing the warning once means the race condition is not adressed. Since the warning of thread 2 (with parameter false) is not printed, because thread 1 is inside of the with statement and replaced the show warning by entering the with statement. |
@fkiraly would it be possible to use the following statement everywhere were we use with warnings.catch_warnings():
warnings.filterwarnings("ignore",
category=FutureWarning,
message=r"'[A-Z]+' is deprecated and will be removed in a future version, please use '[A-Z]+' instead")
This statement would not change the warning module globally and it seem to work. But would appreciate confirmation by someone else. |
that would work. Conjecture: using the same class causes the race condition. Turning the static def _suppress_pd22_warning():
return _SuppressWarningPattern(
FutureWarning,
r"'[A-Z]+' is deprecated and will be removed in a future version, please use '[A-Z]+' instead", # noqa
) and replacing |
Proposed fix: #7910 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the fix in #7910 is the solution - thanks for the fix, I think it put us on the right track.
What I suggest is adding the tests only; I also notice the fix gets the filter removed, I will restore that. I will take care of this and credit you for the fix.
Regarding the fix - should we also replace the internals with catch_warnings
?
Thanks @fkiraly and @benHeid for the feedback! I'm glad my correction helped point you to a solution. I see that #7910 seems like a good way to handle the threaded warnings issue, and I agree that you could edit my PR to restore the old filter code in I'm looking forward to seeing how it turns out! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed the environment to dispatch to warnings.filterwarnings
.
@celestinoxp, would you be able to check whether this still addresses your use case?
_SuppressWarningPattern
and LossySetitemError
in SummaryTransformer
@benHeid, I checked your code - this PR seems to fix the infinite loop if the race condition occurs, but, unfortunately, not the race conidition itself. I would hence go and merge this, and we leave the issue with the race condition open. |
…etitemError` in `SummaryTransformer` (sktime#7903) ### Issue The `_custom_showwarning` method in `sktime/utils/warnings.py` causes infinite recursion when handling certain warnings (e.g., pandas `LossySetitemError`), resulting in a `RecursionError: maximum recursion depth exceeded`. Additionally, in `sktime/transformations/series/summarize.py`, the line `func_dict.loc[:, "window"] = func_dict["window"].astype("object")` throws a `LossySetitemError` in pandas 2.x due to incompatible type coercion. This issue was identified while using PyCaret with sktime, where tests failed with a crash in a joblib worker due to a `PicklingError` caused by excessive recursion. ### Solution - Modified the `_custom_showwarning` method in the `_SuppressWarningPattern` class to add a guard against recursion using an `_in_warning` flag, while preserving delegation to `original_showwarning`. - Fixed `SummaryTransformer` to use a type-safe conversion with `func_dict["window"] = func_dict["window"].astype("object", copy=False)`, avoiding the `LossySetitemError`. ### Changes - `sktime/utils/warnings.py`: Added protection against infinite recursion in the `_custom_showwarning` method of `_SuppressWarningPattern` using an `_in_warning` flag. - `sktime/transformations/series/summarize.py`: Replaced the problematic assignment with an explicit conversion of the `"window"` column to `object` using `copy=False` for greater efficiency. - `sktime/utils/tests/test_warnings.py`: Added a new test file to verify that `_custom_showwarning` in `_SuppressWarningPattern` emits warnings without recursion. - `sktime/transformations/series/tests/test_summarize.py`: Added a new test `test_summarize_no_lossy_setitem` to confirm that `SummaryTransformer.fit` does not raise `LossySetitemError`. ### Related - Investigated in PyCaret PR [sktime#4150](pycaret/pycaret#4150) ### Verification Tested locally with PyCaret and sktime, resolving the crash in the `test_blend_model_predict` test. The change in `summarize.py` ensures compatibility with pandas 2.x while maintaining efficiency with `copy=False`.
…etitemError` in `SummaryTransformer` (sktime#7903) ### Issue The `_custom_showwarning` method in `sktime/utils/warnings.py` causes infinite recursion when handling certain warnings (e.g., pandas `LossySetitemError`), resulting in a `RecursionError: maximum recursion depth exceeded`. Additionally, in `sktime/transformations/series/summarize.py`, the line `func_dict.loc[:, "window"] = func_dict["window"].astype("object")` throws a `LossySetitemError` in pandas 2.x due to incompatible type coercion. This issue was identified while using PyCaret with sktime, where tests failed with a crash in a joblib worker due to a `PicklingError` caused by excessive recursion. ### Solution - Modified the `_custom_showwarning` method in the `_SuppressWarningPattern` class to add a guard against recursion using an `_in_warning` flag, while preserving delegation to `original_showwarning`. - Fixed `SummaryTransformer` to use a type-safe conversion with `func_dict["window"] = func_dict["window"].astype("object", copy=False)`, avoiding the `LossySetitemError`. ### Changes - `sktime/utils/warnings.py`: Added protection against infinite recursion in the `_custom_showwarning` method of `_SuppressWarningPattern` using an `_in_warning` flag. - `sktime/transformations/series/summarize.py`: Replaced the problematic assignment with an explicit conversion of the `"window"` column to `object` using `copy=False` for greater efficiency. - `sktime/utils/tests/test_warnings.py`: Added a new test file to verify that `_custom_showwarning` in `_SuppressWarningPattern` emits warnings without recursion. - `sktime/transformations/series/tests/test_summarize.py`: Added a new test `test_summarize_no_lossy_setitem` to confirm that `SummaryTransformer.fit` does not raise `LossySetitemError`. ### Related - Investigated in PyCaret PR [sktime#4150](pycaret/pycaret#4150) ### Verification Tested locally with PyCaret and sktime, resolving the crash in the `test_blend_model_predict` test. The change in `summarize.py` ensures compatibility with pandas 2.x while maintaining efficiency with `copy=False`.
Issue
The
_custom_showwarning
method insktime/utils/warnings.py
causes infinite recursion when handling certain warnings (e.g., pandasLossySetitemError
), resulting in aRecursionError: maximum recursion depth exceeded
. Additionally, insktime/transformations/series/summarize.py
, the linefunc_dict.loc[:, "window"] = func_dict["window"].astype("object")
throws aLossySetitemError
in pandas 2.x due to incompatible type coercion.This issue was identified while using PyCaret with sktime, where tests failed with a crash in a joblib worker due to a
PicklingError
caused by excessive recursion.Solution
_custom_showwarning
method in the_SuppressWarningPattern
class to add a guard against recursion using an_in_warning
flag, while preserving delegation tooriginal_showwarning
.SummaryTransformer
to use a type-safe conversion withfunc_dict["window"] = func_dict["window"].astype("object", copy=False)
, avoiding theLossySetitemError
.Changes
sktime/utils/warnings.py
: Added protection against infinite recursion in the_custom_showwarning
method of_SuppressWarningPattern
using an_in_warning
flag.sktime/transformations/series/summarize.py
: Replaced the problematic assignment with an explicit conversion of the"window"
column toobject
usingcopy=False
for greater efficiency.sktime/utils/tests/test_warnings.py
: Added a new test file to verify that_custom_showwarning
in_SuppressWarningPattern
emits warnings without recursion.sktime/transformations/series/tests/test_summarize.py
: Added a new testtest_summarize_no_lossy_setitem
to confirm thatSummaryTransformer.fit
does not raiseLossySetitemError
.Related
Verification
Tested locally with PyCaret and sktime, resolving the crash in the
test_blend_model_predict
test. The change insummarize.py
ensures compatibility with pandas 2.x while maintaining efficiency withcopy=False
.